SpringMVC基礎(二)_文件上傳、異常處理、攔截器

實現文件上傳

實現文件上傳,須要藉助如下兩個第三方 jar 包對上傳的二進制文件進行解析:css

form表單的 enctype 取值必須爲:multipart/form-data(默認爲:application/x-www-form-urlencoded);enctype爲表單請求正文的類型;method 屬性必須取值爲 post 方式;提供一個文件選擇域: <input type="file"/>html

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

一、傳統文件上傳方式

@RequestMapping(value = "/fileUploadOld", method = RequestMethod.POST)
public String fileUploadOld(HttpServletRequest request) throws Exception {

    //獲取上傳文件存放位置:絕對路徑
    String path = request.getServletContext().getRealPath("/uploads/");

    //判斷文件是否存在
    File file = new File(path);
    if (!file.exists()) {
        file.mkdirs();//不存在則建立文件
    }

    //解析request對象,獲取文件上傳項
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);

    List<FileItem> items = upload.parseRequest(request);
    //遍歷
    for (FileItem item : items) {
        //判斷item對象是否表單項
        if (item.isFormField()) {
            //true,代表是普通表單
        } else {
            //false,代表是上傳文件項
            //獲取上傳文件名稱
            String fileName = item.getName();

            //把文件名稱設置爲惟一值
            String uuid = UUID.randomUUID().toString().replace("-", "");
            fileName = uuid + "_" + fileName;
            request.setAttribute("fileName", fileName);

            //完成文件上傳
            item.write(new File(path, fileName));
            //刪除臨時文件
            item.delete();
        }
    }
    return "succeed";
}

二、Spring MVC 文件上傳

原理:文件上傳請求發送到前端控制器時,會轉給文件解析器並返回文件上傳項,而後前端控制器將文件上傳項發送到控制器方法,最後完成上傳操做;前端

注意:java

  1. 控制器方法中使用 MultipartFile 對象;
  2. MultipartFile 對象名稱必需要與請求參數名稱一致;
  3. 配置文件解析器 CommonsMultipartResolver 時,ID值必須爲 multipartResolver;

代碼實現web

