當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
SpringMVC自定义拦截器与异常处理(自定义异常)
生活随笔
收集整理的這篇文章主要介紹了
SpringMVC自定义拦截器与异常处理(自定义异常)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
SpringMVC自定義攔截器與異常處理
攔截器概念
攔截器代碼演示
創(chuàng)建maven工程
pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>day02_SpringMVC_Interceptor</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><!-- 版本鎖定--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><spring.version>5.1.9.RELEASE</spring.version></properties><dependencies><!-- spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!-- servlet3.0規(guī)范的坐標 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--jsp坐標--><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.1</version><scope>provided</scope></dependency><!-- lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency><!--json相關(guān)坐標3個--><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-databind</artifactId><version>2.9.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.0</version></dependency></dependencies><build><plugins><!--tomcat插件--><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version><configuration><port>80</port><path>/</path><!-- 配置tomcat插件編碼,因為請求的數(shù)據(jù)會經(jīng)過tomcat.所以在tomcat也要設(shè)置一下編碼--><uriEncoding>UTF-8</uriEncoding></configuration></plugin></plugins></build> </project>web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"><!--springMVC程序啟動流程1.tomcat啟動首先加載web.xml2.保證DispatcherServlet能夠正常加載配置文件3.spring配置文件必須掃描有spring注解的的包--><!-- 配置調(diào)度服務(wù)器(前端控制器),配置后就能夠去調(diào)度controller中的路徑--><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><!-- 初始化DispatcherServlet,初始化springIOC容器,讀取類路徑下的spring-mvc.xml配置文件(target/classes/就會有這個配置文件),掃描controller注解下的RequestMapping的路徑--><param-name>contextConfigLocation</param-name> <!-- <param-value>classpath:spring-mvc.xml</param-value>--><param-value>classpath:spring-mvc.xml</param-value></init-param><!-- 配置load-on-startup元素表示這個servlet應(yīng)該是在啟動時加載(實例化并調(diào)用其init())的web應(yīng)用程序。--><load-on-startup>1</load-on-startup></servlet><!--配置請求調(diào)度服務(wù)--><servlet-mapping><!-- 配置調(diào)度服務(wù)--><servlet-name>dispatcherServlet</servlet-name><!--在spring中, / /*/ : 匹配所有的請求/* :匹配所有的請求,查詢結(jié)果頁面,都是以文本顯示,不會做任何的渲染頁面,包括jsp頁面--><url-pattern>/</url-pattern></servlet-mapping><!-- 配置過濾器,來解決post請求亂碼問題--><filter><filter-name>characterEncodingFilter</filter-name><!-- 加載spring提供的過濾器--><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 設(shè)置過濾器中的屬性值--><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> </web-app>spring-mvc.xml
注意在核心配置文件中配置自定義攔截器的bean
創(chuàng)建自定義攔截器類(代碼中注釋有詳細解釋)
MyInterceptor
package com.fs.springmvc.interceptor; /* 攔截器與過濾器有什么不同Interceptor攔截器是SpringMVC的技術(shù),攔截控制的controller,攔截springIOC中的controllerfilter過濾器是tomcat中所有的接收到的請求都可以被攔截,包括spring中的controller//三個方法的運行順序為 preHandle -> controller中被攔截的方法執(zhí)行 ->postHandle -> afterCompletion//如果preHandle返回值為false,三個方法僅運行preHandle由HandlerInterceptor接口源碼得知,方法被default修飾了(java8新特性)被默認實現(xiàn)了方法的,所以我們自定義攔截器沒有強制我們重寫接口中的方法所以我們需要自己重寫接口中的方法實現(xiàn)自定義攔截器的具體功能HandlerInterceptor接口源碼public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {} }*/ import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //自定義攔截器需要實現(xiàn)HandleInterceptor接口,實現(xiàn)這個接口沒有被強制現(xiàn)實所有方法 //是因為HandlerInterceptor接口中的方法有默認的default實現(xiàn)方法,所以我們需要自己重寫接口中的方法 public class MyInterceptor implements HandlerInterceptor {//處理器運行之前執(zhí)行@Overridepublic boolean preHandle(HttpServletRequest request,//請求攜帶的requestHttpServletResponse response,//響應(yīng)攜帶的Response//handler就是我們執(zhí)行的controller方法路徑Object handler) throws Exception {//下面打印的就是我們自己寫的controller的方法,使用反射技術(shù)//public java.lang.String com.fs.springmvc.controller.InterceptorController.handleRun()///System.out.println(handler.toString());System.out.println("前置運行----a1");//返回值為false將攔截原始處理器的運行,訪問的controller中的方法不會被執(zhí)行,//而且后面的postHandle,afterCompletion也不會執(zhí)行//如果配置多攔截器,返回值為false將終止當(dāng)前攔截器后面配置的攔截器的運行return true;}//處理器運行之后執(zhí)行@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,//controller執(zhí)行方法后要返回的視圖ModelAndViewModelAndView modelAndView) throws Exception {System.out.println("后置運行----b1");}//所有攔截器的后置執(zhí)行全部結(jié)束后,執(zhí)行該操作@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,//Exception ex) throws Exception {System.out.println("完成運行----c1");}//三個方法的運行順序為 preHandle -> postHandle -> afterCompletion//如果preHandle返回值為false,三個方法僅運行preHandle }MyInterceptor2
package com.fs.springmvc.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 MyInterceptor2 implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {System.out.println("前置運行------a2");return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception {System.out.println("后置運行------b2");}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception {System.out.println("完成運行------c2");} }MyInterceptor3
package com.fs.springmvc.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 MyInterceptor3 implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {System.out.println("前置運行--------a3");return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception {System.out.println("后置運行--------b3");}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception {System.out.println("完成運行--------c3");} }controller
InterceptorController
package com.fs.springmvc.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.config.annotation.EnableWebMvc;//@Controller public class InterceptorController {@RequestMapping("/handleRun")public String handleRun() {System.out.println("controller業(yè)務(wù)處理器運行------------main");return "page";} }測試
輸入地址訪問:
控制臺輸出
攔截器執(zhí)行流程
攔截器參數(shù)
核心配置文件中關(guān)于攔截器的配置
攔截器鏈配置
異常處理
我們在controller中調(diào)用業(yè)務(wù)層出現(xiàn)了異常,我們不可能給前端響應(yīng)一大堆異常信息,所以,我們需要將我們的異常進行封裝返回給前端,然后前端對異常進行友好的提示告知客戶
HandlerExceptionResolver接口方式(異常處理器)
package com.fs.springmvc.exception;import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* 自定義異常類,必須實現(xiàn)異常處理程序解析器HandlerExceptionResolver接口,重寫resolveException()方法 自定義異常類(全局(IOC類)異常管理)@Component注解后spring發(fā)現(xiàn)這個類實現(xiàn)了HandlerExceptionResolver接口,就認定為異常處理的類,然后就會對所有的IOC管理的對象的方法進行異常處理,當(dāng)IOC管理的類的方法執(zhí)行出現(xiàn)異常了,就會到達異常處理類的resolveException()方法,執(zhí)行里面的異常處理邏輯使用自定義異常類處理異常是在controller的方法加載參數(shù)后才會加載這個類,就會導(dǎo)致前端傳遞參數(shù) 的時候,SpringMVC將前端傳遞過來參數(shù)封裝到方法的參數(shù)的時候出現(xiàn)類型轉(zhuǎn)換異常,就不會對這個異常進行處理 所以爭對這個問題,出現(xiàn)了注解方式處理異常.注解處理器就可以攔截Dao入?yún)㈩愋娃D(zhuǎn)換異常*/ @Component public class ExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) {System.out.println("自定義異常類正在運行 ...."+ex);ModelAndView modelAndView = new ModelAndView();//對異常類型進行判斷使用instanceof關(guān)鍵字if( ex instanceof NullPointerException){//將異常數(shù)據(jù)返回給前端modelAndView.addObject("msg","空指針異常");}else if ( ex instanceof ArithmeticException){//將異常數(shù)據(jù)返回給前端modelAndView.addObject("msg","算數(shù)運算異常");}else{//將異常數(shù)據(jù)返回給前端modelAndView.addObject("msg","未知的異常");}//然后跳轉(zhuǎn)到異常頁面展示modelAndView.setViewName("error.jsp");return modelAndView;} }@ControllerAdvice注解實現(xiàn)異常分類管理@ExceptionHandler(常用方式)
**注意:**要在核心配置文件中添加==< mvc:annotation-driven/>mvc的注解支持==
兩種異常推薦使用注解,因為注解可以攔截到入?yún)㈩愋娃D(zhuǎn)換異常
注解代碼
package com.fs.springmvc.exception;import com.fs.springmvc.domain.ResultMapper; import com.fs.springmvc.domain.User; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /* 注解的方式處理異常(常用) @ControllerAdvice 聲明該類是一個Controller的通知類,聲明后該類就會被加載成異常處理器 使用注解異常處理器就可以攔截到入?yún)㈩愋娃D(zhuǎn)換異常 而非注解(實現(xiàn)HandlerExceptionResolver接口)就無法攔截到入?yún)㈩愋娃D(zhuǎn)換異常*/ @Component //使用注解開發(fā)異常處理器 //聲明該類是一個Controller的通知類,聲明后該類就會被加載成異常處理器 @ControllerAdvice public class ExceptionAdvice {/*//類中定義的方法攜帶@ExceptionHandler注解的會被作為異常處理器,后面添加實際處理的異常類型@ExceptionHandler(NullPointerException.class)@ResponseBodypublic String doNullException(Exception ex){return "空指針異常";}@ExceptionHandler(ArithmeticException.class)@ResponseBodypublic String doArithmeticException(Exception ex){return "ArithmeticException";}//處理大異常@ExceptionHandler(Exception.class)@ResponseBodypublic String doException(Exception ex){return "all";}*//*一般處理一個大異常就行了*///處理大異常,返回結(jié)果集對象,以json返回@ExceptionHandler(Exception.class)@ResponseBodypublic ResultMapper doExceptionTo(Exception ex){//給返回的結(jié)果集的數(shù)據(jù)準備User user = new User();user.setName("小付");user.setAge(18);ResultMapper resultMapper = new ResultMapper(500,false,"服務(wù)器繁忙~",user);return resultMapper;}//處理自定義異常,返回結(jié)果集對象,以json返回@ExceptionHandler(BusinessException.class)@ResponseBodypublic ResultMapper doExceptionToBusinessException(BusinessException ex){//給返回的結(jié)果集的數(shù)據(jù)準備User user = new User();user.setName("小花");user.setAge(18);ResultMapper resultMapper = new ResultMapper(500,false,ex.getMessage(),user);return resultMapper;} }ResultMapper對返回的結(jié)果進行封裝
package com.fs.springmvc.domain;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;/* 返回的結(jié)果對象*/ @Data @NoArgsConstructor @AllArgsConstructor public class ResultMapper<T> {//狀態(tài)碼private Integer code;//是否成功private Boolean flag;//返回消息private String message;//返回的數(shù)據(jù)private T data; }自定義異常
自定義異常BusinessException
package com.fs.springmvc.exception; //自定義異常繼承RuntimeException,覆蓋父類所有的構(gòu)造方法 public class BusinessException extends RuntimeException {public BusinessException() {}public BusinessException(String message) {super(message);}public BusinessException(String message, Throwable cause) {super(message, cause);}public BusinessException(Throwable cause) {super(cause);}public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);} }controller中一個請求方法模擬異常來測試我們的異常代碼
package com.fs.springmvc.controller;import com.fs.springmvc.domain.User; import com.fs.springmvc.exception.BusinessException; import com.fs.springmvc.exception.SystemException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;import java.util.ArrayList; import java.util.List;@Controller public class UserController {@RequestMapping("/save")@ResponseBodypublic List<User> save(@RequestBody User user) {System.out.println("user controller save is running ...");//拋出自定義的異常throw new BusinessException("請勿連續(xù)刷新頁面,謝謝~~");}// @RequestMapping("/save") // @ResponseBody // public List<User> save(@RequestBody User user) { // System.out.println("user controller save is running ...");//模擬業(yè)務(wù)層發(fā)起調(diào)用產(chǎn)生了異常 // int i = 1/0; // String str = null; // str.length();//對用戶的非法操作進行判定,并包裝成異常對象進行處理,便于統(tǒng)一管理 // if(user.getName().trim().length() < 8){ // throw new BusinessException("對不起,用戶名長度不滿足要求,請重新輸入!"); // } // if(user.getAge() < 0){ // throw new BusinessException("對不起,年齡必須是0到100之間的數(shù)字!"); // } // if(user.getAge() > 100){ // throw new SystemException("服務(wù)器連接失敗,請盡快檢查處理!"); // }// User u1 = new User(); // u1.setName("Tom"); // u1.setAge(3); // User u2 = new User(); // u2.setName("Jerry"); // u2.setAge(5); // ArrayList<User> al = new ArrayList<User>(); // al.add(u1); // al.add(u2); // // return al; // } }總結(jié)
以上是生活随笔為你收集整理的SpringMVC自定义拦截器与异常处理(自定义异常)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springMVC获取异步请求的参数,返
- 下一篇: SSM整合之XML方式,与配置事务,拦截