SpringMVC筆記(五)

linzeliang發表於2021-04-30

1. 攔截器

1.1 攔截器和過濾器

SpringMVC的處理器攔截器類似於Servlet開發過程中的過濾器Filter,用於對處理器進行預處理和後處理。我們可以自定義一些攔截器來實現特定的功能

過濾器和攔截器的區別:攔截器是AOP思想的具體應用

過濾器:

  • Servlet規範中的一部分,任何JavaWeb工程都可以使用
  • 在url-pattern中配置了/*之後,可以對所有要訪問的資源進行攔截

攔截器:

  • 攔截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
  • 攔截器指揮攔截訪問的控制器方法,如果訪問的是jsp/html/css/img/js是不會進行攔截的

1.2 自定義攔截器

  1. 首先編寫一個類,實現HandlerInterceptor介面

    public class MyInterceptor implements HandlerInterceptor {
        
        /**
         * 在業務處理器處理請求之前被呼叫
         * 如果返回false
         *     從當前的攔截器往回執行所有攔截器的afterCompletion(),再退出攔截器鏈
         * 如果返回true
         *    執行下一個攔截器,直到所有的攔截器都執行完畢
         *    再執行被攔截的Controller
         *    然後進入攔截器鏈,
         *    從最後一個攔截器往回執行所有的postHandle()
         *    接著再從最後一個攔截器往回執行所有的afterCompletion()
         */
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
            System.out.println("------------處理前------------");
            return true;
        }
     
        /**
         * 在業務處理器處理請求執行完成後,生成檢視之前執行的動作
         * 可在modelAndView中加入資料,比如當前時間
         */
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("------------處理後------------");
        }
     
        /**
         * 在DispatcherServlet完全處理完請求後被呼叫,可用於清理資源等
         *
         * 當有攔截器丟擲異常時,會從當前攔截器往回執行所有的攔截器的afterCompletion()
         */
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception ex) throws Exception {
            System.out.println("------------清理------------");
        }
    }
    
  2. 在springmvc配置檔案中配置攔截器

    <!--關於攔截器的配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--/** 包括路徑及其子路徑-->
            <!--/admin/* 攔截的是/admin/add等等這種 , /admin/add/user不會被攔截-->
            <!--/admin/** 攔截的是/admin/下的所有-->
            <mvc:mapping path="/**"/>
            <!--bean配置的就是攔截器-->
            <bean class="com.kuang.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    

2. 檔案上傳下載

2.1 上傳

  1. 首先,表單中的enctype屬性要設定為multipart/form-data,只有用這種方式,才會以二進位制流的方式來處理表單資料,這種編碼方式會把檔案域指定檔案的內容也封裝到請求引數種,不會對字元進行編碼,其他的一些格式:

    • application/x-www=form-urlencoded:預設方式,只處理表單中的value屬性值,採用這種編碼方式的表單會將表單域中的值處理成url編碼方式
    • text/plain:處理個空格轉換為'+'外,對其他字元都不做編碼處理
  2. 然後匯入相關jar包,commons-fileupload

  3. 配置bean:multipartResolver

    <!--檔案上傳配置,id必須為multipartResolver-->
    <bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內容,預設為ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 上傳檔案大小上限,單位為位元組(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>
    
  4. CommonsMultipartFile 的 常用方法:

    • String getOriginalFilename():獲取上傳檔案的原名
    • InputStream getInputStream():獲取檔案流
    • void transferTo(File dest):將上傳檔案儲存到一個目錄檔案中
  5. 編寫Controller控制器

    @Controller
    public class FileController {
        //@RequestParam("file") 將name=file控制元件得到的檔案封裝成CommonsMultipartFile 物件
        //批量上傳CommonsMultipartFile則為陣列即可
        @RequestMapping("/upload")
        public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
     
            //獲取檔名 : file.getOriginalFilename();
            String uploadFileName = file.getOriginalFilename();
     
            //如果檔名為空,直接回到首頁!
            if ("".equals(uploadFileName)){
                return "redirect:/index.jsp";
            }
            System.out.println("上傳檔名 : "+uploadFileName);
     
            //上傳路徑儲存設定
            String path = request.getServletContext().getRealPath("/upload");
            //如果路徑不存在,建立一個
            File realPath = new File(path);
            if (!realPath.exists()){
                realPath.mkdir();
            }
            System.out.println("上傳檔案儲存地址:"+realPath);
     
            InputStream is = file.getInputStream(); //檔案輸入流
            OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //檔案輸出流
     
            //讀取寫出
            int len=0;
            byte[] buffer = new byte[1024];
            while ((len=is.read(buffer))!=-1){
                os.write(buffer,0,len);
                os.flush();
            }
            os.close();
            is.close();
            return "redirect:/index.jsp";
        }
    }
    
  6. 或者採用file.Transto來上傳檔案

    @RequestMapping("/upload2")
    public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
    
        //上傳路徑儲存設定
        String path = request.getServletContext().getRealPath("/upload");
        //上傳檔案地址
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
    
        //通過CommonsMultipartFile的方法直接寫檔案(注意這個時候)
        file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
    
        return "redirect:/index.jsp";
    }
    

2.2 下載

檔案下載步驟:

  1. 設定response響應頭
  2. 讀取檔案 -> InputStream
  3. 寫出檔案 -> OutputStream
  4. 執行操作
  5. 關閉流

程式碼實現:

@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
    //要下載的圖片地址
    String  path = request.getServletContext().getRealPath("/upload");
    String  fileName = "基礎語法.jpg";

    //1、設定response 響應頭
    response.reset(); //設定頁面不快取,清空buffer
    response.setCharacterEncoding("UTF-8"); //字元編碼
    response.setContentType("multipart/form-data"); //二進位制傳輸資料
    //設定響應頭
    response.setHeader("Content-Disposition",
                       "attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));

    File file = new File(path,fileName);
    //2、 讀取檔案--輸入流
    InputStream input=new FileInputStream(file);
    //3、 寫出檔案--輸出流
    OutputStream out = response.getOutputStream();

    byte[] buff =new byte[1024];
    int index=0;
    //4、執行 寫出操作
    while((index= input.read(buff))!= -1){
        out.write(buff, 0, index);
        out.flush();
    }
    out.close();
    input.close();
    return null;
}

相關文章