springMVC 异常拦截器,判断返回错误视图还是json格式的数据
博客专区 > 之渊 的博客 > 博客详情
springMVC 异常拦截器,判断返回错误视图还是json格式的数据
之渊 发表于2个月前
springMVC 异常拦截器,判断返回错误视图还是json格式的数据
  • 发表于 2个月前
  • 阅读 18
  • 收藏 0
  • 点赞 0
  • 评论 0

springmvc 的异常是挺好用的,可以 作统一的异常拦截,而且可以记录错误异常到日志里面。。

可是 如果 我有时候想 返回错误的json 格式,,,有时候想返回错误的视图,比如 500错误页面,, 怎么控制呢? 肯定不能写两个异常拦截的,,, 今天在 公司的项目里面,发现大神写好了,,,根据请求头判断的,,,也是厉害了。。。 我之前还想着 是否可以 判断返回 对象来判断呢。。。这样的方式挺好的。。。 下面是 实现代码:参考

package com.gwqm.exception;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.druid.support.json.JSONUtils;
import com.gwqm.app.ctrl.base.AppBaseAction;
import com.gwqm.app.enums.common.SuccessEnum;
import com.gwqm.app.exp.AppAuthorityException;
import com.gwqm.app.exp.AppCommonException;
import com.gwqm.base.mv.JModelAndView;
import com.gwqm.base.tools.exception.BaseException;
import com.gwqm.platform.app.enums.AppCommonErrorEnum;
import com.gwqm.platform.service.ISysConfigService;
import com.gwqm.platform.service.IUserConfigService;

/**
 * 捕获异常统一处理
 * 
 * @description TODO
 * @author liwanhua
 * @create date 2017年4月12日
 * @modified by
 * @modify date
 * @version v1.0
 */