@RequestMapping(value = "/fileUploadMvc", method = RequestMethod.POST)
public String fileUploadMvc(HttpServletRequest request, MultipartFile fileUpload) {

    //獲取上傳文件存放位置:絕對路徑
    String path = request.getServletContext().getRealPath("/uploads/");
    
    //判斷文件是否存在
    File file = new File(path);
    if (!file.exists()) {
        file.mkdirs();//不存在則建立文件
    }

    //獲取上傳文件名
    String filename = fileUpload.getOriginalFilename();

    //把文件名稱設置爲惟一值
    String uuid = UUID.randomUUID().toString().replace("-", "");
    filename = uuid + "_" + filename;

    //上傳文件
    try {
        fileUpload.transferTo(new File(path, filename));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return "succeed";
}

Spring MVC配置文件中配置 CommonsMultipartResolverspring

<!--配置文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--設置最大上傳文件的大小:10M-->
    <property name="maxUploadSize" value="10485760"/>
</bean>

三、跨服務器實現文件上傳

分服務器的目的:讓服務器各司其職,從而提升項目的運行效率;在實際開發中,會有不少處理不一樣功能的服務器。例如:數據庫

  • 應用服務器:負責部署咱們的應用;
  • 數據庫服務器:運行咱們的數據庫;
  • 緩存和消息服務器:負責處理大併發訪問的緩存和消息;
  • 文件服務器:負責存儲用戶上傳文件的服務器;

部署多臺服務器的操做apache

  1. 部署兩臺服務器,並建立一個用於存放圖片的 Web 工程;瀏覽器

  2. 配置存放圖片的服務器能夠支持寫入操做;spring-mvc

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>readonly</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

實現跨服務器文件上傳

@RequestMapping(value = "/fileUploadMultiServer", method = RequestMethod.POST)
public String fileUploadMultiServer(MultipartFile fileUpload) {

    //定義上傳文件存放服務器位置:絕對路徑
    String path = "服務器域名/URI";

    //聲明上傳文件項
    //獲取上傳文件名稱
    String filename = fileUpload.getOriginalFilename();
    //把文件名稱設置爲惟一值
    String uuid = UUID.randomUUID().toString().replace("-", "");
    filename = uuid + "_" + filename;

    /*
        完成文件上傳,跨服務器上傳
            (1)建立客戶端對象;
            (2)和FileServer服務器進行鏈接;
            (3)上傳文件
     */
    //建立 sun 公司提供的 jersey 包中的 Client 對象
    Client client= Client.create();
    //指定上傳文件的地址,該地址是 web 路徑
    WebResource webResource = client.resource(path + filename);
    try {
        webResource.put(fileUpload.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }

    return "succeed";
}

Spring MVC配置文件中配置 CommonsMultipartResolver

<!--配置文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--設置最大上傳文件的大小:10M-->
    <property name="maxUploadSize" value="10485760"/>
</bean>

注意

異常處理

一、異常處理的思路

系統中異常包括兩類:預期異常和運行時異常 RuntimeException,前者經過捕獲異常從而獲取異常信息,後者主要經過規範代碼開發、測試手段減小運行時異常的發生;

Spring MVC項目中的 dao、service、controller 出現的異常都經過 throws Exception 向上拋出,最後,要麼由瀏覽器輸出異常信息,要麼在前端控制器中經過異常解析器進行異常處理;

二、異常解析器處理異常步驟

  1. 自定義異常類;

    package spitter.exception;
    
    /**
     * 自定義異常類
     */
    public class SystemException extends Exception{
        //存儲異常信息
        private String massage;
    
        public SystemException(String massage) {
            this.massage = massage;
        }
    
        public String getMassage() {
            return massage;
        }
    
        public void setMassage(String massage) {
            this.massage = massage;
        }
    }
  2. 定義異常處理器:該類實現HandlerExceptionResolver,並重寫resolveException方法;

    package spitter.exception;
    
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 自定義異常處理器
     */
    public class SystemExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(
            HttpServletRequest httpServletRequest, 
            HttpServletResponse httpServletResponse, 
            Object handler,
            Exception ex 
        ) {
    
            //獲取異常對象
            SystemException se=null;
    
            if (e instanceof SystemException){
                se= (SystemException) ex;
            }else {
                se=new SystemException("系統正在維護...");
            }
    
            ModelAndView mav=new ModelAndView();
            mav.addObject("error",se.getMassage());
            mav.setViewName("error");
    
            return mav;
        }
    }
  3. Spring MVC配置文件中配置異常處理器;

    <!--裝配異常處理器-->
    <bean id="systemExceptionResolver" class="spitter.exception.SystemExceptionResolver"/>

三、resolveException 方法

  • HttpServletRequest:當前請求的請求對象;
  • HttpServletResponse:當前請求的響應對象;
  • Object:當前處理器的對象;
  • Exception:當前拋出的異常對象;
  • 返回值:ModelAndView 對象;能夠進行數據傳輸和頁面跳轉;

攔截器

Spring MVC 的處理器攔截器相似於 Servlet 開發中的過濾器 Filter,用於對處理器進行預處理和後處理。 用戶能夠本身定義一些攔截器來實現特定的功能;

攔截器鏈(Interceptor Chain):攔截器鏈就是將攔截器按必定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其以前定義的順序被調用;

攔截器和過濾器的區別

  • 過濾器:是 servlet 規範中的一部分,任何java web工程均可以使用;攔截器是 SpringMVC 框架獨有,只有 SpringMVC 框架的工程才能使用;
  • 過濾器:在 url-pattern 中配置了/*以後,能夠對全部要訪問的資源攔截;攔截器它是隻會攔截訪問的控制器方法,不攔截靜態資源的訪問(jsp,html,css等);

自定義攔截器步驟

  • 自定義攔截器類,該類實現HandlerInterceptor接口;

    • preHandle():訪問控制器前執行。返回true,訪問控制器;false則不訪問,此時,可以使用請求對象和響應對象經過請求轉發或重定向進行頁面跳轉;
    • postHandle():訪問控制器後執行。若是此處進行頁面跳轉,則控制器返回的視圖名失效;
    • afterCompletion():頁面加載後執行;
    package spitter.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 {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("攔截器前置方法執行...");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("攔截器後置方法執行...");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("頁面加載完成,攔截器方法執行...");
        }
    }
  • 配置攔截器:;配置元素: <mvc:interceptors>

    <!--配置攔截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--指定攔截的 URL-->
            <mvc:mapping path="/interceptor/myInterceptor"/>
            <!--指定不攔截的 URL
                <mvc:exclude-mapping path=""/>-->
            <!--配置攔截器對象-->
            <bean class="spitter.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
  • 攔截器可配多個,執行順序從上到下

多個攔截器執行順序

此上,Spring MVC基礎學習已經完成。

相關文章
相關標籤/搜索