文档章节

springMVC 异常拦截器,判断返回错误视图还是json格式的数据

之渊
 之渊
发布于 2017/09/07 14:02
字数 1162
阅读 38
收藏 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("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />".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 自带的方便和 优化

© 著作权归作者所有

共有 人打赏支持
之渊
粉丝 11
博文 520
码字总数 154962
作品 0
佛山
程序员
Spring Boot全局异常处理

Spring Boot默认的异常处理机制 默认情况下,Spring Boot为两种情况提供了不同的响应方式。 一种是浏览器客户端请求一个不存在的页面或服务端处理发生异常时,一般情况下浏览器默认发送的请求...

狼王黄师傅
10/16
0
0
JAVA学习笔记22——SpingMVC框架第二章

JAVA学习笔记22——SpingMVC框架第二章 Harries Blog™2017-12-210 阅读 ACESpringAppbeancatActionAjax 昨天讲解了 SpringMVC 的入门,今天来讲讲进阶一点的知识,话不多说,请看下文。 今天...

Harries Blog™
2017/12/21
0
0
Archx/spring-agg

#SPRING-AGG 这个一个框架整合案列,包含 SpringMVC/MyBatis/Apache Shiro 。 演示数据 演示数据请导入 db.sql 演示账号密码均为 SpringMVC 配置 演示项目使用的是 RESTful 风格,不是传统的...

Archx
2015/01/12
0
0
springMVC官方文档知识点梳理-关键

一、异步请求处理的相关配置 Servlet容器配置 对于那些使用配置文件的应用,请确保的版本更新到3.0: 异步请求必须在将下的子元素设置为true。此外,所有可能参与异步请求处理的过滤器都必须...

小车车
2016/11/13
44
0
springmvc学习笔记(22)-springmvc开发小结

springmvc学习笔记(22)-springmvc开发小结 标签: springmvc [TOC] 本文对springmvc系列博文进行小结 springmvc框架 前端控制器:接收request,进行response 处理器映射器:根据url查找Handl...

brianway
2016/03/19
427
2

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 小心着凉 @红薯

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:5.33起,其声呜呜然,如怨如慕,如泣如诉。余音袅袅,不绝如缕。分享Arch Enemy的单曲《Bridge Of Destiny (2009)》 《Bridge Of...

小小编辑
今天
170
4
what f,,

anlve
今天
2
0
初级开发-编程题

` public static void main(String[] args) { System.out.println(changeStrToUpperCase("user_name_abc")); System.out.println(changeStrToLowerCase(changeStrToUpperCase("user_name_abc......

小池仔
今天
14
0
现场看路演了!

HiBlock
昨天
21
0
Rabbit MQ基本概念介绍

RabbitMQ介绍 • RabbitMQ是一个消息中间件,是一个很好用的消息队列框架。 • ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的s...

寰宇01
昨天
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部