1. 程式人生 > >SpringMVC(博主轉載老師講義,只圖檢視方便)

SpringMVC(博主轉載老師講義,只圖檢視方便)

Spring-MVC

一、MVC 概述

mvc是軟體開發中非常常見的分層設計,目的是使程式中的程式碼根據負責的功能分離,便於維護,當你更新檢視時,不用修改其他程式碼。

M: Model --  JavaBean 模型
​
V: View --  檢視
​
C: Controller 控制器

二、SpringMVC

Springmvc 是spring 框架的一個模組,用於構建web應用程式,Springmvc是符合mvc設計的一個框架。

 

三、入門案例

  1. 準備依賴

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
            <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
  1. 配置web.xml

     <!-- 字符集編碼過濾器 -->
       <filter>
           <filter-name>CharacterEncodingFilter</filter-name>
           <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
           <init-param>
             <param-name>encoding</param-name>
             <param-value>UTF-8</param-value>
           </init-param>
           <init-param>
              <param-name>forceEncoding</param-name>
              <param-value>true</param-value>
           </init-param>
         </filter>
         <filter-mapping>
           <filter-name>CharacterEncodingFilter</filter-name>
           <url-pattern>/*</url-pattern>
         </filter-mapping>
      
      <!-- 應用程式前端控制器 -->
        <servlet>
            <servlet-name>springDispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>springDispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
  2. 編寫spring-mvc配置檔案 ( spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
              <!-- 掃描控制器所在包 -->
              <context:component-scan base-package="com.xingxue.mvc.controller"/>
              <!-- 開啟註解驅動 -->
              <mvc:annotation-driven/>
              <!-- 對於靜態資源 請求交給容器的預設servlet處理 -->              
              <mvc:default-servlet-handler/>
              <!-- 檢視解析器 -->
              <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/views/"/> <!-- -->
                <property name="suffix" value=".jsp"/>
              </bean>
    </beans>
  3. 編寫控制器

    package com.xingxue.mvc.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    ​
    @Controller
    @RequestMapping("/test/")
    public class HelloController {
    ​
        @RequestMapping("/hello")
        public String test1(  ) {
            return "hello";
        }
    }
  4. 測試

四、請求對映( @RequestMapping )

1、基本請求對映

@RequestMapping("/test/")
public class HelloController {
​
    @RequestMapping("/hello")
    public String test1(  ) {
        return "hello";
    }
}

2、精準請求對映 ( value method param header 對映 Http訊息 )

@RequestMapping(value="/emp",method=RequestMethod.GET)
    public void getEmp() {
        System.out.println("get one resource"+id);
    }
    @RequestMapping(value="/emps",method=RequestMethod.GET)
    public void getEmps() {
        System.out.println("get all resource");
    }
    
    
    @RequestMapping(value="/emp",method=RequestMethod.POST)
    public void save() {
        System.out.println("add one resource");
    }
    @RequestMapping(value="/emp",method=RequestMethod.DELETE)
    public void delete() {
        System.out.println("delete one resource");
    }
    @RequestMapping(value="/emp",method=RequestMethod.PUT)
    public void  update() {
        System.out.println("update one resource");
    }

3、ant請求對映

    @RequestMapping(value="/user/?bc")
    public void abc() {
        System.out.println("abc");
    }
    @RequestMapping(value="/user/*d")
    public void aaa() {
        System.out.println("aaa");
    }
    @RequestMapping(value="/user/**/sb")
    public void bbb() {
        System.out.println("bbb");
    }
    @RequestMapping(value="/user/**/?mvc*")
    public void ccc() {
        System.out.println("ccc");
    }

Ant 資源地址支援3種統配符

:資源名字中一個任意字元

* : 資源名字中的任意個字元

** : 匹配多層路徑

4、@PathVariable 註解

通過 @PathVariable 可以將 URL 中佔位符引數繫結到控 制器處理方法的入參中:URL 中的 {xxx} 佔位符可以通過

