Spring mvc

Spring mvc 框架

  • DispatcherServlet

    前端控制器 ---- 整個(gè)流程控制的中心,由它調(diào)用其它組件處理用戶的請(qǐng)求

  • 三大組件

    • HandlerMapping

      處理器映射器 ---- 根據(jù)用戶請(qǐng)求url找到處理器(Handler),springmvc提供了不同的映射器實(shí)現(xiàn)不同的映射方式,例如:配置文件方式,實(shí)現(xiàn)接口方式,注解方式等

    • HandlAdapter

      處理器適配器 ---- 通過HandlerAdapter對(duì)處理器進(jìn)行執(zhí)行,通過擴(kuò)展適配器可以對(duì)更多類型的處理器進(jìn)行執(zhí)行

    • ViewResolver

      視圖解析器 ---- 負(fù)責(zé)將處理結(jié)果生成View視圖,View Resolver首先根據(jù)邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對(duì)象,最后對(duì)View進(jìn)行渲染將處理結(jié)果通過頁面展示給用戶

  • Handler

    處理器 ---- 繼DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler對(duì)具體的用戶請(qǐng)求進(jìn)行處理

    默認(rèn)支持的參數(shù)類型

    • HttpServletRequest

      通過request對(duì)象獲取請(qǐng)求信息

    • HttpServletResponse

      通過response處理響應(yīng)信息

    • HttpSession

      通過session對(duì)象得到session中存放的對(duì)象

  • View

    視圖 ---- springmvc框架提供了很多的View視圖類型的支持,包括:jstlView、freemarkerView、pdfView等。我們最常用的視圖就是jsp

    視圖對(duì)象

    • ModelAndView

    • Model

      Model是一個(gè)接口,在參數(shù)里直接聲明model即可,Model對(duì)象可以向頁面?zhèn)鬟f數(shù)據(jù),View對(duì)象則可以使用String返回值替代

    • ModelMap

      ModelMap是Model接口的實(shí)現(xiàn)類,也可以通過ModelMap向頁面?zhèn)鬟f數(shù)據(jù),使用Model和ModelMap的效果一樣,如果直接使用Model,springmvc會(huì)實(shí)例化ModelMap

