在搭建項(xiàng)目框架的時(shí)候用的是springboot但惶,想統(tǒng)一處理異常,但是發(fā)現(xiàn)404的錯(cuò)誤總是捕捉不到,總是返回的是springBoot自帶的錯(cuò)誤結(jié)果信息。
如下是springBoot自帶的錯(cuò)誤結(jié)果信息:
{
? "timestamp": 1492063521109,
? "status": 404,
? "error": "Not Found",
? "message": "No message available",
? "path": "/rest11/auth"
}
配置文件中加上如下配置:
properties格式:
#出現(xiàn)錯(cuò)誤時(shí), 直接拋出異常
spring.mvc.throw-exception-if-no-handler-found=true
#不要為我們工程中的資源文件建立映射
spring.resources.add-mappings=false
yml格式:
spring:
#出現(xiàn)錯(cuò)誤時(shí), 直接拋出異常(便于異常統(tǒng)一處理摇予,否則捕獲不到404)
? mvc:
? ? throw-exception-if-no-handler-found: true
#不要為我們工程中的資源文件建立映射
? resources:
? ? add-mappings: false
下面是我SpringMVC-config配置代碼,里面包含統(tǒng)一異常處理代碼吗跋,都貼上:
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;//當(dāng)前激活的配置文件
? ? //使用阿里 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);
? ? }
? ? //統(tǒng)一異常處理
? ? @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) {//業(yè)務(wù)失敗的異常侧戴,如“賬號或密碼錯(cuò)誤”
? ? ? ? ? ? ? ? ? ? result = new ResponseMsg("501", "業(yè)務(wù)層出錯(cuò):" + e.getMessage());
? ? ? ? ? ? ? ? ? ? logger.info(e.getMessage());
? ? ? ? ? ? ? ? } else if (e instanceof NoHandlerFoundException) {
? ? ? ? ? ? ? ? ? ? result = new ResponseMsg("404", "接口 [" + request.getRequestURI() + "] 不存在");
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? result = new ResponseMsg("500", "接口 [" + request.getRequestURI() + "] 錯(cuò)誤,請聯(lián)系管理員跌宛!");
? ? ? ? ? ? ? ? ? ? String message;
? ? ? ? ? ? ? ? ? ? if (handler instanceof HandlerMethod) {
? ? ? ? ? ? ? ? ? ? ? ? HandlerMethod handlerMethod = (HandlerMethod) handler;
? ? ? ? ? ? ? ? ? ? ? ? message = String.format("接口 [%s] 出現(xiàn)異常酗宋,方法:%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,多個(gè)的話可以用逗號分隔入问,默認(rèn)為*
? ? ? ? ? ? ? ? .allowedMethods("GET", "POST", "HEAD", "PUT", "DELETE") // 指請求方式 默認(rèn)為*
? ? ? ? ? ? ? ? .allowCredentials(false) // 支持證書丹锹,默認(rèn)為true
? ? ? ? ? ? ? ? .maxAge(3600) // 最大過期時(shí)間,默認(rèn)為-1
? ? ? ? ? ? ? ? .allowedHeaders("*");
? ? }
? ? //添加攔截器
? ? @Override
? ? public void addInterceptors(InterceptorRegistry registry) {
? ? ? ? //接口登錄驗(yàn)證攔截器
? ? ? ? if (!"dev".equals(env)) { //開發(fā)環(huán)境忽略登錄驗(yàn)證
? ? ? ? ? ? registry.addInterceptor(new HandlerInterceptorAdapter() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
? ? ? ? ? ? ? ? ? ? //驗(yàn)證登錄
? ? ? ? ? ? ? ? ? ? Object obj = request.getSession().getAttribute(Const.LOGIN_SESSION_KEY);
? ? ? ? ? ? ? ? ? ? if (obj != null) {
? ? ? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? logger.warn("請先登錄芬失!==> 請求接口:{}楣黍,請求IP:{},請求參數(shù):{}",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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();
? ? ? ? }
? ? ? ? // 如果是多級代理棱烂,那么取第一個(gè)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監(jiān)控 配置URI攔截策略
? ? *
? ? * @return
? ? */
? ? @Bean
? ? public FilterRegistrationBean druidStatFilter() {
? ? ? ? FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
? ? ? ? // 添加過濾規(guī)則.
? ? ? ? filterRegistrationBean.addUrlPatterns("/*");
? ? ? ? // 添加不需要忽略的格式信息.
? ? ? ? filterRegistrationBean.addInitParameter("exclusions", "/web_frontend/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid,/druid/*,/error,/login*");
? ? ? ? // 用于session監(jiān)控頁面的用戶名顯示 需要登錄后主動(dòng)將username注入到session里
? ? ? ? filterRegistrationBean.addInitParameter("principalSessionName", "username");
? ? ? ? return filterRegistrationBean;
? ? }
? ? /**
? ? * druid數(shù)據(jù)庫連接池監(jiān)控
? ? */
? ? @Bean
? ? public DruidStatInterceptor druidStatInterceptor() {
? ? ? ? return new DruidStatInterceptor();
? ? }
? ? /**
? ? * druid數(shù)據(jù)庫連接池監(jiān)控
? ? */
? ? @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/");
? ? }
}