@PathVariable("xxx") 繫結到操作方法的入參中。

@RequestMapping(value="/emp/{id}",method=RequestMethod.GET)
    public void getEmp(@PathVariable("id") Integer id) {
        System.out.println("get one resource"+id);
}

五、RestFul風格

REST:即 Representational State Transfer。(資源)表現層狀態轉化。是目前 最流行的一種網際網路軟體架構。它結構清晰、符合標準、易於理解、擴充套件方便, 所以正得到越來越多網站的採用

 • 資源(Resources):網路上的一個實體,或者說是網路上的一個具體資訊。它  可以是一段文字、一張圖片、一首歌曲、一種服務,總之就是一個具體的存在。  可以用一個URI(統一資源定位符)指向它,每種資源對應一個特定的 URI 。要  獲取這個資源,訪問它的URI就可以,因此 URI 即為每一個資源的獨一無二的識  別符。
​
 •  表現層(Representation):把資源具體呈現出來的形式,叫做它的表現層(Representation)。比如,文字可以用 txt 格式表現,也可以用 HTML 格  式、XML 格式、JSON 格式表現,甚至可以採用二進位制格式。
​
 •  狀態轉化(State Transfer):每發出一個請求,就代表了客戶端和伺服器的一  次互動過程。HTTP協議,是一個無狀態協議,即所有的狀態都儲存在伺服器  端。因此,如果客戶端想要操作伺服器,必須通過某種手段,讓伺服器端發生“  狀態轉化”(State Transfer)。而這種轉化是建立在表現層之上的,所以就是 “  表現層狀態轉化”。具體說,就是 HTTP 協議裡面,四個表示操作方式的動  詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET 用來獲  取資源,POST 用來新建資源,PUT 用來更新資源,DELETE 用來刪除資源。

API 示例:

URL HTTP Method 作用
–/order/1 GET :得到 id = 1 的 order
–/order/1 PUT :更新id = 1的 order
–/order POST :新增 order
–/order/1 DELETE :刪除 id = 1的 order
-/orders/1 GET : 1號使用者 全部訂單

SpringMVC對RestFul支援

HiddenHttpMethodFilter:瀏覽器 form 表單只支援 GET  與 POST 請求,而DELETE、PUT 等 method 並不支  持,Spring3.0 添加了一個過濾器,可以將這些請求轉換  為標準的 http 方法,使得支援 GET、POST、PUT 與  DELETE 請求。

配置 HiddenHttpMethodFilter

    <!--  HiddenHttpMethodFilter: 支援restful 風格請求  -->
    <filter>
        <filter-name>RestFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>RestFilter</filter-name>
         <servlet-name>SpringMVC</servlet-name>
    </filter-mapping>

六、獲取請求資料

1、簡單資料型別

 @RequestMapping("t1")
    public void test1(String name,int age ) {
        System.out.println("you input is "+name+ "\t" + age );
    }

測試:http://localhost;8080/spring-web/params/t1?name=admin&age=11

2、pojo資料型別(支援級聯屬性注入)

    @RequestMapping("t2")
    public void test2(User u) {
        System.out.println(u);
    }
----------------------------------------------------------------------------------------------
public class User {
    private String username;
    private int age;
    private Company company;
    //省略get set 
}
public class Company{
    private String cname;
    private String address;
    private String phone;
    //省略get set方法
}

測試:http://localhost;8080/spring-web/params/t2?username=admin&age=11&company.cname=baidu&company.address=beijing&company.phone=010-666666

3、@RequestParam

(此註解目的是 把請求引數繫結到入參 主要解決前後引數名字不一致的情況)

    @RequestMapping("t3")
    public void test3(@RequestParam(value="fullname",required=true)String name,@RequestParam(value="phone")String tel ) {
         System.out.println("名字:"+name);
         System.out.println("電話:"+tel);
    }

