Web项目上线或运行时往往会出现一些不可预料的异常信息,对于开发人员可以通过日志来查看逻辑性或设计性的问题,而对于用户,需要呈现出可以理解的异常提示界面。
全局异常处理器
异常的分类:
- 预期异常:通过捕获异常来获取异常信息。
- 运行时异常:主要通过规范代码的开发、测试,通过一些技术手段来减少运行时异常的发生。
以下代码示例,内容接上篇文章:SpringMVC[5]--Validation校验
1. 自定义异常类UserException
以User类的异常为例,定义一个专门处理User相关操作跑步的异常的自定义异常类。
package cn.com.mvc.exception;
public class UserException extends Exception {
//异常信息
private String message;
public UserException(String message){
super();
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
上面通过UserException的构造方法设置异常信息,通过其getMessage()获取其异常信息。
2. 定义全局异常处理器UserExceptionResolver
其实现的主要功能:
- 解析异常类型,判断异常属于哪种异常类。
- 如果是系统自定义的异常,则直接取出异常信息,并在错误页面展示。如果不是系统自定义的异常,构造一个自定义的异常类型,信息为“未知错误”。
- 构建异常信息展示信息,将异常信息绑定到异常界面的Model域中,然后跳转到相关的异常信息显示页面。
创建全局异常处理器UserExceptionResolver,即该核心异常处理器专门用于处理系统中所有有关User的异常,去实现HandlerExceptionResolver接口。
package cn.com.mvc.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 UserExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception ex) {
//1.解析出异常类型
UserException userException = null;
if(ex instanceof UserException){
//2. 如果该异常类型是系统自定义的类型,直接取出异常信息,在错误页面展示
userException = (UserException)ex;
} else {
//3. 如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为"未知错误")
userException = new UserException("未知错误!");
}
//错误信息
String message = userException.getMessage();
ModelAndView modelAndView = new ModelAndView();
//将错误信息传到页面
modelAndView.addObject("message",message);
//只指向错误页面
modelAndView.setViewName("/errorPage/userError");
return modelAndView;
}
}
3. 编写前端异常界面userError.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>提示</title>
</head>
<body>
<h1>抱歉,访问异常,错误信息如下:</h1>
<h2><font color="red">${message}</font></h2>
</body>
</html>
4. 在Controller类中进行判定和抛出
package cn.com.mvc.controller;
import cn.com.mvc.exception.UserException;
import cn.com.mvc.model.User;
import cn.com.mvc.validator.UserValidator;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
import java.util.List;
@Controller
@RequestMapping("user")
public class UserControllerTest {
@InitBinder
public void initBinder(DataBinder binder){
binder.setValidator(new UserValidator());
}
@RequestMapping("toLogin")
public String toLoginPage(){
//跳转至登录页面
return "/user/login";
}
@RequestMapping("login")
public String login(Model model, @Valid User user, BindingResult result) throws UserException{
//登录检测
List<ObjectError> allErrors = null;
if(result.hasErrors()){
allErrors = result.getAllErrors();
for (ObjectError objectError : allErrors){
//输出错误信息
System.out.println("code="+objectError.getCode()+" DefaultMessage="+objectError.getDefaultMessage());
//将错误信息传到页面
model.addAttribute("allErrors",allErrors);
}
return "/user/login";
} else {
//其他的业务逻辑
}
//异常判断代码
//查询用户是否为黑用户
boolean isBlackUser = checkBlackList(user);
//如果用户在黑名单中,则抛出异常,结束程序
if(isBlackUser){
throw new UserException("无权访问!");
}
return "/user/loginSuccess";
}
private boolean checkBlackList(User user){
String blackArray[] = {"jack", "tom", "jean"};
for (int i = 0; i < blackArray.length; i++){
if (user.getUsername().equals(blackArray[i])){
return true;
}
}
return false;
}
}
5. 检测结果
当输入如 jack用户登录时出现以下界面。

6. 配置properties来防止出现硬编码
- 新建exceptionMapping.properties
user.not.have.power=无访问权限!
- 编写读取properties文件的辅助类
package cn.com.mvcUtil;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ExceptionPropertyUtil {
private Properties prop;//属性集合对象
private InputStream fis;//属性文件输入流
private void init() throws IOException{
prop = new Properties();
fis = this.getClass().getResourceAsStream("/exceptionMapping.properties");
prop.load(fis);//将属性文件流装载到Properties对象中
fis.close();//关闭流
}
public String getExceptionMsg(String ExceptionCode) throws IOException{
init();
String msg = prop.getProperty(ExceptionCode);
if (msg != null){
return msg;
}else {
return "未定义异常!";
}
}
}
- 在UserException中的getMessage方法中,在捕获异常时,使用ExceptionPropertyUtil通过约定好的代码获取相应的中文异常信息:
public String getMessage(){
try{
return new ExceptionPropertyUtil().getExceptionMsg(message);
} catch (IOException e){
e.printStackTrace();
}
return message;
}
- 在Controller相关方法中,需要传入异常代号:
//查询用户是否为黑户名单用户
boolean isBlackUser = checkBlackList(user);
//如果在黑户名单中,抛出异常,结束程序
if(isBlackUser){
throw new UserException("user.not.have.power");
}
这样方便以后的统一管理与编辑。
网友评论