天天看點

02 springMVC 響應 檔案上傳 異常處理 攔截器響應檔案上傳異常處理攔截器

目錄

響應

傳回值是String類型

傳回值為空

傳回值是ModelAndView

使用forward和redirect關鍵字進行頁面跳轉

響應json資料

過濾靜态資源

發送ajax請求

響應json格式資料

檔案上傳

必要前提

修改form表單屬性enctype為multipart/form-data

method屬性必須是post

傳統方法的檔案上傳

springMVC方式上傳

原理圖

配置檔案解析器對象

控制器方法

跨伺服器檔案上傳

異常處理

分析

代碼編寫

編寫自定義異常類

編寫異常處理類

配置異常處理器

攔截器

概念

入門代碼

編寫攔截器的類

配置攔截器

HandlerInterceptor接口方法介紹

postHandle()

afterCompletion()

多個攔截器之間的攔截順序

攔截順序規則(個人見解)

  1. 響應

    1. 傳回值是String類型

      1. 常用
      2. springMVC會根據視圖解析器中的字首和字尾去尋找對應的頁面資源檔案
      3. 如果你想傳回的頁面在視圖解析器理面沒有配置, 那麼你就需要自己手動使用重定向或轉發了
    2. 傳回值為空

      1. springMVC預設會去通路請求路徑下面的頁面檔案, 但一般不這麼使用
      2. 需要自己使用重定向或轉發來跳轉頁面
    3. 傳回值是ModelAndView

      1. 不常用
      2. 存儲資料使用方法addObject()
        1. 底層使用的依舊是ModelMap
      3. 跳轉頁面使用的是方法setViewName
        1. 底層使用的是視圖解析器
      4. 當我們使用傳回值是String的跳轉方式時, 底層使用的依舊是ModelAndView方式
      5. /**
         * @return 傳回值是ModelAndView類型
         */
        @RequestMapping("/ModelAndView")
        public ModelAndView test02() {
            ModelAndView modelAndView = new ModelAndView();
            User user = new User("李乾1", "123", 23);
            //存儲資料
            modelAndView.addObject("user", user);
            //設定要跳轉的頁面
            modelAndView.setViewName("success");
            return modelAndView;
        }
                   
    4. 使用forward和redirect關鍵字進行頁面跳轉

      1. 用得不多
      2. /**
         * 使用關鍵字進行頁面跳轉
         *
         * @return
         */
        @RequestMapping("/ForwardOrRedirect")
        public String ForwardOrRedirect() {
            // return "forward:/WEB-INF/pages/success.jsp";
            return "redirect:/index.jsp";// 不需要寫虛拟路徑, springMVC會自動幫你寫虛拟路徑
        }
                   
    5. 響應json資料

      1. 過濾靜态資源

        1. 前端控制器dispatcherServlet預設會攔截所有的靜态資源
        2. 需要告訴前端控制器那些靜态資源不要攔截
          1. springmvc.xml中配置
          2. <!--告訴前端控制器不要攔截那些資源-->
            <!--<mvc:resources location="/css/" mapping="/css/**"/>-->
            <!--<mvc:resources location="/images/" mapping="/images/**"/>-->
            <mvc:resources location="/js/" mapping="/js/**"/>
                       
      2. 發送ajax請求

        1. js表達式
          1. $.ajax({
                url:"user/ajax",//請求的url
                contentType:"application/json;charset=utf-8",//發送的資料格式和字元集編碼
                data:'{"username":"asd","password":"123","age":22}',//json資料
                dataType:"json",//預期伺服器傳回的資料類型
                type:"post",//請求的方式
                success:function (data) {//請求成功之後的回調函數
                    alert(data);
                    alert(data.username)
                    alert(data.password)
                    alert(data.age)
                }
            })
                       
        2. 控制器擷取資料的方式
          1. 請求中的json資料是在請求體中, 是以要給形參添加@RequestBody注解
      3. 響應json格式資料

        1. 第一步需要導入jar包坐标
          1. <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.0</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.9.0</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.9.0</version>
            </dependency>
                       
        2. 給控制器方法中的傳回值添加注解@ResponseBody注解即可
  2. 檔案上傳

    1. 必要前提

      1. 修改form表單屬性enctype為multipart/form-data

        1. 修改之後, 請求體的正文就變成了MIME類型, 我們自己解析比較麻煩, 可以使用第三方的元件Commons-fileupload
        2. jar包坐标
          1. <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.4</version>
            </dependency>
                       
      2. method屬性必須是post

    2. 傳統方法的檔案上傳

      1. 檔案通過request請求發到伺服器, 我們要做的就是, 解析request請求裡面的資料内容, 如果是檔案, 就把它上傳到伺服器
      2. /**
         * 傳統方法的檔案上傳
         *  檔案通過request請求發到伺服器, 我們要做的就是, 解析request請求裡面的資料内容, 如果是檔案, 就把它上傳到伺服器
         *
         * @param request
         * @return
         * @throws Exception
         */
        @RequestMapping("/upload")
        public String upload(HttpServletRequest request) throws Exception {
            //設定上傳的位置, 一般在webapps下面的ROOT檔案夾裡面
            String path = request.getSession().getServletContext().getRealPath("/uploads");
            //判斷該路徑是否存在, 不存在就再建立一個新的
            File file = new File(path);
            if (!file.exists()) {
                //路徑不存在
                file.mkdirs();
            }
            //擷取解析request對象的對象(磁盤檔案項)
            DiskFileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            //解析request對象, 擷取資料項
            List<FileItem> items = upload.parseRequest(request);
            for (FileItem item : items) {
                if (item.isFormField()) {
                    //是普通的表單資料
                } else {
                    //是上傳檔案資料
                    //擷取檔案名
                    //UUID: 保證檔案名字不重複
                    String name = UUID.randomUUID().toString().replaceAll("-", "") + item.getName();
                    item.write(new File(path, name));
                    //删除臨時檔案, 一旦檔案項大于10kb就會産生緩存檔案, 低于10kb的緩存檔案出現在記憶體裡面, 不需要我們管
                    item.delete();
                }
            }
            return "success";
        }
                   
    3. springMVC方式上傳

      1. 需要配置一個檔案解析器
        1. bean的屬性id必須為: multipartResolver
      2. 相比傳統方式的優點
        1. 解析request的操作不需要而我們來做了
      3. 原理圖

        1. 02 springMVC 響應 檔案上傳 異常處理 攔截器響應檔案上傳異常處理攔截器
      4. 配置檔案解析器對象

        1. <!--配置檔案解析器對象-->
          <!--id屬性必須為multipartResolver-->
          <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
              <!--配置上傳檔案大小, 10485769=10MB -->
              <property name="maxUploadSize" value="10485769"></property>
          </bean>
                     
      5. 控制器方法

        1. /**
           * 使用springMVC方式上傳檔案
           *
           * @param request
           * @param upload  此參數名字必須和type屬性為file的input标簽的name屬性值保持一緻
           * @return
           * @throws Exception
           */
          @RequestMapping("/upload")
          public String upload(HttpServletRequest request, MultipartFile upload) throws Exception {
              //設定上傳的位置, 一般在webapps下面的ROOT檔案夾裡面
              String path = request.getSession().getServletContext().getRealPath("/uploads");
              //判斷該路徑是否存在, 不存在就再建立一個新的
              File file = new File(path);
              if (!file.exists()) {
                  //路徑不存在
                  file.mkdirs();
              }
              //擷取檔案名
              //UUID: 保證檔案名字不重複
              //getOriginalFilename(): 擷取原始檔案名字
              String filename = "aaa" + UUID.randomUUID().toString().replaceAll("-", "") + upload.getOriginalFilename();
              upload.transferTo(new File(path, filename));
              return "success";
          }
                     
    4. 跨伺服器檔案上傳

      1. 檔案伺服器
        1. 負責存儲使用者上傳檔案的伺服器
      2. 需要導入jar包的依賴坐标
        1. <dependency>
              <groupId>com.sun.jersey</groupId>
              <artifactId>jersey-core</artifactId>
              <version>1.18.1</version>
          </dependency>
          <dependency>
              <groupId>com.sun.jersey</groupId>
              <artifactId>jersey-client</artifactId>
              <version>1.18.1</version>
          </dependency>
                     
      3. 控制器方法代碼
        1. /**
           * 跨伺服器檔案上傳
           *
           * @param upload
           * @return
           * @throws Exception
           */
          @RequestMapping("/upload2")
          public String upload2(MultipartFile upload) throws Exception {
              System.out.println("upload2...");
              //定義上傳到檔案伺服器的位置
              String path = "http://localhost:81/uploads/";
              //擷取檔案名
              //UUID: 保證檔案名字不重複
              //getOriginalFilename(): 擷取原始檔案名字
              String filename = UUID.randomUUID().toString().replaceAll("-", "")
                      + "_" + upload.getOriginalFilename();
              System.out.println("filename = " + filename);
              //建立用戶端對象
              Client client = Client.create();
              //和檔案伺服器進行連接配接
              WebResource webResource = client.resource(path + filename);
              //上傳檔案
              webResource.put(upload.getBytes());
              return "success";
          }
                     
  3. 異常處理

    1. 分析

      1. 底層出現異常一般情況都是向上抛出
      2. 新元件
        1. 異常處理器元件
      3. 02 springMVC 響應 檔案上傳 異常處理 攔截器響應檔案上傳異常處理攔截器
    2. 代碼編寫

      1. 編寫自定義異常類

        1. 用來做提示資訊用的
        2. 需要異常類都要繼承Exception類
        3. package lq.exception;
          
          /*
          author: lq
          time: 2020-05-09 11:17 
          */
          public class SysException extends Exception {
              private String massage;
          
              public SysException(String message) {
                  this.massage = massage;
              }
          
              public String getMassage() {
                  return massage;
              }
          
              public void setMassage(String massage) {
                  this.massage = massage;
              }
          }
                     
      2. 編寫異常處理類

        1. 跳轉到指定頁面
        2. 需要實作HandlerExceptionResolver接口
        3. package lq.exception;
          
          import org.springframework.web.servlet.HandlerExceptionResolver;
          import org.springframework.web.servlet.ModelAndView;
          
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          /*
          author: lq
          time: 2020-05-09 11:19 
          */
          public class SysExceptionResolver  implements HandlerExceptionResolver {
              /**
               * 異常處理器類
               * @param httpServletRequest
               * @param httpServletResponse
               * @param o 不常用, 表示目前處理器對象
               * @param e 接收抛出的異常對象
               * @return 傳回的是一個ModelAndView對象, 可以幫你實作存儲資訊和頁面跳轉
               */
              @Override
              public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
                  SysException sysException=null;
                  //判斷接收到的異常是不是我們自定義的異常
                  if (e instanceof SysException){
                      //是, 直接指派
                      sysException= (SysException) e;
                  }else {
                      //不是, 再重新建立一個
                      e=new SysException("系統維護中...");
                  }
                  //建立視圖對象
                  ModelAndView modelAndView = new ModelAndView();
                  //往request中存儲錯誤資訊
                  modelAndView.addObject("errorMsg",((SysException) e).getMassage());
                  //設定跳轉頁面
                  modelAndView.setViewName("error");
                  return modelAndView;
              }
          }
                     
      3. 配置異常處理器

        1. <!--配置異常處理器對象-->
          <bean id="sysExceptionResolver" class="lq.exception.SysExceptionResolver"></bean>
                     
  4. 攔截器

    1. 概念

      1. 用于對控制器中的方法進行預處理和後處理
      2. 攔截器和過濾器的差別
        1. 過濾器是sun公司提供的, 任何javaWeb工程都可以使用
        2. 攔截器是springMVC自己的, 隻有使用springMVC架構的項目才可以使用
        3. 過濾器一旦配置了/*就可以攔截所有的資源(jsp 圖檔 靜态資源)
        4. 攔截器隻能攔截控制器中的方法
    2. 入門代碼

      1. 編寫攔截器的類

        1. 實作HandlerInterceptor接口
          1. 實作了接口之後并沒有讓實作方法, 不是接口裡面沒有方法, 接口裡面是有方法的, 隻不過JDK1.8之後對接口進行了加強, 允許在接口中直接實作方法
        2. package lq.interceptor;
          
          import org.springframework.web.servlet.HandlerInterceptor;
          import org.springframework.web.servlet.ModelAndView;
          
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          /**
           *
           */
          public class MyInterceptor implements HandlerInterceptor {
              /**
               * 預處理
               * @param request
               * @param response
               * @param handler
               * @return 傳回值為true放行 傳回值為false不放行, 使用request response這兩個對象跳轉到指定頁面
               * @throws Exception
               */
              @Override
              public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                  System.out.println("preHandle...");
                  return true;
              }
          
              @Override
              public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                  System.out.println("postHandle...");
              }
          }
                     
      2. 配置攔截器

        1. <!--配置攔截器-->
          <mvc:interceptors>
              <mvc:interceptor>
                  <!--攔截的路徑-->
                  <mvc:mapping path="/user/*"/>
                  <bean class="lq.interceptor.MyInterceptor"></bean>
                  <!--不攔截的路徑-->
                  <!--<mvc:exclude-mapping path="" />-->
              </mvc:interceptor>
          </mvc:interceptors>
                     
    3. HandlerInterceptor接口方法介紹

      1. postHandle()

        1. 在控制器方法執行後, success.jsp頁面執行前執行
        2. 當你在這個方法裡面指定了一個新的跳轉之後, 那麼springMVC就會往新的頁面跳轉, 不再往舊的頁面跳轉, 但是, 舊的頁面依然會被執行(jsp頁面會現在伺服器内部執行)
      2. afterCompletion()

        1. 會在success.jsp頁面執行之後執行
        2. 通常可以用于釋放一些資源
        3. 最後執行
        4. 無法在此方法中實作頁面跳轉
    4. 多個攔截器之間的攔截順序

      1. 攔截順序規則(個人見解)

        1. 當兩個攔截器攔截的路徑相同時(即mvc:mapping标簽的path屬性相同), 攔截順序以在springmvc.xml配置攔截器時的順序為準
          1. 配置在上面的攔截器會先執行, 配置在後面的攔截器會後執行
          2. <!--配置攔截器-->
            <mvc:interceptors>
                <mvc:interceptor>
                    <mvc:mapping path="/user/*"/>
                    <bean class="lq.interceptor.MyInterceptor"></bean>
                </mvc:interceptor>
                <mvc:interceptor>
                    <mvc:mapping path="/user/*"/>
                    <bean class="lq.interceptor.MyInterceptor2"></bean>
                </mvc:interceptor>
            </mvc:interceptors>
                       

繼續閱讀