spring mvc4:异常处理
前面学习过struts2的异常处理,今天来看下spring mvc4的异常处理:
一、Servlet配置文件修改
1 <bean id="exceptionResolver"
2 class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
3 <property name="defaultErrorView" value="errors/error" />
4 <property name="exceptionMappings">
5 <props>
6 <prop key="java.lang.Throwable">errors/error</prop>
7 </props>
8 </property>
9 </bean>
增加上面这一节,大意是:只要有异常就跳到/WEB-INF/views/errors/error.jsp这个页面,当然如果要实现个性化的错误处理,比如:业务错误跳到页面A,SQL错误跳到页面B...,直接在props节点下,根据不同的异常类型,自行扩充 (注:404之类的错误,仍然参考struts2异常处理中的做法,在web.xml中配置解决)
二、创建一个BaseController基类,里面放一个以下方法:
1 @ExceptionHandler
2 public String exp(HttpServletRequest request, Exception ex) {
3 String resultViewName = "errors/error";
4
5 // 记录日志
6 logger.error(ex.getMessage(), ex);
7
8 // 根据不同错误转向不同页面
9 if (ex instanceof BusinessException) {
10 resultViewName = "errors/biz-error";
11 } else {
12 // 异常转换
13 ex = new Exception("系统太累了,需要休息!");
14 }
15 request.setAttribute("ex", ex);
16 return resultViewName;
17 }
记录异常日志、根据不同的异常类型转到不同的处理页面、友好异常转换(如果需要的话),都在上面的方法中处理了
三、所有Controller都继承自BaseController
这个,就不解释了
四、error.jsp页面
1 <%@ page contentType="text/html;charset=UTF-8" language="java"%>
2 <%
3 Exception e = (Exception) request.getAttribute("ex");
4 %>
5 <html>
6 <head>
7 <title>师傅,有妖怪:error</title>
8 </head>
9 <body>
10 <H2>
11 错误:<%=e.getClass().getSimpleName()%></H2>
12 <hr />
13 <P>
14 <strong>错误描述:</strong><%=e.getMessage()%>
15 </P>
16
17 <P>
18 <strong>详细信息:</strong>
19 </P>
20 <pre>
21 <%
22 e.printStackTrace(new java.io.PrintWriter(out));
23 %>
24 </pre>
25 </body>
26 </html>
上面的内容只是示意,大家可以根据需要自行美化
另:前文struts2的异常处理中,采用的是拦截器思想,spring mvc中也有拦截器,而且拦截的点更灵活:
1 package com.cnblogs.yjmyzz.interceptor;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5
6 import org.apache.logging.log4j.LogManager;
7 import org.apache.logging.log4j.Logger;
8 import org.springframework.web.servlet.ModelAndView;
9 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
10
11 public class ExcpetionInterceptor extends HandlerInterceptorAdapter {
12
13 protected Logger logger = LogManager.getLogger();
14
15 @Override
16 public boolean preHandle(HttpServletRequest request,
17 HttpServletResponse response, Object handler) throws Exception {
18 System.out.println("ExcpetionInterceptor.preHandle");
19 // 演示:限制仅允许从本机访问
20 if (request.getLocalAddr().equals("127.0.0.1")
21 || request.getLocalAddr().equals("0.0.0.0")) {
22 return true;
23 }
24 logger.error("非法入侵:" + request.getLocalAddr());
25 return false;
26 }
27
28 @Override
29 public void postHandle(HttpServletRequest request,
30 HttpServletResponse response, Object handler,
31 ModelAndView modelAndView) throws Exception {
32 System.out.println("ExcpetionInterceptor.postHandle");
33 }
34
35 @Override
36 public void afterCompletion(HttpServletRequest request,
37 HttpServletResponse response, Object handler, Exception ex)
38 throws Exception {
39 System.out.println("ExcpetionInterceptor.afterCompletion");
40 if (ex != null) {
41 logger.error(handler);
42 logger.error(ex.getMessage(), ex);
43 }
44 }
45
46 @Override
47 public void afterConcurrentHandlingStarted(HttpServletRequest request,
48 HttpServletResponse response, Object handler) throws Exception {
49 System.out
50 .println("ExcpetionInterceptor.afterConcurrentHandlingStarted");
51 }
52
53 }
拦截器创建后,依然要在servlet配置文件中注册:
<mvc:interceptors>
<bean class="com.cnblogs.yjmyzz.interceptor.ExcpetionInterceptor"></bean>
</mvc:interceptors>
spring mvc的拦截器提供了4个处理方法:
preHandle在Controller被调用前,先执行,可以在这里执行一些安全检查(上面示意了如何对IP做限制)
postHandle在Controller调用后执行,这时,可以修改ModelAndView,比如转到其它view之类
afterCompletion在Controller调用全部完成后执行,如果ex变量不为空,表示有异常了,这里可以记录异常日志
afterConcurrentHandlingStarted这个没怎么研究过,暂时不做评价
值得一提的是:spring-mvc中的拦截器,虽然可以在afterCompletion中记录异常日志,但如果按前面的baseController配合@ExceptionHandler做了处理,这里的ex就变成了null,因为异常在前面已经得到了处理,所以这二种方法不推荐混用,另外afterCompletion方法中,如果要根据不同的异常类型转到不同处理页面,并不方便。
附:ajax的统一异常处理,请移步 Struts2、Spring MVC4 框架下的ajax统一异常处理
- FZU 1889 龟兔赛跑
- 1381 硬币游戏
- 零基础学并查集算法
- POJ 2492 A Bug's Life
- 【Scrapy】走进成熟的爬虫框架
- Codeforces 777C Alyona and Spreadsheet
- HDU 1039 Easier Done Than Said?
- Codeforces 777A Shell Game
- Codeforces 777B Game of Credit Cards
- [Jenkins 新插件] 兼容阿里开发手册 (P3C) 的火线插件安装使用教程
- Codeforces 591B Rebranding
- 零基础学贪心算法
- WebSocket协议深入探究
- 全渠道客服中心聊天机器人实战
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- TS 设计模式08 - 发布订阅模式
- GrowingIO 数据采集 iOS SDK 测试实践
- Kubernetes 1.19.0——Pod(2)
- 极速40分钟写出SQLite数据展示与导出功能【技术创作101训练营】
- opencv cudacodec VideoReader 报错
- Flutter中富文件标签的解决方案
- JDK 15已发布,你所要知道的都在这里!
- [Concent速成] (1) 定义和共享模块状态
- 利用JS代码批量自动取消抖音关注
- 开机报错/dev/vda1 contains a file system with errors,check forced.
- centos内核的删除或修改
- chkconfig学习笔记
- 3分钟短文:说说Laravel通用缓存Cache的使用技巧
- 【技术创作101训练营】想用代码改变世界?先用好Git和Github!
- 绘制散点图(克利夫兰系列)