配置

  • web.xml

    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee                                   http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
        <!-- 指定Spring 配置文件位置 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </context-param>
        <!-- Spring隨服務(wù)器啟動(dòng)而啟動(dòng) -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <!--spring mvc 前端控制器-->
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- spring MVC配置文件 -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:dispatcher-servlet.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <!-- /* 攔截所有jsp js png css 全部攔截 -->
            <!-- *.action *.do 攔截已a(bǔ)ction,do結(jié)尾的請(qǐng)求 -->
            <!-- /* 攔截所有(不包含jsp)(包含js png css) -->
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • dispatcher-servlet.xml

    <!-- 組件掃描器,自動(dòng)掃描注解組件 -->
    <!-- 配置掃描包,多個(gè)包之間用,分隔 -->
    <context:component-scan base-package="com.lirui.springmvc"/>
    
    <!-- 處理器映射器 -->
    <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>-->
    <!-- 處理器適配器 -->
    <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
    
    <!-- 注解驅(qū)動(dòng),代替以上兩種方式 -->
    <mvc:annotation-driven />
    
    <!-- 視圖解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置邏輯視圖的前綴 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 配置邏輯視圖的后綴 -->
        <property name="suffix" value=".jsp"/>
        <!-- 前綴+邏輯視圖名+后綴 -->
    </bean>
    
  • 定義controller

    @Controller
    public class Test1Controller {
        @RequestMapping("/test1")
        public ModelAndView getList() {
            ModelAndView mav = new ModelAndView();
            mav.addObject("key", request域中的數(shù)據(jù));
            mav.setViewName("視圖路徑");
            return mav;
        }
    

Handler支持的參數(shù)類型

  • 默認(rèn)支持的參數(shù)類型

    • HttpServletRequest

      通過request對(duì)象獲取請(qǐng)求信息

    • HttpServletResponse

      通過response處理響應(yīng)信息

    • HttpSession

      通過session對(duì)象得到session中存放的對(duì)象

  • 綁定簡單類型

    當(dāng)請(qǐng)求的參數(shù)名稱和處理器形參名稱一致時(shí)會(huì)將請(qǐng)求參數(shù)與形參進(jìn)行綁定,可以使用@RequestParam處理簡單類型的綁定

    @RequestParam(value = "name",required = true,defaultValue = "value")

    ? value:參數(shù)名稱,即入?yún)⒌恼?qǐng)求參數(shù)名字

    ? required :是否必須,默認(rèn)是true,表示請(qǐng)求中一定要有相應(yīng)的參數(shù),否則將報(bào)錯(cuò)

    ? defaultValue :默認(rèn)值

  • 綁定pojo對(duì)象

    如果提交的參數(shù)很多,或者提交的表單中的內(nèi)容很多的時(shí)候,可以使用簡單類型接受數(shù)據(jù),也可以使用pojo接收數(shù)據(jù)。pojo對(duì)象中的屬性名和表單中input的name屬性一致

  • 綁定包裝pojo對(duì)象

  • 自定義參數(shù)綁定

    實(shí)現(xiàn)參數(shù)格式的修改,例如由于日期數(shù)據(jù)有很多種格式,springmvc沒辦法把字符串轉(zhuǎn)換成日期類型。所以需要自定義參數(shù)綁定

    • 自定義Converter

      實(shí)現(xiàn)Converter接口

    • 配置

      方式一

      <!-- 配置注解驅(qū)動(dòng) -->
      <!-- 如果配置此標(biāo)簽,可以不用配置... -->
      <mvc:annotation-driven conversion-service="conversionService" />
      
      <!-- 轉(zhuǎn)換器配置 -->
      <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
          <property name="converters">
              <set>
                  <bean class="cn.itcast.springmvc.converter.DateConverter" />
              </set>
          </property>
      </bean>
      

      方式二

      <!--注解適配器 -->
      <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
          <property name="webBindingInitializer" ref="customBinder"></property>
      </bean>
      
      <!-- 自定義webBinder -->
      <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
          <property name="conversionService" ref="conversionService" />
      </bean>
      
      <!-- 轉(zhuǎn)換器配置 -->
      <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
          <property name="converters">
              <set>
                  <bean class="cn.itcast.springmvc.convert.DateConverter" />
              </set>
          </property>
      </bean>
      //此方法需要獨(dú)立配置處理器映射器、適配器,不再使用<mvc:annotation-driven/>
      
  • 高級(jí)參數(shù)綁定

    • 數(shù)組

      提交的數(shù)組,可以直接使用數(shù)組接收,或者pojo的數(shù)組屬性接收。兩種方式任選其一即可

    • list

      jsp頁面name屬性必須是list屬性名+下標(biāo)+元素屬性

      接收List類型的數(shù)據(jù)必須是pojo的屬性,如果方法的形參為ArrayList類型無法正確接收到數(shù)據(jù)

@RequestMapping()注解

  • URL路徑映射

    @RequestMapping(value="xxx")或@RequestMapping("/xxx"),value的值是數(shù)組,可以將多個(gè)url映射到同一個(gè)方法,例如:@RequestMapping(value = { "xxx", "xxxx" })

  • 添加在類上面

    在class上添加@RequestMapping(url)指定通用請(qǐng)求前綴, 限制此類下的所有方法請(qǐng)求url必須以請(qǐng)求前綴開頭

  • 請(qǐng)求方法限定

    限定GET方法:@RequestMapping(method =RequestMethod.GET)

    限定POST方法:@RequestMapping(method =RequestMethod.POST)

    GET和POST都可以:@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})

Controller方法返回值

  • ModelAndView

    controller方法中定義ModelAndView對(duì)象并返回,對(duì)象中可添加model數(shù)據(jù)、指定view

  • Void

    在Controller方法形參上可以定義request和response,使用request或response指定響應(yīng)結(jié)果

    • 使用request轉(zhuǎn)發(fā)頁面

      request.getRequestDispatcher("頁面路徑").forward(request,response);

    • 可以通過response頁面重定向:

      response.sendRedirect("url")

    • 可以通過response指定響應(yīng)結(jié)果,例如響應(yīng)json數(shù)據(jù)如下:

      response.getWriter().print("{\"abc\":123}");

  • String

    controller方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析為物理視圖地址

    • Redirect重定向

      return "redirect:xxx"

    • forward轉(zhuǎn)發(fā)

      return "forward:xxx"

異常處理

? 系統(tǒng)中異常包括兩類:預(yù)期異常和運(yùn)行時(shí)異常RuntimeException,前者通過捕獲異常從而獲取異常信息,后者主要通過規(guī)范代碼開發(fā)、測試通過手段減少運(yùn)行時(shí)異常的發(fā)生。

? 系統(tǒng)的dao、service、controller出現(xiàn)都通過throws Exception向上拋出,最后由springmvc前端控制器交由異常處理器(HandlerExceptionResolver)進(jìn)行異常處理。

  • 自定義異常處理器

    實(shí)現(xiàn)接口HandlerExceptionResolver

    public class CustomHandlerExceptionResolver implements HandlerExceptionResolver {
        @Nullable
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest,                   HttpServletResponse httpServletResponse, @Nullable Object o, Exception e) {
            String msg;
            if (e instanceof CustomException) {
                msg = ((CustomException) e).getMsg();
            } else {
                msg = e.getMessage();
            }
            ModelAndView mav = new ModelAndView();
            mav.addObject("error", msg);
            mav.setViewName("error");
            return mav;
        }
    }
    
  • 配置

    //dispatcher-servlet.xml文件
    <!-- 配置異常處理器 -->
    <bean class="com.lirui.springmvc.exeception.CustomHandlerExceptionResolver"/>
    

上傳圖片

  • 配置虛擬目錄

    在tomcat上配置圖片虛擬目錄,在tomcat下conf/server.xml中添加:

    <Context docBase="D:\develop\upload\temp"path="/pic" reloadable="false"/>

    訪問http://localhost:8080/pic即可訪問D:\develop\upload\temp下的圖片。也可以通過

    eclipse配置

  • 加入jar文件

    commons-fileupload.jar commons-io.jar

  • 修改jsp頁面,添加enctype="multipart/form-data"

  • 采用參數(shù)MultipartFile pictureFile接收文件,pictureFile名稱與jsp文件上傳控件name名稱一致

    String fileName = UUID.randomUUID().toString().replace("-", "");
    String pictureName = pictureFile.getOriginalFilename();
    String type = FilenameUtils.getExtension(pictureName);
    fileName = fileName + "." + type;
    pictureFile.transferTo(new File("E:\\Learn\\pic\\" + fileName));
    
  • 配置文件上傳解析器

    //dispatcher-servlet.xml
    <!-- 文件上傳,id必須設(shè)置為multipartResolver -->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 設(shè)置文件上傳大小 -->
        <property name="maxUploadSize" value="5000000" />
    </bean>
    

Json解析

  • 注解

    @RequestBody ---- 用于讀取http請(qǐng)求的內(nèi)容(字符串),通過springmvc提供的HttpMessageConverter接口將讀到的內(nèi)容(json數(shù)據(jù))轉(zhuǎn)換為java對(duì)象并綁定到Controller方法的參數(shù)上

    @ResponseBody ---- 用于將Controller的方法返回的對(duì)象,通過springmvc提供HttpMessageConverter接口轉(zhuǎn)換為指定格式的數(shù)據(jù)如:json,xml等,通過Response響應(yīng)給客戶端

  • 添加json解析器

    如果不使用注解驅(qū)動(dòng)<mvc:annotation-driven/>,就需要給處理器適配器配置json轉(zhuǎn)換器

    在springmvc.xml配置文件中,給處理器適配器加入json轉(zhuǎn)換器:

    <!--處理器適配器 -->
    <bean class=*"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"*>
      <property name="messageConverters">
          <list>
              <bean                                       class=*"org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"*>
              </bean>
              </list>
      </property>
    </bean>
    

RESTful支持

使用注解@RequestMapping("item/{id}")聲明請(qǐng)求的url,{xxx}叫做占位符,請(qǐng)求的URL可以是“item /1”或“item/2”

使用(@PathVariable() Integer id)獲取url上的數(shù)據(jù)

如果@RequestMapping中表示為"item/{id}",id和形參名稱一致,@PathVariable不用指定名稱。如果不一致,例如"item/{ItemId}"則需要指定名稱@PathVariable("itemId")。

  1. @PathVariable是獲取url上數(shù)據(jù)的。@RequestParam獲取請(qǐng)求參數(shù)的(包括post表單提交)
  1. 如果加上@ResponseBody注解,就不會(huì)走視圖解析器,不會(huì)返回頁面,目前返回的json數(shù)據(jù)。如果不加,就走視圖解析器,返回頁面

攔截器

Spring Web MVC 的處理器攔截器類似于Servlet 開發(fā)中的過濾器Filter,用于對(duì)處理器進(jìn)行預(yù)處理和后處理

  • 攔截器定義(實(shí)現(xiàn)HandlerInterceptor接口)

    public class HandlerInterceptor1 implements HandlerInterceptor {
      // controller執(zhí)行后且視圖返回后調(diào)用此方法
      // 這里可得到執(zhí)行controller時(shí)的異常信息
      // 這里可記錄操作日志
      @Override
      public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object           arg2, Exception arg3) throws Exception {}
    
      // controller執(zhí)行后但未返回視圖前調(diào)用此方法
      // 這里可在返回用戶前對(duì)模型數(shù)據(jù)進(jìn)行加工處理,比如這里加入公用信息以便頁面顯示
      @Override
      public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,          ModelAndView arg3) throws Exception {}
    
      // Controller執(zhí)行前調(diào)用此方法
      // 返回true表示繼續(xù)執(zhí)行,返回false中止執(zhí)行
      // 這里可以加入登錄校驗(yàn)、權(quán)限攔截等
      @Override
      public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2)        throws Exception {
              return true;
          }
    }
    
    

    ?

  • 攔截器配置

    <!-- 配置攔截器 -->
    <mvc:interceptors>
      <mvc:interceptor>
          <!-- 所有的請(qǐng)求都進(jìn)入攔截器 -->
          <mvc:mapping path="/**" />
          <!-- 配置具體的攔截器 -->
          <bean class="xxx" />
      </mvc:interceptor>
      <mvc:interceptor>
          <!-- 所有的請(qǐng)求都進(jìn)入攔截器 -->
          <mvc:mapping path="/**" />
          <!-- 配置具體的攔截器 -->
          <bean class="xxx" />
      </mvc:interceptor>
    </mvc:interceptors>
    
  • 攔截器處理流程

    preHandle按攔截器定義順序調(diào)用

    postHandler按攔截器定義逆序調(diào)用

    afterCompletion按攔截器定義逆序調(diào)用

    ?

    postHandler在攔截器鏈內(nèi)所有攔截器返成功調(diào)用

    afterCompletion只有preHandle返回true才調(diào)用

springmvc與struts2不同

  • springmvc的入口是一個(gè)servlet即前端控制器,而struts2入口是一個(gè)filter過濾器。
  • springmvc是基于方法開發(fā)(一個(gè)url對(duì)應(yīng)一個(gè)方法),請(qǐng)求參數(shù)傳遞到方法的形參,可以設(shè)計(jì)為單例或多例(建議單例),struts2是基于類開發(fā),傳遞參數(shù)是通過類的屬性,只能設(shè)計(jì)為多例。
  • Struts采用值棧存儲(chǔ)請(qǐng)求和響應(yīng)的數(shù)據(jù),通過OGNL存取數(shù)據(jù), springmvc通過參數(shù)解析器是將request請(qǐng)求內(nèi)容解析,并給方法形參賦值,將數(shù)據(jù)和視圖封裝成ModelAndView對(duì)象,最后又將ModelAndView中的模型數(shù)據(jù)通過request域傳輸?shù)巾撁妗sp視圖解析器默認(rèn)使用jstl
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,694評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,690評(píng)論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,019評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,188評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,718評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,438評(píng)論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,667評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,845評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評(píng)論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,384評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,635評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容