日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

SpringMVC学习笔记整理

發(fā)布時(shí)間:2023/12/1 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringMVC学习笔记整理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SpringMVC學(xué)習(xí)筆記

以下是我整理的SpringMVC學(xué)習(xí)筆記:

? 導(dǎo)入jar

?

一:springmvc工作流程。

①.???? servlet容器初始化一個(gè)request請(qǐng)求

②.???? DispatcherServlet分發(fā)器負(fù)責(zé)發(fā)送請(qǐng)求到映射器.

③.???? despatcherServlet把請(qǐng)求交給處理器映射Mapping,mapping來(lái)尋找需要執(zhí)行的control

④.???? 處理器映射把請(qǐng)求分發(fā)給控制器Controler

⑤.???? Controler執(zhí)行完畢后返回ModelAndView(視圖解析器)

⑥.???? 把ModelAndView返回給dispatcherServlet核心分發(fā)器

⑦.???? 由于DespatcherServlet不參與具體的處理,所以把modelAndView交給視圖解析器。

⑧.???? 視圖解析器解析成一個(gè)真正的視圖,再發(fā)給view然后response

?

?

  • ParameterizableViewController(參數(shù)控制器)

①.在springmvc-servlet.xml里面加上配置

<bean id="index" class="org.springframework.web.servlet.mvc.ParameterizableViewController">

  <property name="viewName" value="index"></property>

</bean>

②.通過(guò)參數(shù)控制器訪問(wèn)頁(yè)面流程

?

解析:也可以直接在參數(shù)控制器里定義name屬性,直接通過(guò)name屬性地址來(lái)訪問(wèn)。

如下:

<bean id="index" name="/mmmm.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">

  <property name="viewName" value="index"></property>

</bean>

但要注意的是:配置文件里必須有BeanNameUrlHandlerMapping;如果配置了其他映射的情況下,默認(rèn)映射將會(huì)被覆蓋;以name屬性;來(lái)訪問(wèn)將會(huì)失敗。

  • 命令控制器

①.創(chuàng)建自定義命令控制器接收url傳遞過(guò)來(lái)的參數(shù)并封裝到j(luò)avabean

public class MyCommandController extends AbstractCommandController{

?? protected ModelAndView handle(HttpServletRequest request,

???????? HttpServletResponse response, Object command, BindException errors)

???????? throws Exception {

????? User u = (User) command; ?? System.out.println(u.getUserName()+"||"+u.getPassword());

?????  return new ModelAndView("index","user",u);

?? }

}

②.創(chuàng)建javabean

public class User {

  private Integer id;

  private String userName;

  private String password;

  private Integer age;

  public Integer getId() {

??   return id;

  }

  public void setId(Integer id) {

??   this.id = id;

  }

  public String getUserName() {

??   return userName;

  }

  public void setUserName(String userName) {

??   this.userName = userName;

  }

  public String getPassword() {

??   return password;

  }

  public void setPassword(String password) {

??   this.password = password;

  }

  public Integer getAge() {

??   return age;

  }

  public void setAge(Integer age) {

??   this.age = age;

  }

}

③.在springmvc里面有如下配置。

<bean id="comm" name="/comm.do" class="cn.itcast.controller.MyCommandController">

?????????? <property name="commandClass" value="cn.itcast.domain.User"></property>

</bean>

④.使用簡(jiǎn)單url進(jìn)行訪問(wèn),參數(shù)被封裝進(jìn)javabean

http://localhost:8080/mysm/comm.do?id=1&userName=zhangsan&password=123&age=13

  • 命令控制器

①.

首先:springMVC有三個(gè)映射器,如果不定義映射Mapping,那么就會(huì)使默認(rèn):

l?? <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>

也就是說(shuō):上面這個(gè)定義和不定義都是一樣的。

不定義:

<bean id="testController" name="/hello.do" class="cn.itcast.controller.TestController"></bean>

直接使用:hello.do來(lái)訪問(wèn)。

<!-- 簡(jiǎn)單的url映射處理器 -->

l?? <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

?????????????????? <property name="mappings">

??????????????????????????? <props>

???????????????????????????????????? <prop key="/hello1.do">testController[h1]?</prop>

???????????????????????????????????? <prop key="/a.do">testController</prop>

??????????????????????????? </props>

?????????????????? </property>

</bean>

???????? 那么上面的這個(gè)映射配置:表示多個(gè)*.do文件可以訪問(wèn)多個(gè)Controller或者一個(gè)Controller.

???????? 前提是:都必須依賴:

???????? <bean id="testController" name="/hello.do" class="cn.itcast.controller.TestController"></bean>

???????? <!-- /WEB-INF/jsp/index.jsp -->

???????? <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

?????????????????? <property name="prefix" value="/WEB-INF/jsp/"></property>

?????????????????? <property name="suffix" value=".jsp"></property>

???????? </bean>

l?? 第三個(gè)Mapping

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>

這個(gè)Mapping一配置:我們就可以使用Contrller [類名.do]來(lái)訪問(wèn)這個(gè)Controller.

訪問(wèn)形式如下:

http://localhost:8080/myspringmvc/testController.do

或者

http://localhost:8080/myspringmvc/testController

這樣的形式都可訪問(wèn)到index頁(yè)面。

?? 也可以在前臺(tái)傳入?yún)?shù):

http://localhost:8080/myspringmvc/testController1.do?name=hhhh

在后臺(tái)接收如下:

String name = req.getParameter("name");

????? System.out.println("這里是springmvc!");

????? return new ModelAndView("index","name",name);

