文档章节

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

之渊
 之渊
发布于 2017/09/07 14:02
字数 1162
阅读 22
收藏 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("<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
博文 492
码字总数 144126
作品 0
佛山
程序员
JAVA学习笔记22——SpingMVC框架第二章

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

Harries Blog™ ⋅ 2017/12/21 ⋅ 0

Archx/spring-agg

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

Archx ⋅ 2015/01/12 ⋅ 0

springMVC官方文档知识点梳理-关键

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

小车车 ⋅ 2016/11/13 ⋅ 0

springmvc学习笔记(22)-springmvc开发小结

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

brianway ⋅ 2016/03/19 ⋅ 2

springMVC初认识

本文为转载学习 原文链接:http://jinnianshilongnian.iteye.com/blog/1594806 Spring Web MVC处理请求的流程 具体执行步骤如下: 1、首先用户发送请求————>前端控制器,前端控制器根据请...

heroShane ⋅ 2014/01/25 ⋅ 0

springMVC --(讲解1)介绍

springMVC处理请求流程 1.客户端发起一个http请求 2.该请求被springMVC的DispacherServlet(控制器)进行拦截匹配,匹配到了委托给HandleRequest(处理器) 3.处理器会调用HandlerMapping与Handl...

求是科技 ⋅ 2016/10/06 ⋅ 0

Spring MVC

Spring MVC一、什么是 Spring MVC Spring MVC 属于 SpringFrameWork 的后续产品,已经融合在 Spring Web Flow 里面,是一个强大灵活的 Web 框架。Spring MVC 提供了一个 DispatcherServlet ...

任任任任师艳 ⋅ 2017/11/20 ⋅ 0

SpringMVC使用Interceptor拦截器

SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判...

Rickxue ⋅ 2016/01/18 ⋅ 0

SpringMVC中使用Interceptor拦截器

SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判...

凯文加内特 ⋅ 2015/05/29 ⋅ 0

Spring Cloud Spring Boot mybatis分布式微服务云架构 返回JSON格式

在上述例子中,通过统一定义不同Exception映射到不同错误处理页面。而当我们要实现RESTful API时,返回的错误是JSON格式的数据,而不是HTML页面,这时候我们也能轻松支持。 本质上,只需在之...

itcloud ⋅ 前天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JavaScript零基础入门——(十)JavaScript的DOM基础

JavaScript零基础入门——(十)JavaScript的DOM基础 欢迎大家回到我们的JavaScript零基础入门,上一节课,我们了解了JavaScript中的函数,这一节课,我们来了解一下JavaScript的DOM。 第一节...

JandenMa ⋅ 59分钟前 ⋅ 0

Spring mvc DispatchServlet 实现原理

在Spring中, ContextLoaderListener只是辅助类,在web 容器启动的时候查找并创建WebApplicationContext对象,通过该对象进行加载spring的配置文件。而真正的逻辑实现其实是在DispatcherSer...

轨迹_ ⋅ 今天 ⋅ 0

Weex起步

本教程假设你已经在你的本地环境安装了node 其实weex起步教程在 https://github.com/lilugirl/incubator-weex 项目说明文件中都已经有了,但为了有些同学看到英文秒变文盲,所以这里我重新写...

lilugirl ⋅ 今天 ⋅ 0

Jenkins实践1 之安装

1 下载 http://mirrors.jenkins.io/war/latest/jenkins.war 2 启动 java -jar jenkins.war 前提:安装jdk并配置环境变量 启动结果节选: ************************************************......

晨猫 ⋅ 今天 ⋅ 0

组合数学 1-2000 中,能被6或10整除的数的个数

1--2000 中,能被6或10整除的数的个数 利用集合的性质 能被6整除的个数 2000/6 = 333 能被10整除的个数 2000/10 = 200 能被6和10整除的个数 2000/30 = 66 能被6或10整除的个数 333+200-66 =...

阿豪boy ⋅ 今天 ⋅ 0

一篇文章学懂Shell脚本

Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合。 Shell可以直接使用在win/Unix/Linux上面,并且可以调用...

Jake_xun ⋅ 今天 ⋅ 0

大数据工程师需要精通算法吗,要达到一个什么程度呢?

机器学习是人工智能的一个重要分支,而机器学习下最重要的就是算法,本文讲述归纳了入门级的几个机器学习算法,加大数据学习群:716581014一起加入AI技术大本营。 1、监督学习算法 这个算法由...

董黎明 ⋅ 今天 ⋅ 0

Kylin 对维度表的的要求

1.要具有数据一致性,主键值必须是唯一的;Kylin 会进行检查,如果有两行的主键值相同则会报错。 2.维度表越小越好,因为 Kylin 会将维度表加载到内存中供查询;过大的表不适合作为维度表,默...

无精疯 ⋅ 今天 ⋅ 0

58到家数据库30条军规解读

军规适用场景:并发量大、数据量大的互联网业务 军规:介绍内容 解读:讲解原因,解读比军规更重要 一、基础规范 (1)必须使用InnoDB存储引擎 解读:支持事务、行级锁、并发性能更好、CPU及...

kim_o ⋅ 今天 ⋅ 0

代码注释中顺序更改 文件读写换行

`package ssh; import com.xxx.common.log.LogFactory; import com.xxx.common.log.LoggerUtil; import org.apache.commons.lang3.StringUtils; import java.io.*; public class DirErgodic ......

林伟琨 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部