您的位置:首页 > 编程语言 > Java开发

关于SpringMVC的异常中心DefaultExceptionHandler

2017-03-26 16:43 190 查看
摘要: 在服务端经常会遇到需要手动的抛出异常,比如业务系统,校验异常,比较通用的处理方案是在最顶层进行拦截异常,例如Struts的全局异常处理,而Spring的异常处理机制就相对于Struts来说好用多了

在服务端经常会遇到需要手动的抛出异常,比如业务系统,校验异常,比较通用的处理方案是在最顶层进行拦截异常,例如Struts的全局异常处理,而Spring的异常处理机制就相对于Struts来说好用多了。

第一种:配置式

<!-- 基于配置文件式的异常处理 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>
<prop key="com.sirdc.modules.exceptions.ServiceException">error/503</prop>
</props>
</property>
</bean>


第二种:注解式

<!-- 基于注解式子的异常处理 -->
<bean id="exceptionHandlerExceptionResolver"
class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"></bean>

然后在后端采用@ControllerAdvice注解进行全局处理。

import com.sirdc.modules.exceptions.ServiceException;
import com.sirdc.modules.validator.BeanValidators;
import com.sirdc.modules.web.model.Message;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.ConstraintViolationException;
import java.util.List;

/**
* 自定义统一异常处理中心
*
* @version Revision: 0.0.1
* @author: weihuang.peng
* @Date: 2015年1月17日
*/
@ControllerAdvice
public class DefaultExceptionHandler {

/**
* 处理业务异常
*
* @param request
* @param model
* @param exception
* @return Model
*/
@ExceptionHandler({ServiceException.class})
public ModelAndView processServiceException(NativeWebRequest request, ServiceException exception) {
ModelAndView model = new ModelAndView("/error/503");
model.addObject("exception", exception);
model.addObject("message", "服务器未能处理您的请求");
return model;
}

/**
* 处理校验异常
*
* @param request
* @param exception
* @return
*/
@ExceptionHandler({ConstraintViolationException.class})
@ResponseBody
public Message processConstraintViolationException(NativeWebRequest request, ConstraintViolationException exception) {
exception.printStackTrace();
List<String> list = BeanValidators.extractPropertyAndMessageAsList(exception, ": ");
list.add(0, "数据验证失败:");
return handleMessage(list.toArray(new String[]{}));
}

@ExceptionHandler({Exception.class})
public ModelAndView processException(NativeWebRequest request, Exception exception) {
exception.printStackTrace();
ModelAndView model = new ModelAndView("/error/500");
model.addObject("exception", exception);
model.addObject("message", "服务器出错了");
return model;
}

/**
* 添加Flash消息
*
* @param messages 消息
* @return
*/
protected Message handleMessage(String... messages) {
Message model = new Message();
StringBuilder sb = new StringBuilder();
for (String message : messages) {
sb.append(message).append(messages.length > 1 ? "<br/>" : "");
}
model.setCode("500");
model.setMessage(sb.toString());
return model;
}
}


在DefaultExceptionHandler中使用了BeanValidators,代码如下。

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
* <pre>
* JSR303 Validator(Hibernate Validator)工具类.
* JSR 303 – Bean Validation 是一个数据验证的规范.
*
* validate(Object)的返回值是Set,每一个ConstraintViolation包含了出错的
* message和propertyPath、InvalidValue, 不同场景有不同的显示需求,国际化在propertyPath的i18N翻译上.
* ConstraintViolation中包含propertyPath, message 和invalidValue等信息.
* 提供了各种convert方法,适合不同的i18n需求:
* 1. List<String>, String内容为message
* 2. List<String>, String内容为propertyPath + separator + message
* 3. Map<propertyPath, message>
*
* 详情见wiki: http://hibernate.org/subprojects/validator/docs/ * </pre>
*
* @author HaiYan
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class BeanValidators {

/**
* 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException,
* 而不是返回constraintViolations.
*/
public static void validateWithException(Validator validator,
Object object, Class<?>... groups)
throws ConstraintViolationException {
Set constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
}

/**
* 转换ConstraintViolationException中的Set<ConstraintViolations>中为List<message>.
*
* @param e
*            ConstraintViolationException
* @return List<String>, String内容为message
*/
public static List<String> extractMessage(ConstraintViolationException e) {
return extractMessage(e.getConstraintViolations());
}

/**
* 转换Set<ConstraintViolation>为List<message>.
*
* @param constraintViolations
* @return List<String>, String内容为message
*/
public static List<String> extractMessage(
Set<? extends ConstraintViolation> constraintViolations) {
List<String> errorMessages = Lists.newArrayList();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getMessage());
}
return errorMessages;
}

/**
* 转换ConstraintViolationException中的Set<ConstraintViolations>为Map<property,
* message>.
*
* @param e
*            ConstraintViolationException
* @return Map<String, String> key=propertyPath,value=message
*/
public static Map<String, String> extractPropertyAndMessage(
ConstraintViolationException e) {
return extractPropertyAndMessage(e.getConstraintViolations());
}

/**
* 转换Set<ConstraintViolation>为Map<property, message>.
*
* @param e
*            ConstraintViolationException
* @return Map<String, String> key=propertyPath,value=message
*/
public static Map<String, String> extractPropertyAndMessage(
Set<? extends ConstraintViolation> constraintViolations) {
Map<String, String> errorMessages = Maps.newHashMap();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.put(violation.getPropertyPath().toString(),
violation.getMessage());
}
return errorMessages;
}

/**
* 转换ConstraintViolationException中的Set<ConstraintViolations>为List<
* propertyPath message>.
*
* @param e
*            ConstraintViolationException
* @return List<String>, String内容为propertyPath + separator + message
*/
public static List<String> extractPropertyAndMessageAsList(
ConstraintViolationException e) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
}

/**
* 转换ConstraintViolationException的Set<ConstraintViolations>为List<
* propertyPath + separator + message>.
*
* @param e
*            ConstraintViolationException
* @param separator
*            分隔符
* @return List<String>, String内容为propertyPath + separator + message
*/
public static List<String> extractPropertyAndMessageAsList(
ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(),
separator);
}

/**
* 转换Set<ConstraintViolations>为List<propertyPath message>.
*
* @param constraintViolations
* @return List<String>, String内容为propertyPath + separator + message
*/
public static List<String> extractPropertyAndMessageAsList(
Set<? extends ConstraintViolation> constraintViolations) {
return extractPropertyAndMessageAsList(constraintViolations, " ");
}

/**
* 转换Set<ConstraintViolation>为List<propertyPath + separator + message>.
*
* @param e
*            ConstraintViolationException
* @return List<String>, String内容为propertyPath + separator + message
*/
public static List<String> extractPropertyAndMessageAsList(
Set<? extends ConstraintViolation> constraintViolations,
String separator) {
List<String> errorMessages = Lists.newArrayList();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator
+ violation.getMessage());
}
return errorMessages;
}
}


Message对象:

import java.io.Serializable;

/**
*
* @author: weihuang.peng
* @version Revision: 0.0.1
* @Date: 2015年1月21日
*/
public class Message implements Serializable {

private static final long serialVersionUID = 1769341992221383236L;

private String code;

private String message;

private Object data;

/**
* @author: weihuang.peng
* @return the data
*/
public Object getData() {
return data;
}

/**
* @author: weihuang.peng
* @param data the data to set
*/
public void setData(Object data) {
this.data = data;
}

/**
* @return the code
*/
public String getCode() {
return code;
}

/**
* @param code the code to set
*/
public void setCode(String code) {
this.code = code;
}

/**
* @return the message
*/
public String getMessage() {
return message;
}

/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息