在頁(yè)面使用EL表達(dá)式獲取值。

  • 1.??????? SpringMvc的三個(gè)控制器。
  • l?? 命令控制器CommandController(命令控制器)

    public class MyCommandController extends AbstractCommandController {

    ?? public MyCommandController() {

    ????? this.setCommandClass(User.class);

    ????? this.setCommandName("user");

    ?? }?

    ?? @Override

    ?? protected ModelAndView handle(HttpServletRequest request,

    ???????? HttpServletResponse response, Object command, BindException errors)

    ???????? throws Exception {

    ????? // TODO Auto-generated method stub

    ????? User u = (User) command;

    ????? System.out.println(u.getName());

    ????? return new ModelAndView("command","user",u);

    ?? }

    }

    <!-- 命令控制器 -->

    <bean

      name="/command.do" class="cn.itcast.controller.MyCommandController">

    </bean>

    ?

    頁(yè)面就可以采用如下方式進(jìn)行獲取:

    ?

    public class MyCommandController extends AbstractCommandController {

    ?

    ?? public MyCommandController() {

    ? ? ? ? ?this.setCommandClass(User.class);

    ? ? ? ? ?this.setCommandName("user");

    ?? }?

    ?? @Override

    ?? protected ModelAndView handle(HttpServletRequest request,

    ???????? HttpServletResponse response, Object command, BindException errors)

    ???????? throws Exception {

    ????? // TODO Auto-generated method stub

    ????? User u = (User) command;

    ????? System.out.println(u.getName());

    ????? return null;

    ?? }

    }

    配置文件:

    <bean name="/command.do" class="cn.itcast.controller.MyCommandController"></bean>

    說(shuō)明:在domain包里面定義User類:并為Usernamesexage屬性生成setter

    Getter方法。

    當(dāng)我們使用:command.do訪問(wèn)時(shí),使用get請(qǐng)求:?name=oo&sex=man&age=17

    后臺(tái)繼承AbstractCommandController這個(gè)類的命令控制器將會(huì)自動(dòng)

    獲取并封裝這個(gè)三個(gè)值。

    并放入command

    l?? 表單控制器FormController(表單控制器)

    public class MyFormContrller extends SimpleFormController {

    ?? public MyFormContrller() {

    ????? // TODO Auto-generated constructor stub

    ????? this.setCommandClass(User.class);

    ????? this.setCommandName("user");

    ?? }

    ?? @Override

    ?? protected void doSubmitAction(Object command) throws Exception {

    ????? // TODO Auto-generated method stub

    ????? User u = (User) command;

    ????? System.out.println(u.getName()+"kkkooo");

    ????? super.doSubmitAction(command);

    ?? }

    }

    <!-- 表單控制器 -->

    ??? <bean name="/form.do" class="cn.itcast.controller.MyFormContrller">

    ??? <property name="successView" value="success[h2]?"></property>

    ??? <property name="formView[h3]?" value="form"></property>

    ??? </bean>

    ?

    24.2.4 AbstractWizardFormController(1)

    在使用Eclipse或者Netbeans之類的IDE進(jìn)行開發(fā)的時(shí)候,如果我們新建一個(gè)工程或者文件,這些IDE通常都會(huì)提供多步的向?qū)椭覀円徊揭徊酵瓿上鄳?yīng)部件的創(chuàng)建。在某些Web應(yīng)用程序中,也存在類似的操作場(chǎng)景,比如,要注冊(cè)某個(gè)網(wǎng)站的會(huì)員,注冊(cè)過(guò)程可能就包括多步,每一步會(huì)提示輸入某一方面的信息,以幫助我們簡(jiǎn)化操作流程。對(duì)于這種向?qū)降暮?jiǎn)單的多頁(yè)面流程實(shí)現(xiàn),我們可以求助于AbstractWizardFormController,它可以幫助我們簡(jiǎn)化類似場(chǎng)景的開發(fā)工作。

    注意 實(shí)際上,AbstractWizardFormController也只是面向簡(jiǎn)單的多頁(yè)面流程處理,它所管理的多個(gè)頁(yè)面表單中的數(shù)據(jù),最終都是綁定到一個(gè)Command對(duì)象上的。只不過(guò)是每個(gè)頁(yè)面綁定一部分而已。如果要在Web應(yīng)用程序中處理更復(fù)雜的頁(yè)面流程交互,建議集成Spring Web Flow(http://?www.springframework.org/Webflow),Expert Spring MVC and Web Flow一書對(duì)Spring Web Flow進(jìn)行了詳盡的介紹。

    1. AbstractWizardFormController淺析

    說(shuō)白了,AbstractWizardFormController實(shí)現(xiàn)類就是要處理組成向?qū)Я鞒痰乃许?yè)面所發(fā)起的Web請(qǐng)求。但與SimpleFormController處理單個(gè)表單頁(yè)面不同,AbstractWizardFormController要管理多個(gè)表單頁(yè)面的顯示以及提交數(shù)據(jù)的處理工作。

    圖24-12對(duì)AbstractWizardFormController如何管理整個(gè)向?qū)Я鞒探o出了一個(gè)概況,我們對(duì)AbstractWizardFormController的認(rèn)識(shí)將在這個(gè)的基礎(chǔ)上展開。

    ?

    (點(diǎn)擊查看大圖)圖24-12 AbstractWizardFormController的Web請(qǐng)求處理結(jié)構(gòu)

    Page1、Page2和Page3是組成向?qū)Я鞒痰捻?yè)面,這些頁(yè)面提交的Web請(qǐng)求將統(tǒng)一由我們的AbstractWizardFormController接收并處理。但AbstractWizardFormController如何知道當(dāng)前該顯示哪個(gè)頁(yè)面?它又是如何判斷哪個(gè)頁(yè)面提交的請(qǐng)求是最終的結(jié)束向?qū)Я鞒痰腤eb請(qǐng)求呢?AbstractWizardFormController將根據(jù)每個(gè)頁(yè)面請(qǐng)求所包含的特定參數(shù)來(lái)決定如何對(duì)當(dāng)前請(qǐng)求進(jìn)行處理,這些特定的參數(shù)我們可以分為如下三類。

    PARAM_TARGET參數(shù)。PARAM_TARGET參數(shù)用于指定目標(biāo)頁(yè)面,它的形式為_target后綴頁(yè)面索引,比如_target0、_target1等。當(dāng)AbstractWizardFormController實(shí)現(xiàn)類接收到這種類型的參數(shù)的時(shí)候,它只是將當(dāng)前請(qǐng)求中的相應(yīng)參數(shù)綁定到Command對(duì)象上,然后根據(jù)PARAM_TARGET參數(shù)后綴的目標(biāo)頁(yè)面索引顯示相應(yīng)的頁(yè)面。

    PARAM_FINISH參數(shù)。PARAM_FINISH參數(shù)的表示形式為_finish。如果AbstractWizard- FormController實(shí)現(xiàn)類接收到該參數(shù),則表示整個(gè)向?qū)Я鞒探Y(jié)束,可以調(diào)用process- Finish(..)方法處理最終的表單數(shù)據(jù),并將頁(yè)面轉(zhuǎn)向任何一個(gè)想要轉(zhuǎn)到的頁(yè)面。

    PARAM_CANCEL參數(shù)。PARAM_CANCEL參數(shù)的表示形式為_cancel。當(dāng)接收到該參數(shù)的時(shí)候,表示用戶要取消當(dāng)前的向?qū)Я鞒獭DJ(rèn)情況下,AbstractWizardFormController不支持該參數(shù)的處理,但我們可以通過(guò)覆寫processCancel(..)方法來(lái)改變這種默認(rèn)行為。唯一要做的,可能只是返回一個(gè)ModelAndView實(shí)例,其中只包含了一個(gè)邏輯視圖名。

    實(shí)際上,AbstractWizardFormController實(shí)現(xiàn)類本質(zhì)上依然是像SimpleFormController那樣,分兩個(gè)階段來(lái)管理表單頁(yè)面的處理,只不過(guò)是從邏輯上將單個(gè)表單頁(yè)面劃分為了多個(gè)表單頁(yè)面,而最終綁定數(shù)據(jù)的Command對(duì)象卻只有一個(gè)。AbstractWizardFormController將根據(jù)_targetX參數(shù)決定顯示表單頁(yè)面的某一部分,對(duì)應(yīng)到視圖那就是顯示哪個(gè)向?qū)ы?yè)面。在該向?qū)ы?yè)面提交請(qǐng)求之后,AbstractWizardFormController會(huì)把它顯示并提交的那部分?jǐn)?shù)據(jù)綁定到唯一的那個(gè)Command對(duì)象上,只有在所有向?qū)ы?yè)面都提交之后,Command對(duì)象的數(shù)據(jù)才算綁定完成。從這樣的角度來(lái)說(shuō),AbstractWizardFormController只不過(guò)是將一部分信息劃分為多步來(lái)顯示和處理罷了。

    我們?cè)谙驅(qū)?#xff08;Wizard)最終結(jié)束的畫面提交_finish參數(shù)之后,AbstractWizardFormController將從Command對(duì)象獲取到所有向?qū)ы?yè)面(Wizard Page)搜集來(lái)的數(shù)據(jù),然后它就可以調(diào)用process- Finish(..)方法開始"壓軸戲"了。實(shí)際上,在實(shí)現(xiàn)AbstractWizardFormController的時(shí)候,也只有processFinish(..)方法是需要我們必須去實(shí)現(xiàn)的。

    我想,以上的分析內(nèi)容已經(jīng)足以說(shuō)明AbstractWizardFormController的底細(xì)。不過(guò),如果你還意猶未盡的話,不妨再研讀一下Expert Spring MVC and Web Flow一書。像如何提供數(shù)據(jù)驗(yàn)證,如何覆寫某些方法以添加擴(kuò)展邏輯之類的細(xì)節(jié),該書都有提及。相信我,因?yàn)槲乙呀?jīng)讀過(guò)了。

    2. AbstractWizardFormController實(shí)例

    我搜刮了FX系統(tǒng)的前臺(tái)和后臺(tái)的所有場(chǎng)景,也沒(méi)有找到一個(gè)需要向?qū)У牧鞒獭K?#xff0c;為了演示AbstractWizardFormController的使用,我也不能免俗,創(chuàng)造了一個(gè)調(diào)查問(wèn)卷的場(chǎng)景。我們將分三步引導(dǎo)用戶完成對(duì)購(gòu)車意愿的問(wèn)卷調(diào)查。當(dāng)然,整個(gè)問(wèn)卷調(diào)查看起來(lái)有些簡(jiǎn)單了,但如果需要,我們也可以在這個(gè)基礎(chǔ)上提供更加友好、更加全面的問(wèn)卷調(diào)查向?qū)А?/p>

    為了分步顯示調(diào)查的內(nèi)容,我們提供了4個(gè)頁(yè)面分別顯示整體的某一部分內(nèi)容,它們的關(guān)系如下所述。

    welcome.jsp。問(wèn)卷調(diào)查向?qū)У拈_始頁(yè)面,提供簡(jiǎn)單的說(shuō)明信息

    carManufacturers.jsp。該頁(yè)面將提供汽車廠商信息列表供用戶選擇

    carPriceScope.jsp。向?qū)Я鞒讨凶詈笠粋€(gè)問(wèn)卷調(diào)查頁(yè)面,顯示意愿購(gòu)車價(jià)格區(qū)間,點(diǎn)擊"結(jié)束問(wèn)卷"提交按鈕即結(jié)束當(dāng)前問(wèn)卷調(diào)查

    surveyResult.jsp。確切地講,該頁(yè)面不能算向?qū)У囊徊糠?#xff0c;它只是調(diào)查結(jié)束后的一個(gè)結(jié)果顯示頁(yè)面,對(duì)應(yīng)的是successView。當(dāng)然,將具體數(shù)據(jù)轉(zhuǎn)換為柱狀圖顯示或許更討人愛(ài)一些,該頁(yè)面最終效果如下圖。

    現(xiàn)在讓我們著手實(shí)現(xiàn)該向?qū)Я鞒獭?/p>

    先來(lái)了解一下,幾個(gè)重要的接口與類。現(xiàn)在不知道他們是干什么的沒(méi)關(guān)系,先混個(gè)臉熟,為以后認(rèn)識(shí)他們打個(gè)基礎(chǔ)。

    DispatcherServlet?? -- 前置控制器

    ?

    HandlerMapping接口 -- 處理請(qǐng)求的映射

    HandlerMapping接口的實(shí)現(xiàn)類:

    SimpleUrlHandlerMapping? 通過(guò)配置文件,把一個(gè)URL映射到Controller

    DefaultAnnotationHandlerMapping? 通過(guò)注解,把一個(gè)URL映射到Controller類上

    ?

    HandlerAdapter接口 -- 處理請(qǐng)求的映射

    AnnotationMethodHandlerAdapter類,通過(guò)注解,把一個(gè)URL映射到Controller類的方法上

    ?

    Controller接口 -- 控制器

    由于我們使用了@Controller注解,添加了@Controller注解注解的類就可以擔(dān)任控制器(Action)的職責(zé),

    所以我們并沒(méi)有用到這個(gè)接口。

    ?

    HandlerInterceptor 接口--攔截器

    無(wú)圖,我們自己實(shí)現(xiàn)這個(gè)接口,來(lái)完成攔截的器的工作。?

    ViewResolver接口的實(shí)現(xiàn)類

    UrlBasedViewResolver類 通過(guò)配置文件,把一個(gè)視圖名交給到一個(gè)View來(lái)處理

    InternalResourceViewResolver類,比上面的類,加入了JSTL的支持

    ?

    View接口

    JstlView類

    ?

    LocalResolver接口

    ?

    HandlerExceptionResolver接口 --異常處理

    SimpleMappingExceptionResolver實(shí)現(xiàn)類

    ?

    ModelAndView類

    無(wú)圖。?

    三、核心流程圖?

    ?

    ?

    四、DispatcherServlet說(shuō)明?

    使用Spring MVC,配置DispatcherServlet是第一步。

    DispatcherServlet是一個(gè)Servlet,所以可以配置多個(gè)DispatcherServlet。

    DispatcherServlet是前置控制器,配置在web.xml文件中的。攔截匹配的請(qǐng)求,Servlet攔截匹配規(guī)則要自已定義,把攔截下來(lái)的請(qǐng)求,依據(jù)某某規(guī)則分發(fā)到目標(biāo)Controller(我們寫的Action)來(lái)處理。?

    “某某規(guī)則”:是根據(jù)你使用了哪個(gè)HandlerMapping接口的實(shí)現(xiàn)類的不同而不同。?

    先來(lái)看第一個(gè)例子:

    Xml代碼??

  • <web-app>??
  • ????<servlet>??
  • ????????<servlet-name>example</servlet-name>??
  • ????????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>??
  • ????????<load-on-startup>1</load-on-startup>??
  • ????</servlet>??
  • ????<servlet-mapping>??
  • ????????<servlet-name>example</servlet-name>??
  • ????????<url-pattern>*.form</url-pattern>??
  • ????</servlet-mapping>??
  • </web-app>??
  • ?<load-on-startup>1</load-on-startup>是啟動(dòng)順序,讓這個(gè)Servlet隨Servletp容器一起啟動(dòng)。

    ?<url-pattern>*.form</url-pattern> 會(huì)攔截*.form結(jié)尾的請(qǐng)求。

    ?<servlet-name>example</servlet-name>這個(gè)Servlet的名字是example,可以 有多個(gè)DispatcherServlet,是通過(guò)名字來(lái)區(qū)分的。每一個(gè)DispatcherServlet有自己的 WebApplicationContext上下文對(duì)象。同時(shí)保存的ServletContext中和Request對(duì)象中,關(guān)于key,以后說(shuō)明。

    在DispatcherServlet的初始化過(guò)程中,框架會(huì)在web應(yīng)用的 WEB-INF文件夾下尋找名為[servlet-name]-servlet.xml 的配置文件,生成文件中定義的bean。

    第二個(gè)例子:

    Xml代碼??

  • <servlet>??
  • ????<servlet-name>springMVC</servlet-name>??
  • ????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>??
  • ????<init-param>??
  • ????????<param-name>contextConfigLocation</param-name>??
  • ????????<param-value>classpath*:/springMVC.xml</param-value>??
  • ????</init-param>??
  • ????<load-on-startup>1</load-on-startup>??
  • </servlet>??
  • <servlet-mapping>??
  • ????<servlet-name>springMVC</servlet-name>??
  • ????<url-pattern>/</url-pattern>??
  • </servlet-mapping>??
  • 指明了配置文件的文件名,不使用默認(rèn)配置文件名,而使用springMVC.xml配置文件。

    其中<param-value>**.xml</param-value> 這里可以使用多種寫法
    1、不寫,使用默認(rèn)值:/WEB-INF/<servlet-name>-servlet.xml
    2、<param-value>/WEB-INF/classes/springMVC.xml</param-value>
    3、<param-value>classpath*:springMVC-mvc.xml</param-value>
    4、多個(gè)值用逗號(hào)分隔

    Servlet攔截匹配規(guī)則可以自已定義,Servlet攔截哪種URL合適??
    當(dāng)映射為@RequestMapping("/user/add")時(shí):
    1、攔截*.do,例如:/user/add.do,弊端:所有的url都要以.do結(jié)尾。不會(huì)影響訪問(wèn)靜態(tài)文件。
    2、攔截/app/*,例如:/app/user/add,弊端:請(qǐng)求的url都要包含/app,@RequestMapping("/user/add")中不須要包含/app。
    3、攔截/,例如:/user/add,弊端:對(duì)jpg,js,css靜態(tài)文件的訪問(wèn)也被攔截不能正常顯示。后面有解決辦法。
    4、攔截/*,可以走到Action中,但轉(zhuǎn)發(fā)到j(luò)sp時(shí)再次被攔截,不能訪問(wèn)到j(luò)sp。

    五、雙親上下文的說(shuō)明

    如果你使用了listener監(jiān)聽器來(lái)加載配置,一般在Struts+Spring+Hibernate的項(xiàng)目中都是使用listener監(jiān)聽器的。如下

    Java代碼??

  • <listener>???
  • ? ? ?<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>???
  • </listener>???
  • Spring會(huì)創(chuàng)建一個(gè)全局的WebApplicationContext上下文,稱為根上下文?,保存在?ServletContext 中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE屬性的值。可 以使用工具類取出上下 文:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

    DispatcherServlet是一個(gè)Servlet,可以同時(shí)配置多個(gè),每個(gè)?DispatcherServlet有一個(gè)自己的?WebApplicationContext上下文,這個(gè)上下文繼承了?根上下文?中所有東西。?保存在?ServletContext中,key是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名稱。當(dāng)一個(gè)Request對(duì)象產(chǎn)生時(shí),會(huì)把這個(gè)WebApplicationContext上下文保存在Request對(duì)象中,key是DispatcherServlet.class.getName() + ".CONTEXT"。可以使用工具類取出上下文:RequestContextUtils.getWebApplicationContext(request);

    Spring中的 ApplicationContext實(shí)例可以被限制在不同的作用域(scope)中。
    在web MVC框架中,每個(gè) DispatcherServlet有它自己的WebApplicationContext ,這個(gè)context繼承了根 WebApplicationContext 的所有bean定義。
    這些繼承的bean也可以在每個(gè)serlvet自己的所屬的域中被覆蓋(override),覆蓋后的bean 可以被設(shè)置上只有這個(gè)servlet實(shí)例自己使用的屬性。

    總結(jié):不使用listener監(jiān)聽器來(lái)加載spring的配置,改用DispatcherServlet來(lái)加載spring的配置,不要雙親上下文,只使用一個(gè)DispatcherServlet,事情就簡(jiǎn)單了,什么麻煩事兒也沒(méi)有了。

    六、springMVC-mvc.xml 配置文件片段講解?(未使用默認(rèn)配置文件名)

    Xml代碼??

  • <?xml?version="1.0"?encoding="UTF-8"?>??
  • <beans??
  • ????xmlns="http://www.springframework.org/schema/beans"??
  • ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
  • ????xmlns:tx="http://www.springframework.org/schema/tx"??
  • ????xmlns:context="http://www.springframework.org/schema/context"????
  • ????xmlns:mvc="http://www.springframework.org/schema/mvc"????
  • ????xsi:schemaLocation="http://www.springframework.org/schema/beans???
  • ????http://www.springframework.org/schema/beans/spring-beans-3.0.xsd???
  • ????http://www.springframework.org/schema/tx???
  • ????http://www.springframework.org/schema/tx/spring-tx-3.0.xsd??
  • ????http://www.springframework.org/schema/context??
  • ????http://www.springframework.org/schema/context/spring-context-3.0.xsd??
  • ????http://www.springframework.org/schema/mvc??
  • ????http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">??
  • ??
  • ??
  • ????<!--?自動(dòng)掃描的包名?-->??
  • ????<context:component-scan?base-package="com.app,com.core,JUnit4"?></context:component-scan>??
  • ??????
  • ????<!--?默認(rèn)的注解映射的支持?-->??
  • ????<mvc:annotation-driven?/>??
  • ??????
  • ????<!--?視圖解釋類?-->??
  • ????<bean?class="org.springframework.web.servlet.view.InternalResourceViewResolver">??
  • ????????<property?name="prefix"?value="/WEB-INF/jsp/"/>??
  • ????????<property?name="suffix"?value=".jsp"/><!--可為空,方便實(shí)現(xiàn)自已的依據(jù)擴(kuò)展名來(lái)選擇視圖解釋類的邏輯??-->??
  • ????????<property?name="viewClass"?value="org.springframework.web.servlet.view.JstlView"?/>??
  • ????</bean>??
  • ??????
  • ????<!--?攔截器?-->??
  • ????<mvc:interceptors>??
  • ????????<bean?class="com.core.mvc.MyInteceptor"?/>??
  • ????</mvc:interceptors>???????
  • ??????
  • ????<!--?對(duì)靜態(tài)資源文件的訪問(wèn)??方案一?(二選一)?-->??
  • ????<mvc:default-servlet-handler/>??
  • ??????
  • ????<!--?對(duì)靜態(tài)資源文件的訪問(wèn)??方案二?(二選一)-->??
  • ????<mvc:resources?mapping="/images/**"?location="/images/"?cache-period="31556926"/>??
  • ????<mvc:resources?mapping="/js/**"?location="/js/"?cache-period="31556926"/>??
  • ????<mvc:resources?mapping="/css/**"?location="/css/"?cache-period="31556926"/>??
  • ??
  • </beans> ??
  • <context:component-scan/> 掃描指定的包中的類上的注解,常用的注解有:

    @Controller 聲明Action組件
    @Service??? 聲明Service組件??? @Service("myMovieLister")?
    @Repository 聲明Dao組件
    @Component?? 泛指組件, 當(dāng)不好歸類時(shí).?
    @RequestMapping("/menu")? 請(qǐng)求映射
    @Resource? 用于注入,( j2ee提供的 ) 默認(rèn)按名稱裝配,@Resource(name="beanName")?
    @Autowired 用于注入,(srping提供的) 默認(rèn)按類型裝配?
    @Transactional( rollbackFor={Exception.class}) 事務(wù)管理
    @ResponseBody
    @Scope("prototype")?? 設(shè)定bean的作用域

    <mvc:annotation-driven /> 是一種簡(jiǎn)寫形式,完全可以手動(dòng)配置替代這種簡(jiǎn)寫形式,簡(jiǎn)寫形式可以讓初學(xué)都快速應(yīng)用默認(rèn)配置方 案。<mvc:annotation-driven /> 會(huì)自動(dòng)注冊(cè)DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個(gè)bean,是spring MVC為@Controllers分發(fā)請(qǐng)求所必須的。
    并提供了:數(shù)據(jù)綁定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,讀寫XML的支持(JAXB),讀寫JSON的支持(Jackson)。
    后面,我們處理響應(yīng)ajax請(qǐng)求時(shí),就使用到了對(duì)json的支持。
    后面,對(duì)action寫JUnit單元測(cè)試時(shí),要從spring IOC容器中取DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個(gè)bean,來(lái)完成測(cè)試,取的時(shí)候要知道是<mvc:annotation-driven />這一句注冊(cè)的這兩個(gè)bean。

    如何替換?<mvc:annotation-driven />?他到底做了什么工作,請(qǐng)看,最后面的 十九節(jié)?<mvc:annotation-driven />?到底做了什么工作。

    <mvc:interceptors/> 是一種簡(jiǎn)寫形式。通過(guò)看前面的大圖,知道,我們可以配置多個(gè)HandlerMapping。<mvc:interceptors/>會(huì)為每一個(gè)HandlerMapping,注入一個(gè)攔截器。其實(shí)我們也可以手動(dòng)配置為每個(gè)HandlerMapping注入一個(gè)攔截器。

    <mvc:default-servlet-handler/> 使用默認(rèn)的Servlet來(lái)響應(yīng)靜態(tài)文件。

    <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/> 匹配URL? /images/**? 的URL被當(dāng)做靜態(tài)資源,由Spring讀出到內(nèi)存中再響應(yīng)http。


    七、如何訪問(wèn)到靜態(tài)的文件,如jpg,js,css?

    如何你的DispatcherServlet攔截 *.do這樣的URL,就不存在訪問(wèn)不到靜態(tài)資源的問(wèn)題。如果你的DispatcherServlet攔截“/”,攔截了所有的請(qǐng)求,同時(shí)對(duì)*.js,*.jpg的訪問(wèn)也就被攔截了。

    目的:可以正常訪問(wèn)靜態(tài)文件,不要找不到靜態(tài)文件報(bào)404。
    方案一:激活Tomcat的defaultServlet來(lái)處理靜態(tài)文件

    Xml代碼??

  • <servlet-mapping>???
  • ????<servlet-name>default</servlet-name>??
  • ????<url-pattern>*.jpg</url-pattern>?????
  • </servlet-mapping>????
  • <servlet-mapping>???????
  • ????<servlet-name>default</servlet-name>????
  • ????<url-pattern>*.js</url-pattern>????
  • </servlet-mapping>????
  • <servlet-mapping>????????
  • ????<servlet-name>default</servlet-name>???????
  • ????<url-pattern>*.css</url-pattern>??????
  • </servlet-mapping>????
  • 配置多個(gè),每種文件配置一個(gè)???
  • 要寫在DispatcherServlet的前面, 讓?defaultServlet先攔截,這個(gè)就不會(huì)進(jìn)入Spring了,我想性能是最好的吧。

    Tomcat, Jetty, JBoss, and GlassFish 自帶的默認(rèn)Servlet的名字 -- "default"
    Google App Engine?自帶的?默認(rèn)Servlet的名字 -- "_ah_default"
    Resin?自帶的?默認(rèn)Servlet的名字 -- "resin-file"
    WebLogic?自帶的?默認(rèn)Servlet的名字? -- "FileServlet"
    WebSphere??自帶的?默認(rèn)Servlet的名字 -- "SimpleFileServlet"?

    方案二: 在spring3.0.4以后版本提供了mvc:resources?
    mvc:resources 的使用方法:

    Xml代碼??

  • <!--?對(duì)靜態(tài)資源文件的訪問(wèn)?-->????
  • <mvc:resources?mapping="/images/**"?location="/images/"?/> ?
  • /images/**映射到ResourceHttpRequestHandler進(jìn)行處理,location指定靜態(tài)資源的位置.可以是 web application根目錄下、jar包里面,這樣可以把靜態(tài)資源壓縮到j(luò)ar包中。cache-period 可以使得靜態(tài)資源進(jìn)行web cache?
    ?
    如果出現(xiàn)下面的錯(cuò)誤,可能是沒(méi)有配置<mvc:annotation-driven />的原因。?
    報(bào)錯(cuò)WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'

    使用<mvc:resources/>元素,把mapping的URI注冊(cè)到SimpleUrlHandlerMapping的urlMap中,
    key為mapping的URI pattern值,而value為ResourceHttpRequestHandler,
    這樣就巧妙的把對(duì)靜態(tài)資源的訪問(wèn)由HandlerMapping轉(zhuǎn)到ResourceHttpRequestHandler處理并返回,所以就支持classpath目錄,jar包內(nèi)靜態(tài)資源的訪問(wèn).
    另外需要注意的一點(diǎn)是,不要對(duì)SimpleUrlHandlerMapping設(shè)置defaultHandler.因?yàn)閷?duì)static uri的defaultHandler就是ResourceHttpRequestHandler,
    否則無(wú)法處理static resources request.

    方案三 ,使用<mvc:default-servlet-handler/>

    Xml代碼??

  • <mvc:default-servlet-handler/>??
  • 會(huì)把"/**" url,注冊(cè)到SimpleUrlHandlerMapping的urlMap中,把對(duì)靜態(tài)資源的訪問(wèn)由HandlerMapping轉(zhuǎn)到 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler 處理并返回.
    DefaultServletHttpRequestHandler使用就是各個(gè)Servlet容器自己的默認(rèn)Servlet.

    補(bǔ)充說(shuō)明:多個(gè)HandlerMapping的執(zhí)行順序問(wèn)題:

    DefaultAnnotationHandlerMapping的order屬性值是:0

    <mvc:resources/?>自動(dòng)注冊(cè)的?SimpleUrlHandlerMapping的order屬性值是:?2147483646

    <mvc:default-servlet-handler/>自動(dòng)注冊(cè)?的SimpleUrlHandlerMapping?的order屬性值是:?2147483647

    spring會(huì)先執(zhí)行order值比較小的。當(dāng)訪問(wèn)一個(gè)a.jpg圖片文件時(shí),先通過(guò)?DefaultAnnotationHandlerMapping?來(lái)找處理器,一定是找不到的,我們沒(méi)有叫a.jpg的Action。再?按order值升序找,由于最后一個(gè)?SimpleUrlHandlerMapping?是匹配"/**"的,所以一定會(huì)匹配上,再響應(yīng)圖片。

    訪問(wèn)一個(gè)圖片,還要走層層匹配。真不知性能如何?改天做一下壓力測(cè)試,與Apache比一比。

    最后再說(shuō)明一下,?如何你的DispatcherServlet攔截 *.do這樣的URL后綴,就不存上述問(wèn)題了。還是有后綴方便。

    八、請(qǐng)求如何映射到具體的Action中的方法?
    方案一:基于xml配置映射,可以利用SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping進(jìn)行Url映射和攔截請(qǐng)求。
    配置方法略。
    ?
    方案二:基于注解映射,可以使用DefaultAnnotationHandlerMapping。

    Xml代碼??

  • <bean?class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">??</bean>???
  • 但前面我們配置了<mvc:annotation-driven />,他會(huì)自動(dòng)注冊(cè)這個(gè)bean,就不須要我們顯示的注冊(cè)這個(gè)bean了。??

    如何替換?<mvc:annotation-driven />?他到底做了什么工作,請(qǐng)看,最后面的 十九節(jié)?<mvc:annotation-driven />?到底做了什么工作。

    以上都可以注入interceptors,實(shí)現(xiàn)權(quán)限控制等前置工作。
    我們使用第2種,基于注解來(lái)使用spring MVC?

    ?并在action類上使用:
    @Controller
    @RequestMapping("/user")
    ?
    九、Spring中的攔截器:
    Spring為我們提供了:
    org.springframework.web.servlet.HandlerInterceptor接口,

    org.springframework.web.servlet.handler.HandlerInterceptorAdapter適配器,
    實(shí)現(xiàn)這個(gè)接口或繼承此類,可以非常方便的實(shí)現(xiàn)自己的攔截器。
    ?
    有以下三個(gè)方法:
    ?
    Action之前執(zhí)行:
    ?public boolean preHandle(HttpServletRequest request,
    ?? HttpServletResponse response, Object handler);
    ?
    生成視圖之前執(zhí)行
    ?public void postHandle(HttpServletRequest request,
    ?? HttpServletResponse response, Object handler,
    ?? ModelAndView modelAndView);
    ?
    最后執(zhí)行,可用于釋放資源
    ?public void afterCompletion(HttpServletRequest request,
    ?? HttpServletResponse response, Object handler, Exception ex)
    ?
    分別實(shí)現(xiàn)預(yù)處理、后處理(調(diào)用了Service并返回ModelAndView,但未進(jìn)行頁(yè)面渲染)、返回處理(已經(jīng)渲染了頁(yè)面)?
    在preHandle中,可以進(jìn)行編碼、安全控制等處理;?
    在postHandle中,有機(jī)會(huì)修改ModelAndView;?
    在afterCompletion中,可以根據(jù)ex是否為null判斷是否發(fā)生了異常,進(jìn)行日志記錄。?
    參數(shù)中的Object handler是下一個(gè)攔截器。
    轉(zhuǎn)載請(qǐng)注明出處:本文地址:http://elf8848.iteye.com/blog/875830


    十、如何使用攔截器?
    自定義一個(gè)攔截器,要實(shí)現(xiàn)HandlerInterceptor接口:

    Java代碼??

  • public?class?MyInteceptor?implements?HandlerInterceptor?{?????
  • ????略。。。??
  • } ? ?
  • Spring MVC并沒(méi)有總的攔截器,不能對(duì)所有的請(qǐng)求進(jìn)行前后攔截。
    Spring MVC的攔截器,是屬于HandlerMapping級(jí)別的,可以有多個(gè)HandlerMapping ,每個(gè)HandlerMapping可以有自己的攔截器。
    當(dāng)一個(gè)請(qǐng)求按Order值從小到大,順序執(zhí)行HandlerMapping接口的實(shí)現(xiàn)類時(shí),哪一個(gè)先有返回,那就可以結(jié)束了,后面的HandlerMapping就不走了,本道工序就完成了。就轉(zhuǎn)到下一道工序了。
    攔截器會(huì)在什么時(shí)候執(zhí)行呢? 一個(gè)請(qǐng)求交給一個(gè)HandlerMapping時(shí),這個(gè)HandlerMapping先找有沒(méi)有處理器來(lái)處理這個(gè)請(qǐng)求,如何找到了,就執(zhí)行攔截器,執(zhí)行完攔截后,交給目標(biāo)處理器。
    如果沒(méi)有找到處理器,那么這個(gè)攔截器就不會(huì)被執(zhí)行。

    在spring MVC的配置文件中配置有三種方法:

    方案一,(近似)總攔截器,攔截所有url

    Java代碼??

  • ???<mvc:interceptors>??
  • ????<bean?class="com.app.mvc.MyInteceptor"?/>??
  • </mvc:interceptors>??
  • 為什么叫“近似”,前面說(shuō)了,Spring沒(méi)有總的攔截器。

    <mvc:interceptors/>會(huì)為每一 個(gè)HandlerMapping,注入一個(gè)攔截器。總有一個(gè)HandlerMapping是可以找到處理器的,最多也只找到一個(gè)處理器,所以這個(gè)攔截器總會(huì)被執(zhí)行的。起到了總攔截器的作用。

    ?

    方案二,?(近似)?總攔截器,?攔截匹配的URL。

    Xml代碼??

  • <mvc:interceptors?>????
  • ??<mvc:interceptor>????
  • ????????<mvc:mapping?path="/user/*"?/>?<!--?/user/*??-->????
  • ????????<bean?class="com.mvc.MyInteceptor"></bean>????
  • ????</mvc:interceptor>????
  • </mvc:interceptors>????
  • 就是比?方案一多了一個(gè)URL匹配。

    ?

    方案三,HandlerMappint上的攔截器

    Xml代碼??

  • <bean?class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">???????
  • ?<property?name="interceptors">???????
  • ?????<list>???????
  • ?????????<bean?class="com.mvc.MyInteceptor"></bean>??????
  • ?????</list>???????
  • ?</property>???????
  • </bean>???
  • ??如果使用了<mvc:annotation-driven />,?它會(huì)自動(dòng)注冊(cè)DefaultAnnotationHandlerMapping 與AnnotationMethodHandlerAdapter 這兩個(gè)bean,所以就沒(méi)有機(jī)會(huì)再給它注入interceptors屬性,就無(wú)法指定攔截器。

    當(dāng)然我們可以通過(guò)人工配置上面的兩個(gè)Bean,不使用?<mvc:annotation-driven />,就可以?給interceptors屬性?注入攔截器了。

    其實(shí)我也不建議使用?<mvc:annotation-driven />,而建議手動(dòng)寫詳細(xì)的配置文件,來(lái)替代?<mvc:annotation-driven />,這就控制力就強(qiáng)了。

    如何替換?<mvc:annotation-driven />?他到底做了什么工作,請(qǐng)看,最后面的 十九節(jié)?<mvc:annotation-driven />?到底做了什么工作。

    十一、如何實(shí)現(xiàn)全局的異常處理?

    在spring MVC的配置文件中:

    Xml代碼??

  • <!--?總錯(cuò)誤處理-->??
  • <bean?id="exceptionResolver"?class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">??
  • ????<property?name="defaultErrorView">????
  • ????????<value>/error/error</value>??
  • ????</property>??
  • ????<property?name="defaultStatusCode">????
  • ????????<value>500</value>??
  • ????</property>?????
  • <property?name="warnLogCategory">????
  • ????????<value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value>??
  • ????</property>?????
  • </bean> ??
  • 這里主要的類是SimpleMappingExceptionResolver類,和他的父類AbstractHandlerExceptionResolver類。

    具體可以配置哪些屬性,我是通過(guò)查看源碼知道的。

    你也可以實(shí)現(xiàn)HandlerExceptionResolver接口,寫一個(gè)自己的異常處理程序。spring的擴(kuò)展性是很好的。

    通過(guò)SimpleMappingExceptionResolver我們可以將不同的異常映射到不同的jsp頁(yè)面(通過(guò)exceptionMappings屬性的配置)。

    同時(shí)我們也可以為所有的異常指定一個(gè)默認(rèn)的異常提示頁(yè)面(通過(guò)defaultErrorView屬性的配置),如果所拋出的異常在exceptionMappings中沒(méi)有對(duì)應(yīng)的映射,則Spring將用此默認(rèn)配置顯示異常信息。

    注意這里配置的異常顯示界面均僅包括主文件名,至于文件路徑和后綴已經(jīng)在viewResolver中指定。如/error/error表示/error/error.jsp

    顯示錯(cuò)誤的jsp頁(yè)面:

    Html代碼??

  • <%@?page?language="java"?contentType="text/html;?charset=GBK"??
  • ????pageEncoding="GBK"%>??
  • <%@?page?import="java.lang.Exception"%>??
  • <!DOCTYPE?html?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"?"http://www.w3.org/TR/html4/loose.dtd">??
  • <html>??
  • <head>??
  • <meta?http-equiv="Content-Type"?content="text/html;?charset=GBK">??
  • <title>錯(cuò)誤頁(yè)面</title>??
  • </head>??
  • <body>??
  • <h1>出錯(cuò)了</h1>??
  • <%??
  • Exception?e?=?(Exception)request.getAttribute("exception");??
  • out.print(e.getMessage());??
  • %>??
  • </body>??
  • </html>??
  • 其中一句:request.getAttribute("exception"),key是exception,也是在SimpleMappingExceptionResolver類默認(rèn)指定的,是可能通過(guò)配置文件修改這個(gè)值的,大家可以去看源碼。

    ??參考文章:

    http://www.blogjava.net/wuxufeng8080/articles/191150.html

    http://fangjunai.blog.163.com/blog/static/1124970520108102013839/

    十二、如何把全局異常記錄到日志中?

    在前的配置中,其中有一個(gè)屬性warnLogCategory,值是 “SimpleMappingExceptionResolver類的全限定名”。我是在SimpleMappingExceptionResolver 類父類AbstractHandlerExceptionResolver類中找到這個(gè)屬性的。查看源碼后得知:如果warnLogCategory不為 空,spring就會(huì)使用apache的org.apache.commons.logging.Log日志工具,記錄這個(gè)異常,級(jí)別是warn。

    值:“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”,是“SimpleMappingExceptionResolver類的全限定名”。這個(gè)值不是隨便寫的。??因?yàn)槲以趌og4j的配置文 件中還要加入 log4j.logger.org.springframework.web.servlet.handler.SimpleMappingExceptionResolver=WARN, 保證這個(gè)級(jí)別是warn的日志一定會(huì)被記錄,即使log4j的根日志級(jí)別是ERROR。

    ?十三、如何給spring3 MVC中的Action做JUnit單元測(cè)試?

    ?使用了spring3 MVC后,給action做單元測(cè)試變得很方便,我以前從來(lái)不給action寫單元測(cè)試的,現(xiàn)在可以根據(jù)情況寫一些了。

    ?不用給每個(gè)Action都寫單元測(cè)試吧,自己把握吧。

    ?JUnitActionBase類是所有JUnit的測(cè)試類的父類

    Java代碼??

  • package?test;??
  • import?javax.servlet.http.HttpServletRequest;??
  • import?javax.servlet.http.HttpServletResponse;??
  • import?org.junit.BeforeClass;??
  • import?org.springframework.mock.web.MockServletContext;??
  • import?org.springframework.web.context.WebApplicationContext;??
  • import?org.springframework.web.context.support.XmlWebApplicationContext;??
  • import?org.springframework.web.servlet.HandlerAdapter;??
  • import?org.springframework.web.servlet.HandlerExecutionChain;??
  • import?org.springframework.web.servlet.HandlerMapping;??
  • import?org.springframework.web.servlet.ModelAndView;??
  • import?org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;??
  • import?org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping;??
  • /**??
  • *?說(shuō)明:?JUnit測(cè)試action時(shí)使用的基類?
  • *??
  • *?@author??胡晟源?
  • *?@version?創(chuàng)建時(shí)間:2013-2-2?下午10:27:03???
  • */???
  • public?class?JUnitActionBase?{??
  • ????private?static?HandlerMapping?handlerMapping;??
  • ????private?static?HandlerAdapter?handlerAdapter;??
  • ????/**?
  • ?????*?讀取spring3?MVC配置文件?
  • ?????*/??
  • ????@BeforeClass??
  • ?public?static?void?setUp()?{??
  • ????????if?(handlerMapping?==?null)?{??
  • ????????????String[]?configs?=?{?"file:src/springConfig/springMVC.xml"?};??
  • ????????????XmlWebApplicationContext?context?=?new?XmlWebApplicationContext();??
  • ????????????context.setConfigLocations(configs);??
  • ????????????MockServletContext?msc?=?new?MockServletContext();??
  • ????????????context.setServletContext(msc);?????????context.refresh();??
  • ????????????msc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,?context);??
  • ????????????handlerMapping?=?(HandlerMapping)?context??
  • ????????????????????.getBean(DefaultAnnotationHandlerMapping.class);??
  • ????????????handlerAdapter?=?(HandlerAdapter)?context.getBean(context.getBeanNamesForType(AnnotationMethodHandlerAdapter.class)[0]);?????
  • ????????}??
  • ????}??
  • ??
  • ????/**?
  • ?????*?執(zhí)行request對(duì)象請(qǐng)求的action?
  • ?????*??
  • ?????*?@param?request?
  • ?????*?@param?response?
  • ?????*?@return?
  • ?????*?@throws?Exception?
  • ?????*/??
  • ????public?ModelAndView?excuteAction(HttpServletRequest?request,?HttpServletResponse?response)??
  • ?throws?Exception?{??
  • ????????HandlerExecutionChain?chain?=?handlerMapping.getHandler(request);??
  • ????????final?ModelAndView?model?=?handlerAdapter.handle(request,?response,??
  • ????????????????chain.getHandler());??
  • ????????return?model;??
  • ????}??
  • } ?
  • 這是個(gè)JUnit測(cè)試類,我們可以new Request對(duì)象,來(lái)參與測(cè)試,太方便了。給request指定訪問(wèn)的URL,就可以請(qǐng)求目標(biāo)Action了。

    Java代碼??

  • package?test.com.app.user;??
  • import?org.junit.Assert;??
  • import?org.junit.Test;??
  • import?org.springframework.mock.web.MockHttpServletRequest;??
  • import?org.springframework.mock.web.MockHttpServletResponse;??
  • import?org.springframework.web.servlet.ModelAndView;??
  • ??
  • import?test.JUnitActionBase;??
  • ??
  • /**??
  • *?說(shuō)明:?測(cè)試OrderAction的例子?
  • *??
  • *?@author??胡晟源??
  • *?@version?創(chuàng)建時(shí)間:2013-2-2?下午10:26:55???
  • */???
  • ??
  • public?class?TestOrderAction?extends?JUnitActionBase?{??
  • ????@Test??
  • ????public?void?testAdd()?throws?Exception?{??
  • ????MockHttpServletRequest?request?=?new?MockHttpServletRequest();??
  • ????????MockHttpServletResponse?response?=?new?MockHttpServletResponse();??
  • ????????request.setServletPath("/order/add");??
  • ????????request.addParameter("id",?"1002");??
  • ????????request.addParameter("date",?"2010-12-30");??
  • ????????request.setMethod("POST");??
  • ????????//?執(zhí)行URI對(duì)應(yīng)的action??
  • ????????final?ModelAndView?mav?=?this.excuteAction(request,?response);??
  • ????????//?Assert?logic??
  • ????????Assert.assertEquals("order/add",?mav.getViewName());??
  • ????????String?msg=(String)request.getAttribute("msg");??
  • ????????System.out.println(msg);??
  • ????}??
  • }??
  • ?需要說(shuō)明一下?:由于當(dāng)前最想版本的Spring(Test) 3.0.5還不支持@ContextConfiguration的注解式context file注入,所以還需要寫個(gè)setUp處理下,否則類似于Tiles的加載過(guò)程會(huì)有錯(cuò)誤,因?yàn)闆](méi)有ServletContext。3.1的版本應(yīng)該有更 好的解決方案,參見:?https://jira.springsource.org/browse/SPR-5243?。

    ?十四、轉(zhuǎn)發(fā)與重定向

    可以通過(guò)redirect/forward:url方式轉(zhuǎn)到另一個(gè)Action進(jìn)行連續(xù)的處理。

    可以通過(guò)redirect:url 防止表單重復(fù)提交?。

    寫法如下:

    return "forward:/order/add";

    return "redirect:/index.jsp";

    ?十五、處理ajax請(qǐng)求

    1、引入下面兩個(gè)jar包,我用的是1.7.2,好像1.4.2版本以上都可以,下載地址:http://wiki.fasterxml.com/JacksonDownload

    jackson-core-asl-1.7.2.jar?

    jackson-mapper-asl-1.7.2.jar

    2、spring的配置文件中要有這一行,才能使用到spring內(nèi)置支持的json轉(zhuǎn)換。如果你手工把POJO轉(zhuǎn)成json就可以不須要使用spring內(nèi)置支持的json轉(zhuǎn)換。

    <mvc:annotation-driven />

    3、使用@ResponseBody注解

    Java代碼??

  • /**?
  • ?*?ajax測(cè)試?
  • *?http://127.0.0.1/mvc/order/ajax?
  • ?*/??
  • ??
  • @RequestMapping("/ajax")??
  • @ResponseBody??
  • public?Object?ajax(HttpServletRequest?request){??
  • ????List<String>?list=new?ArrayList<String>();??
  • ????list.add("電視");??
  • nbsp;???????list.add("洗衣機(jī)");??
  • ????list.add("冰箱");??
  • ????list.add("電腦");??
  • ????list.add("汽車");??
  • ????list.add("空調(diào)");??
  • ????list.add("自行車");??
  • ????list.add("飲水機(jī)");??
  • ????list.add("熱水器");??
  • ????return?list;??
  • }??
  • 十六、關(guān)于寫幾個(gè)配置文件的說(shuō)明?

    我看到有的人把配置文件寫兩份:
    一個(gè)是原有的applicationContext.xml,這個(gè)文件從spring2.0-2.5時(shí)一直在使用。
    別一個(gè)是新加的spring MVC的配置文件。
    其實(shí)這兩個(gè)文件是可以寫成一個(gè)文件的,springMVC相關(guān)的配置,數(shù)據(jù)源,事務(wù)相關(guān)配置可以都寫再一個(gè)配置文件中。
    本例子中只使用了一個(gè)spring配置文件叫“springMVC.xml”。
    就不要再多配置一個(gè)applicationContext.xml文件了。
    web.xml文件中也不要再配置org.springframework.web.context.ContextLoaderListener的listener了。
    寫兩個(gè)配置文件spring會(huì)掃描兩次。

    寫兩個(gè)配置文件還出現(xiàn)事務(wù)不好使的現(xiàn)象,是當(dāng)把@Transactional寫有Action層時(shí)出現(xiàn)的。
    如果寫兩個(gè)配置文件,先執(zhí)行springMVC.xml(xxx-servlet.xml),后執(zhí)行applicationContext.xml。
    先執(zhí)行springMVC.xml(xxx-servlet.xml)時(shí),由于數(shù)據(jù)源、事務(wù)都配置在applicationContext.xml中,還沒(méi)有執(zhí)行(未準(zhǔn)備好), 所以導(dǎo)致了上面的問(wèn)題。

    十七、如何取得Spring管理的bean?(請(qǐng)用第3種方法)
    1、servlet方式加載時(shí),
    【web.xml】

    Xml代碼??

  • <servlet>??
  • <servlet-name>springMVC</servlet-name>??
  • <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>??
  • <init-param>??
  • <param-name>contextConfigLocation</param-name>??
  • <param-value>classpath*:/springMVC.xml</param-value>??
  • </init-param>??
  • <load-on-startup>1</load-on-startup>??
  • </servlet>??
  • ?spring容器放在ServletContext中的key是org.springframework.web.servlet.FrameworkServlet.CONTEXT.springMVC
    注意后面的springMVC,是你的servlet-name配置的值,注意適時(shí)修改。

    Java代碼??

  • ServletContext?sc=略??
  • WebApplicationContext?attr?=?(WebApplicationContext)sc.getAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.springMVC"); ?
  • 2、listener方式加載時(shí):
    【web.xml】

    Xml代碼??

  • <context-param>??
  • ??<param-name>contextConfigLocation</param-name>??
  • ??<param-value>/WEB-INF/applicationContext</param-value>??
  • </context-param>??
  • ??
  • <listener>??
  • ??<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>??
  • </listener>??
  • ?【jsp/servlet】可以這樣取得

    Java代碼??

  • ServletContext?context?=?getServletContext();??
  • WebApplicationContext?applicationContext??=?WebApplicationContextUtils?.getWebApplicationContext(context); ??
  • 3、通用的方法來(lái)了,神器啊,前的? 1、2兩種方法并不通用,可以拋棄了。
    配置文件中加入:

    Xml代碼??

  • <!--?用于持有ApplicationContext,可以使用SpringContextHolder.getBean('xxxx')的靜態(tài)方法得到spring?bean對(duì)象?-->??
  • <bean?class="com.xxxxx.SpringContextHolder"?lazy-init="false"?/> ?
  • Java代碼??

  • import?org.springframework.context.ApplicationContext;??
  • import?org.springframework.context.ApplicationContextAware;??
  • /**?
  • ?*?以靜態(tài)變量保存Spring?ApplicationContext,?可在任何代碼任何地方任何時(shí)候中取出ApplicaitonContext.?
  • ?*??
  • ?*/??
  • public?class?SpringContextHolder?implements?ApplicationContextAware?{??
  • private?static?ApplicationContext?applicationContext;??
  • ??
  • /**?
  • *?實(shí)現(xiàn)ApplicationContextAware接口的context注入函數(shù),?將其存入靜態(tài)變量.?
  • */??
  • public?void?setApplicationContext(ApplicationContext?applicationContext)?{??
  • SpringContextHolder.applicationContext?=?applicationContext;?//?NOSONAR??
  • }??
  • ??
  • /**?
  • *?取得存儲(chǔ)在靜態(tài)變量中的ApplicationContext.?
  • */??
  • public?static?ApplicationContext?getApplicationContext()?{??
  • checkApplicationContext();??
  • return?applicationContext;??
  • }??
  • ??
  • /**?
  • *?從靜態(tài)變量ApplicationContext中取得Bean,?自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型.?
  • */??
  • @SuppressWarnings("unchecked")??
  • public?static?<T>?T?getBean(String?name)?{??
  • checkApplicationContext();??
  • return?(T)?applicationContext.getBean(name);??
  • }??
  • ??
  • /**?
  • *?從靜態(tài)變量ApplicationContext中取得Bean,?自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型.?
  • */??
  • @SuppressWarnings("unchecked")??
  • public?static?<T>?T?getBean(Class<T>?clazz)?{??
  • checkApplicationContext();??
  • return?(T)?applicationContext.getBeansOfType(clazz);??
  • }??
  • ??
  • /**?
  • *?清除applicationContext靜態(tài)變量.?
  • */??
  • public?static?void?cleanApplicationContext()?{??
  • applicationContext?=?null;??
  • }??
  • ??
  • private?static?void?checkApplicationContext()?{??
  • if?(applicationContext?==?null)?{??
  • throw?new?IllegalStateException("applicaitonContext未注入,請(qǐng)?jiān)赼pplicationContext.xml中定義SpringContextHolder");??
  • }??
  • }??
  • } ?
  • 十八、多視圖控制器

    當(dāng)有jsp,flt (模板)等多種頁(yè)面生成展示方式時(shí),spring默認(rèn)使用的是“視圖解析器鏈”。 真是一個(gè)鏈,所以性能不好,spring會(huì)在“視圖解析器鏈”中順序的查找,直到找到對(duì)應(yīng)的 “視圖解析器” 。jsp視圖解析器一定要寫在最后面,因?yàn)橐坏┱{(diào)用jsp,就向?yàn)g覽器發(fā)出數(shù)據(jù)了,Spring就沒(méi)有機(jī)會(huì)再嘗試下一個(gè)了。

    所以自己寫一個(gè)"多視圖解析器",依靠擴(kuò)展名來(lái)區(qū)分,可一次準(zhǔn)確的選中一個(gè) 視圖解析器,提高性能(會(huì)有多少提高呢?沒(méi)測(cè)試過(guò)).

    下面的例子支持jsp,flt (模板)兩種頁(yè)面生成展示方式,你中以自己添加,支持更多。

    Xml代碼??

  • ???<!--?多視圖處理器?-->??
  • ???<bean?class="com.xxx.core.web.MixedViewResolver">??
  • ????<property?name="resolvers">??
  • ????????<map>??
  • ????????????<entry?key="jsp">??
  • ????????????????<bean?class="org.springframework.web.servlet.view.InternalResourceViewResolver">??
  • ????????????????????<property?name="prefix"?value="/WEB-INF/jsp/"/>??
  • ????????????????????<property?name="viewClass"?value="org.springframework.web.servlet.view.JstlView"></property>??
  • ????????????????</bean>??
  • ????????????</entry>??
  • ????????????<entry?key="ftl">??
  • ????????????????<bean?class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">??
  • ????????????????????<property?name="cache"?value="true"/>??
  • ????????????????????<property?name="contentType"?value="text/html;charset=UTF-8"></property>??
  • ????????????????????<!--?宏命令的支持??-->????
  • ????????????????????<property?name="exposeSpringMacroHelpers"?value="true"/>??
  • ????????????????????<property?name="viewClass"?value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>??
  • ????????????????????<property?name="requestContextAttribute"?value="rc"></property>??
  • ????????????????</bean>??
  • ????????????</entry>??
  • ????????</map>??
  • ????</property>??
  • </bean>??
  • ??
  • <!--?freemarker?config?-->??
  • ???<bean?id="freeMarkerConfigurer"?class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">???
  • ???????<property?name="templateLoaderPath"?value="/WEB-INF/ftl/"?/>???
  • ???????<property?name="freemarkerSettings">???
  • ???????????<props>???
  • ???????????????<prop?key="template_update_delay">5</prop>???
  • ???????????????<prop?key="default_encoding">UTF-8</prop>???
  • ???????????????<prop?key="locale">zh_CN</prop>???
  • ???????????</props>???
  • ???????</property>???
  • ???</bean> ??
  • Java代碼??

  • import?java.util.Locale;??
  • import?java.util.Map;??
  • import?org.springframework.web.servlet.View;??
  • import?org.springframework.web.servlet.ViewResolver;??
  • ??
  • /**??
  • *?說(shuō)明:?多視圖處理器?
  • *??
  • *?@author??胡晟源??
  • *?@version?創(chuàng)建時(shí)間:2013-8-19?上午09:41:09???
  • */???
  • public?class?MixedViewResolver?implements?ViewResolver{??
  • ????private?Map<String,ViewResolver>?resolvers;??
  • ??
  • ????public?void?setResolvers(Map<String,?ViewResolver>?resolvers)?{??
  • ????????this.resolvers?=?resolvers;??
  • ????}??
  • ??????
  • ????public?View?resolveViewName(String?viewName,Locale?locale)?throws?Exception{??
  • ????????int?n=viewName.lastIndexOf(".");??
  • ????????if(n!=-1){??
  • ????????????//取出擴(kuò)展名??
  • ????????????String?suffix=viewName.substring(n+1);??
  • ????????????//取出對(duì)應(yīng)的ViewResolver??
  • ????????????ViewResolver?resolver=resolvers.get(suffix);??
  • ????????????if(resolver==null){??
  • ????????????????throw?new?RuntimeException("No?ViewResolver?for?"+suffix);??
  • ????????????}??
  • ????????????return??resolver.resolveViewName(viewName,?locale);??
  • ????????}else{??
  • ????????????ViewResolver?resolver=resolvers.get("jsp");??
  • ????????????return??resolver.resolveViewName(viewName,?locale);??
  • ????????}??
  • ????}??
  • } ?
  • 十九、?<mvc:annotation-driven />?到底做了什么工作

    一句?<mvc:annotation-driven />實(shí)際做了以下工作:(不包括添加自己定義的攔截器)

    我們了解這些之后,對(duì)Spring3 MVC的控制力就更強(qiáng)大了,想改哪就改哪里。

    Xml代碼??

  • ???<!--?注解請(qǐng)求映射??-->??
  • ???<bean?class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">??????????
  • ????<property?name="interceptors">??
  • ????????<list>????
  • ????????????<ref?bean="logNDCInteceptor"/>???<!--?日志攔截器,這是你自定義的攔截器?-->??
  • ????????????<ref?bean="myRequestHelperInteceptor"/>???<!--?RequestHelper攔截器,這是你自定義的攔截器-->???
  • ????????????<ref?bean="myPermissionsInteceptor"/>??<!--?權(quán)限攔截器,這是你自定義的攔截器-->???
  • ????????????<ref?bean="myUserInfoInteceptor"/>??<!--?用戶信息攔截器,這是你自定義的攔截器-->???
  • ????????</list>??????????
  • ????</property>??????????
  • </bean>?????
  • <bean?class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">??
  • ????<property?name="messageConverters">????
  • ????????<list>????
  • ????????????<ref?bean="byteArray_hmc"?/>????
  • ????????????<ref?bean="string_hmc"?/>????
  • ????????????<ref?bean="resource_hmc"?/>????
  • ????????????<ref?bean="source_hmc"?/>????
  • ????????????<ref?bean="xmlAwareForm_hmc"?/>????
  • ????????????<ref?bean="jaxb2RootElement_hmc"?/>????
  • ????????????<ref?bean="jackson_hmc"?/>????
  • ????????</list>????
  • ????</property>????
  • </bean>????
  • <bean?id="byteArray_hmc"?class="org.springframework.http.converter.ByteArrayHttpMessageConverter"?/><!--?處理..?-->??
  • <bean?id="string_hmc"?class="org.springframework.http.converter.StringHttpMessageConverter"?/><!--?處理..?-->??
  • <bean?id="resource_hmc"?class="org.springframework.http.converter.ResourceHttpMessageConverter"?/><!--?處理..?-->??
  • <bean?id="source_hmc"?class="org.springframework.http.converter.xml.SourceHttpMessageConverter"?/><!--?處理..?-->??
  • <bean?id="xmlAwareForm_hmc"?class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"?/><!--?處理..?-->??
  • <bean?id="jaxb2RootElement_hmc"?class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"?/><!--?處理..?--> ?

  • ?[h1]Bean的id

    ?[h2]Value的值是jsp文件的名稱。

    ?[h3]SuccessView,formView這是固定的。

    ?

    到這里對(duì)springMVC的筆記就整理完了。

    希望整理的這篇文章能夠給予廣大博友帶來(lái)學(xué)習(xí)用處。謝謝

    轉(zhuǎn)載于:https://www.cnblogs.com/ZRJ-boke/p/6445758.html

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的SpringMVC学习笔记整理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。