測試:http://localhost:8080/spring-mvc/params/t3?fullname=kangkang&phone=188xxxxxx

4、@RequestHeader(獲得請求頭資訊) @CookieValue(獲得Cookie資訊)

@RequestMapping("t4")
    public void test4(@RequestHeader(value="connection",required=false)String header, @CookieValue(value="JSESSIONID",required=false) String sessid ) {
        System.out.println("Connection:"+header);
        System.out.println("sessionid:"+sessid);
    }

5、使用Servlet API作為入參

    @RequestMapping("t5")
    public void test5(HttpServletRequest req,HttpServletResponse resp, HttpSession session) throws IOException {
        String n=req.getParameter("name");
        resp.getWriter().write(n);
        resp.getWriter().flush();
        
    }

以下是方法支援的 型別

•HttpServletRequest

•HttpServletResponse

•HttpSession

•java.security.Principal

•Locale

•InputStream

•OutputStream

•Reader

•Writer

總結:SpringMVC控制器方法入參非常靈活

七、頁面渲染

  • ModelAndView

    直接翻譯為 模型和資料,其作用是儲存模型和資料,最終目的是把模型資料( Model )帶到檢視(View)中展現

        @RequestMapping("t6")
            public ModelAndView t6() {
                ModelAndView mv = new ModelAndView();
                mv.getModel().put("company", "baidu");
                mv.getModel().put("phone", "010-666666");
                mv.setViewName("hello");
                return mv;
        }
  • Model

    直接翻譯為 模型,其作用是提供資料,但是也僅僅提供資料,不參與跳轉檢視,跳轉檢視需要 return 確定,此Model不需要開發者手動建立,只需要宣告在方法的入參中即可,它由框架建立和注入以及傳送到檢視

        @RequestMapping("t7")
        public String  t7(  Model md ) {
            md.addAttribute("company", "tengxun");
            md.addAttribute("phone", "010=888888");
            return "hello";
        }
  • ModelMap Map

    其作用和使用方法 與Model一致

        @RequestMapping("t8")
        public String  t8(ModelMap mp) {
            mp.addAttribute("company", "alibaba");
            mp.addAttribute("phone", "010-999999");
            return "hello";
        }
        
        @RequestMapping("t9")
        public String  t9(Map<String,Object> mp) {
            mp.put("company", "oralce");
            mp.put("phone", "010-555555");
            return "hello"; 
        }
     測試效果:
      
      ![1535214218514](C:\Users\ADMINI~1\AppData\Local\Temp\1535214218514.png)

 

八、轉發和重定向

   區別:轉發一次請求,瀏覽器上地址不變
​
        重定向兩次請求,瀏覽器地址改變
    /*重定向到jsp*/
    @RequestMapping("/t10")
    public  String  t10(){
           return  "redirect:/static/jsp/add.jsp";
    }
    /*轉發向到jsp*/
    @RequestMapping("/t10")
    public  String  t10(){
           return  "forward:/static/jsp/add.jsp";
    }
    /*重定向到controller*/
    @RequestMapping("/t11")
    public  String  t11(){
        return  "redirect:/param/t9";
    }
    /*轉發到控制器controller*/
    @RequestMapping("/t12")
    public  String  t12( ){
        return  "forward:/param/t8";
    }

SpringMVC 預設採取的方式是轉發

重定向: redirect:/xxx

轉發:forward:/xxx

 

九、處理JSON資料

   當前端請求方法後不需要跳轉頁面,而只是需要json資料,這時可以使用@ResponseBody註解,該註解的作用是把控制器方法的返回值 通過訊息轉換器 HttpMessageConverter 自動把方法的返回值 新增 到HttpResponse 響應訊息的body中。為此我們需要新增 json依賴
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.7</version>
</dependency>

還需要開啟註解驅動 ,

 <mvc:annotation-driven/>

•<mvc:annotation-driven /> 會自動注 冊RequestMappingHandlerMapping