@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {

	@Autowired
	protected ISysConfigService configService;
	@Autowired
	protected IUserConfigService userConfigService;
           
	protected static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); 
      
    private final static String EXPTION_MSG_KEY = "message";
    private final static String EXPTION_SUCC_KEY = "success";
    private final static String SELLER = "seller";
    private final static String ADMIN = "admin";
    private final static String BUYER = "buyer";
      
    @Override
    public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object obj,Exception ex){
    	 ex.printStackTrace();//打印异常,方便问题追踪
    	 logger.info("BaseException handler  " + ex.getMessage()); 
    	 ModelAndView mv = new ModelAndView(); 
    	 if(!(request.getHeader("accept").indexOf("application/json") > -1 || (request
                 .getHeader("X-Requested-With") != null && request.getHeader(
                         "X-Requested-With").indexOf("XMLHttpRequest") > -1))){
    		 //如果不是ajax,jsp格式返回
    		 String url = "";
        	 String requestUrl = request.getRequestURI();
             requestUrl = requestUrl.substring(1, requestUrl.indexOf("/",2));
             
             if(ex instanceof BaseException) {
	             if(requestUrl.toLowerCase().equals(ADMIN)){//管理员统一异常返回
	            	 url = "exception/error-admin.html";
	             }else if(requestUrl.toLowerCase().equals(SELLER)){//卖家统一异常返回
	            	 url = "exception/error-seller.html";
	             }else if(requestUrl.toLowerCase().equals(BUYER)){//买家统一异常返回
	            	 url = "exception/error-seller.html";
	             }else{
	            	 url="exception/error-seller.html";
	             }
             }
        	 mv = new JModelAndView(url,
     				this.configService.getSysConfig(),
     				this.userConfigService.getUserConfig(), 0, request,
     				response);
        	 
             mv.addObject(EXPTION_MSG_KEY, ex.getMessage());   		 
		} else {
			response.setStatus(HttpStatus.OK.value());
			// 设置ContentType
			response.setContentType(MediaType.APPLICATION_JSON_VALUE);
			// 避免乱码
			response.setCharacterEncoding("UTF-8");
			response.setHeader("Cache-Control", "no-cache, must-revalidate");
			try {
				PrintWriter writer = response.getWriter();
				Map<String, Object> map = new HashMap<String, Object>();

				String header = request.getHeader(AppBaseAction.USER_AGENTS_KEY);
//				String headerParam = request.getParameter(AppBaseAction.USER_AGENTS_KEY);
//				header = (null != header && !"".equals(header)) ? header : headerParam;
				logger.info("获取头部信息:【{}】", header);
				if (AppBaseAction.USER_AGENTS_VALUE.equals(header)) {
					map.put(AppBaseAction.SUCCESS, SuccessEnum.FAIL.getType());
					if (ex instanceof AppAuthorityException) {
						map.put(AppBaseAction.ERROR_CODE, ((AppAuthorityException) ex).getType());
						map.put(AppBaseAction.ERROR_MSG, ((AppAuthorityException) ex).getMessage());
					} else if (ex instanceof AppCommonException) {
						map.put(AppBaseAction.ERROR_CODE, ((AppCommonException) ex).getType());
						map.put(AppBaseAction.ERROR_MSG, ((AppCommonException) ex).getMessage());
					} else {
						map.put(AppBaseAction.ERROR_CODE, AppCommonErrorEnum.SYSTEM_ERROR.getType());
						map.put(AppBaseAction.ERROR_MSG, AppCommonErrorEnum.SYSTEM_ERROR.getDescpt());
					}
				} else {
					map.put("success", false);
					map.put("message", ex.getMessage());
				}

				writer.write(JSONUtils.toJSONString(map));
				writer.flush();
				writer.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return mv;
	}

}

为了处理 json串中文乱码这样在xml里面配置:

<!-- 解决@ExceptionHandler的@ResponseBody中文乱码 -->
	<!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
	    <property name="messageConverters">
	        <list>
	            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
	                <constructor-arg value="UTF-8"/>
	            </bean>
	        </list>
	    </property>
	</bean> -->

可以有其他的方式来控制中文乱码的通过 response来设置,,,比如 response 输入的时候,设置 utf-8 编码。。。这里就不具体说了。

//这句话的意思,是让浏览器用utf8来解析返回的数据
response.setHeader("Content-type", "text/html;charset=UTF-8");
//这句话的意思,是告诉servlet用UTF-8转码,而不是用默认的ISO8859
response.setCharacterEncoding("UTF-8");
String data = "中国";
PrintWriter pw = response.getWriter();
pw.write(data);

//这句话的意思,是让浏览器用utf8来解析返回的数据
response.setHeader("Content-type", "text/html;charset=UTF-8");
String data = "中国";
OutputStream ps = response.getOutputStream();
//这句话的意思,使得放入流的数据是utf8格式
ps.write(data.getBytes("UTF-8"));

这里有几个小细节需要注意:

  1. response.setCharacterEncoding("UTF-8");需要写在PrintWriter out = response.getWriter();的前面。拿到字符流后再设置编码是没有用的。
  2. response.setHeader("content-type", "text/html;charset=UTF-8");有一种更为简单的写法response.setContentType("text/html;charset=UTF-8");。 3.response.setContentType("text/html;charset=UTF-8");这句代码其实有两个作用:通知response以UTF-8输出和浏览器以UTF-8打开。即等价于response.setHeader("content-type", "text/html;charset=UTF-8");和response.setCharacterEncoding("UTF-8");两句代码。 4.通过以上阅读,读者应该能明白为什么response.getOutputStream.write(1);这句代码在浏览器的输出不是1。因为浏览器是一个文本编辑器,收到数据后会拿着1去查码表,然后显示对应字符。想在浏览器输出数字,应该把数字变成字符串,response.getOutputStream.write((1+"").getBytes());. 用OutputStream(字节流)发送数据: 1、response.getOutputStream().write(“中国”.getBytes());//以默认编码发送数据 2、response.getOutputStream().write("中国".getBytes("UTF-8"));//以UTF-8编码发送数据,浏览器(默认用GB2312)会出现乱码 解决办法: 2.1通过更改浏览器的编码方式:IE/”查看”/”编码”/”UTF-8”(不可取) 2.2通过设置响应头告知客户端编码方式:response.setHeader(“Content-type”, “text/html;charset=UTF-8”);//告知浏览器数据类型及编码 2.3通过meta标签模拟请求头:out.write("".getBytes()); 2.4通过以下方法:response.setContentType("text/html;charset=UTF-8");

中文乱码 参考> http://blog.csdn.net/simon_1/article/details/9092747http://www.jb51.net/article/56704.htm

当然了 异常拦截也可以通过 AOP 来作,只是性能肯定没有 springmvc 自带的方便和 优化

共有 人打赏支持
粉丝 8
博文 421
码字总数 125400
×
之渊
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: