配置springboot在访问404时自定义返回结果以及统一异常处理
在搭建项目框架的时候用的是springboot,想统一处理异常,但是发现404的错误总是捕捉不到,总是返回的是springBoot自带的错误结果信息。
如下是springBoot自带的错误结果信息:
{
"timestamp": 1492063521109,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/rest11/auth"
}
百度一波,发现需要配置文件中加上如下配置:
properties格式:
#出现错误时, 直接抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
#不要为我们工程中的资源文件建立映射
spring.resources.add-mappings=false
yml格式:
spring:
#出现错误时, 直接抛出异常(便于异常统一处理,否则捕获不到404)
mvc:
throw-exception-if-no-handler-found: true #不要为我们工程中的资源文件建立映射
resources:
add-mappings: false
下面是我SpringMVC-config配置代码,里面包含统一异常处理代码,都贴上:
package com.qunyi.jifenzhi_zx.core.config; import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.BeanTypeAutoProxyCreator;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.qunyi.jifenzhi_zx.core.Const;
import com.qunyi.jifenzhi_zx.core.base.exception.ServiceException;
import com.qunyi.jifenzhi_zx.core.base.result.ResponseMsg;
import com.qunyi.jifenzhi_zx.core.base.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List; /**
* Spring MVC 配置
*
* @author xujingyang
* @date 2018/05/25
*/
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter { private final Logger logger = LoggerFactory.getLogger(WebMvcConfigurer.class);
@Value("${spring.profiles.active}")
private String env;//当前激活的配置文件 //使用阿里 FastJson 作为JSON MessageConverter
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteMapNullValue,//保留空的字段
SerializerFeature.WriteNullStringAsEmpty,//String null -> ""
SerializerFeature.WriteNullNumberAsZero);//Number null -> 0
converter.setFastJsonConfig(config);
converter.setDefaultCharset(Charset.forName("UTF-8"));
converters.add(converter);
} //统一异常处理
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
exceptionResolvers.add(new HandlerExceptionResolver() {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
ResponseMsg result;
if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”
result = new ResponseMsg("501", "业务层出错:" + e.getMessage());
logger.info(e.getMessage());
} else if (e instanceof NoHandlerFoundException) {
result = new ResponseMsg("404", "接口 [" + request.getRequestURI() + "] 不存在");
} else {
result = new ResponseMsg("500", "接口 [" + request.getRequestURI() + "] 错误,请联系管理员!");
String message;
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
request.getRequestURI(),
handlerMethod.getBean().getClass().getName(),
handlerMethod.getMethod().getName(),
e.getMessage());
} else {
message = e.getMessage();
}
logger.error(message, e);
}
responseResult(response, result);
return new ModelAndView();
} });
} //解决跨域问题
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // **代表所有路径
.allowedOrigins("*") // allowOrigin指可以通过的ip,*代表所有,可以使用指定的ip,多个的话可以用逗号分隔,默认为*
.allowedMethods("GET", "POST", "HEAD", "PUT", "DELETE") // 指请求方式 默认为*
.allowCredentials(false) // 支持证书,默认为true
.maxAge(3600) // 最大过期时间,默认为-1
.allowedHeaders("*");
} //添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//接口登录验证拦截器
if (!"dev".equals(env)) { //开发环境忽略登录验证
registry.addInterceptor(new HandlerInterceptorAdapter() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//验证登录
Object obj = request.getSession().getAttribute(Const.LOGIN_SESSION_KEY);
if (obj != null) {
return true;
} else {
logger.warn("请先登录!==> 请求接口:{},请求IP:{},请求参数:{}",
request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap())); responseResult(response, new ResponseMsg(Result.SIGNERROR));
return false;
}
}
});
}
} private void responseResult(HttpServletResponse response, ResponseMsg result) {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setStatus(200);
try {
response.getWriter().write(JSON.toJSONString(result));
} catch (IOException ex) {
logger.error(ex.getMessage());
}
} private String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 如果是多级代理,那么取第一个ip为客户端ip
if (ip != null && ip.indexOf(",") != -1) {
ip = ip.substring(0, ip.indexOf(",")).trim();
} return ip;
} /**
* druidServlet注册
*/
@Bean
public ServletRegistrationBean druidServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet());
registration.addUrlMappings("/druid/*");
return registration;
} /**
* druid监控 配置URI拦截策略
*
* @return
*/
@Bean
public FilterRegistrationBean druidStatFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
// 添加过滤规则.
filterRegistrationBean.addUrlPatterns("/*");
// 添加不需要忽略的格式信息.
filterRegistrationBean.addInitParameter("exclusions", "/web_frontend/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid,/druid/*,/error,/login*");
// 用于session监控页面的用户名显示 需要登录后主动将username注入到session里
filterRegistrationBean.addInitParameter("principalSessionName", "username");
return filterRegistrationBean;
} /**
* druid数据库连接池监控
*/
@Bean
public DruidStatInterceptor druidStatInterceptor() {
return new DruidStatInterceptor();
} /**
* druid数据库连接池监控
*/
@Bean
public BeanTypeAutoProxyCreator beanTypeAutoProxyCreator() {
BeanTypeAutoProxyCreator beanTypeAutoProxyCreator = new BeanTypeAutoProxyCreator();
beanTypeAutoProxyCreator.setTargetBeanType(DruidDataSource.class);
beanTypeAutoProxyCreator.setInterceptorNames("druidStatInterceptor");
return beanTypeAutoProxyCreator;
} /**
* RequestContextListener注册
*/
@Bean
public ServletListenerRegistrationBean<RequestContextListener> requestContextListenerRegistration() {
return new ServletListenerRegistrationBean<>(new RequestContextListener());
} /**
* 将swagger-ui.html 添加 到 resources目录下
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/web_frontend/**").addResourceLocations("classpath:/web_frontend/"); } }
至此,所有错误异常都能捕捉到,统一处理了~~
配置springboot在访问404时自定义返回结果以及统一异常处理的更多相关文章
- Eclipse配置Tomcat,访问404错误
我从官网上面下载的tomcat6,直接启动发现正常使用,但是在Eclipse绑定后启动,访问localhost:8080,本来应该是tomcat的主页,但是却报了404错误. 百度搜索了一下,原来是t ...
- SpringBoot2配置prometheus浏览器访问404
背景:SpringBoot2的项目要配置 actuator + prometheus的健康检查,按照教程配置好之后再浏览器测试 http://localhost:port/prometheus 后40 ...
- SpringBoot入门(五)——自定义配置
本文来自网易云社区 大部分比萨店也提供某种形式的自动配置.你可以点荤比萨.素比萨.香辣意大利比萨,或者是自动配置比萨中的极品--至尊比萨.在下单时,你并没有指定具体的辅料,你所点的比萨种类决定了所用的 ...
- springboot统一异常处理及返回数据的处理
一.返回code数据的处理 代码: Result.java /** * http请求返回的最外层对象 * Created by 廖师兄 * 2017-01-21 13:34 */ public cla ...
- IntelliJ IDEA+SpringBoot中静态资源访问路径陷阱:静态资源访问404
IntelliJ IDEA+SpringBoot中静态资源访问路径陷阱:静态资源访问404 .embody{ padding:10px 10px 10px; margin:0 -20px; borde ...
- springboot + thymeleaf静态资源访问404
在使用springboot 和thtmeleaf开发时引用静态资源404,静态资源结如下: index.html文件: <!DOCTYPE html> <html xmlns:th= ...
- springboot配置静态资源访问路径
其实在springboot中静态资源的映射文件是在resources目录下的static文件夹,springboot推荐我们将静态资源放在static文件夹下,因为默认配置就是classpath:/s ...
- Nginx自定义404页面并返回404状态码
Nginx定义404页面并返回404状态码, WebServer是nginx,直接告诉我应该他们配置了nginx的404错误页面,虽然请求不存在的资源可以成功返回404页面,但返回状态码确是200. ...
- thinkphp配置rewrite模式访问时不生效 出现No input file specified解决方法
使用thinkphp配置rewire模式的路径访问网站时, 直接复制官网的.htaccess文件的代码复制过去 1 2 3 4 5 6 <IfModule mod_rewrite.c> ...
随机推荐
- 10.排序数组中和为给定值的两个数字[Find2NumbersWithGivenSum]
[题目] 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出任意一对即可. 例如输入数组1 ...
- [转载] 视音频数据处理入门:RGB、YUV像素数据处理
===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...
- Info.plist字段列表详解
常用字段: 1.获取版本信息: NSDictionary*infoDic = [[NSBundle mainBundle] infoDictionary]; NSString *localVersio ...
- 4 字符串 Swift/Objective -C ——《Swift3.0从入门到出家》
4 字符串 Swift and Object-C 字符串由多个字符组成,使用 “” 引起的内容 swift语言中提供了两种字符串:可变字符串和不可变字符串 可变字符串:字符串的内容可以修改,字符串 ...
- Jquery3.x高版本支持IE8
最近在做项目的时候,遇到一个安全漏洞的问题 检测到目标站点存在javascript框架库漏洞 解决办法是 将受影响的javascript框架库升级到最新版本. 好吧,就给你升吧,升完之后,我的天啊,尽 ...
- PCBA 的收货要求记录
PCBA 的收货要求记录 性能 功能性测试 外观 标识 需要可以识别的料号(客户料号或货号) 贴片 元件焊点饱满 元件参数统一 后焊 插件焊盘饱满 插件焊盘不可以有小孔 焊盘不可以有漏铜上锡均匀 体积 ...
- java中String和char的区别
首先来看一下Java的数据类型.Java 包括两种数据类型: 1.原始数据类型(primitive data type):byte,short, char, int, long,float,doubl ...
- php-fpm.conf 配置文件详解
php-fpm.conf 配置文件详解 [global] pid = run/php-fpm.pid error_log = log/php-fpm.log log_level = notice # ...
- php redis 常用方法
一些php redis 常用的方法: 1.hGet($key,$hashKey) Redis Hget 命令用于返回哈希表中指定字段的值. <?php $redis = new redis(); ...
- (转)WebApi 上传文件
本文转载自:http://www.cnblogs.com/zj1111184556/p/3494502.html public class FileUploadController : ApiCont ...