、RequestMappingHandlerAdapter 與

ExceptionHandlerExceptionResolver 三個bean。

• 還將提供以下支援:

–支援使用 ConversionService 例項對錶單引數進行型別轉換

–支援使用 @NumberFormat annotation、@DateTimeFormat

註解完成資料型別的格式化

– 支援使用 @Valid 註解對 JavaBean 例項進行 JSR 303 驗證

–支援使用 @RequestBody 和 @ResponseBody 註解

    @RequestMapping("/json")
    @ResponseBody()
    public User t11() {
        
        User user = new User();
        user.setUsername("admin");
        user.setAge(10);
        
        Address  addr= new Address();
        addr.setXian("奉節縣");
        addr.setXiang("石崗鄉");
        addr.setSheng("重慶市");
        user.setAddr(addr );
        return user;
    }
{"username":"admin","age":10,"addr":{"sheng":"重慶市","xian":"奉節縣","xiang":"石崗鄉"}}

十、檔案上傳

依賴

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.5</version>
    </dependency>

①準備上傳html頁面

<form action="/file/upload" method="post" enctype="multipart/form-data">
    <input name="file" type="file">
   <input type="submit" value="上傳" />
</form>

②準備控制器接受檔案

@Controller
@RequestMapping("/file")
public class FileController {
​
    @RequestMapping("/upload")
    public  String  fileUpoad(MultipartFile file, HttpServletRequest request){
        System.out.println(file);
        String path=request.getServletContext().getRealPath("/")+"upload\\";
        File f= new File(path);
        if(!f.exists()){
            f.mkdirs();
        }
        try {
            //儲存檔案方法   /d:/abc/mvc/upload/abc.png
            file.transferTo(  new File(f,   file.getOriginalFilename() ) );
        } catch (IOException e) {
            return "error";
        }
        System.out.println("ok...................");
        return "success";
    }
}

③sping配置

    <!--檔案上傳配置-->
    <bean id="multipartResolver"                                class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
                <property name="defaultEncoding" value="UTF-8"/>
                <property name="maxUploadSize" value="104857600"/>
    </bean>

十 一、攔截器

1 、什麼是攔截器?

Spring MVC中的攔截器(Interceptor)類似於Servlet中的過濾器(Filter),它主要用於攔截使用者請求並作相應的處理。例如通過攔截器可以進行許可權驗證、記錄請求資訊的日誌、判斷使用者是否登入等。要使用Spring MVC中的攔截器,就需要對攔截器類進行定義和配置。通常攔截器類可以通過兩種方式來定義。通過實現HandlerInterceptor介面,或繼承HandlerInterceptor介面的實現類(如HandlerInterceptorAdapter)來定義。

2、實現攔截器

①編寫攔截器程式碼

以實現HandlerInterceptor介面方式為例,自定義攔截器類的程式碼如下:

public class CustomInterceptor implements HandlerInterceptor{
        public boolean preHandle(HttpServletRequest request, 
                                 HttpServletResponse response, Object handler)throws Exception {
            System.out.println("開始攔截....");
            return false;
        }
        public void postHandle(HttpServletRequest request, 
                               HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
             System.out.println("結束攔截....");
            
        }
        public void afterCompletion(HttpServletRequest request,
                                    HttpServletResponse response, Object handler,
                                    Exception ex) throws Exception {
             System.out.println("整個攔截過程完成");
        }
    }
  • preHandle() 方法:該方法會在控制器方法前執行,其返回值表示是否中斷後續操作。當其返回值為true時,表示繼續向下執行;當其返回值為false時,會中斷後續的所有操作(包括呼叫下一個攔截器和控制器類中的方法執行等)。

  • postHandle()方法:該方法會在控制器方法呼叫之後,且解析檢視之前執行。可以通過此方法對請求域中的模型和檢視做出進一步的修改。

  • afterCompletion()方法:該方法會在整個請求完成,即檢視渲染結束之後執行。可以通過此方法實現一些資源清理、記錄日誌資訊等工作。

② 註冊和配置攔截器

<!--配置攔截器-->
<mvc:interceptors>
        <!-- 直接註冊 interceptors 下的攔截器為全域性的攔截器  -->
        <!--<bean class="com.ma.interceptor.CustomeInterceptor" />--> 
        <!--攔截器1-->
        <mvc:interceptor>
            <!--配置攔截器的作用路徑-->
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path=""/>
            <!--定義在<mvc:interceptor>下面的表示匹配指定路徑的請求才進行攔截-->
            <bean class="com.ma.interceptor.Intercptor1"/>
        </mvc:interceptor>
        <!--攔截器2-->
        <mvc:interceptor>
            <mvc:mapping path="/hello"/>
            <bean class="com.ma.interceptor.Interceptor2"/>
        </mvc:interceptor>
</mvc:interceptors>

上面的程式碼中,mvc:interceptors元素用於配置一組攔截器,基子元素<bean>中定義的是全域性攔截器,它會攔截所有的請求;而mvc:interceptor元素中定義的是指定路徑的攔截器,它會對指定路徑下的請求生效。mvc:interceptor元素的子元素mvc:mapping用於配置攔截器作用的路徑,該路徑在其屬性path 中定義。如上述程式碼中 path 的屬性值“/**” 表示攔截所有路徑,“/hello” 表示攔截所有以 “/hello” 結尾的路徑。如果在請求路徑中包含不需要攔截的內容,還可以通過mvc:exclude-mapping元素進行配置。

③ 測試

 

3、攔截器 執行流程

請求 --> preHandle(前置處理) --> target(控制器方法) --> postHandle(後置處理) --> dispatcherServlet(渲染頁面) --> afterCompletion(結束處理)

十二、異常處理

在實際開發過程中,我們通常會把應用後端分為3層來開發,Controller(控制器) Service(服務層) Dao(資料訪問層),這3層都可能會有異常的發生,通常的做法是把異常,由 DAO 拋到 Service 再拋到 Controller,最後再控制其中處理異常。這樣可以把異常反饋給最頂層呼叫者處理。但是一個系統中有若干個Controller ,若干個方法,處理異常就變得十分難受了,Springmvc提供了一種全域性異常處理機制,允許我們在一個類中集中處理異常,控制器不需理會異常。

實現異常處理方式一:

  @ExceptionHandler({IOException.class,NullPointerException.class } )
  public String  excpetionHandle(){
           return "error";
  }

註解中的異常型別可以給 單個 或 多個

這種處理方式,比較侷限,只能處理當前 Controller中的異常

實現全域性異常處理方式一:

①實現 HandlerExceptionResolver 介面

//確保 AppGolablException 例項加入IOC容器中  可以用xml配置和註解配置
@Component
public class AppGolablException  implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //這裡無論什麼異常都到 error 頁面去
        //當然這裡可以根據實際的異常型別做 不同的響應
        ModelAndView mv = new ModelAndView("error");
        return mv;
    }
}

②丟擲異常

    @RequestMapping("/ex")
    public  String  testex(){
           throw  new NullPointerException("hehe");
    }
    @RequestMapping("/ex2")
    public  String  textex2() throws  Exception{
           throw  new IOException("haha");
    }

這時請求 ex 和 ex2 方法都會跳轉到 error頁面

 

實現全域性異常處理方式二: @ControllerAdvice + @ExceptionHandler

①編寫異常處理程式碼

@ControllerAdvice
public class AppException {
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Object handleHttpMessageNotReadableException(Exception e) {
        System.out.println("------------");
        return   "50X";
     }
}

②控制器丟擲異常

    @RequestMapping("/ex")
    public  String  testex(){
           throw  new NullPointerException("hehe");
    }
    @RequestMapping("/ex2")
    public  String  textex2() throws  Exception{
           throw  new IOException("haha");
    }