SpringBoot如何設(shè)置404、500返回統(tǒng)一格式j(luò)son
SpringBoot默認訪問不存在資源就會出現(xiàn)404

解決后:

主要是添加下面配置:
# 自定義 #出現(xiàn)錯誤時, 直接拋出異常 spring.mvc.throw-exception-if-no-handler-found=true #不要為我們工程中的資源文件建立映射 spring.web.resources.add-mappings=false
全局處理異常:
package com.qykhhr.dujiaoshouservice.exceptionhandler;
import com.qykhhr.dujiaoshouservice.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.sql.SQLIntegrityConstraintViolationException;
/**
* 異常處理機制
* 先找到特定異常處理機制,如果沒有就會調(diào)用Exception異常處理機制
*/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 指定出現(xiàn)什么異常來執(zhí)行這個方法
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public R error(Exception e){
e.printStackTrace();
if (e instanceof SQLIntegrityConstraintViolationException){
return R.error().message("數(shù)據(jù)庫主鍵沖突,如是本人,請聯(lián)系管理員");
}else if (e instanceof org.springframework.web.servlet.NoHandlerFoundException){
return R.error().message("找不到資源,/(ㄒoㄒ)/~~");
}
return R.error().message("內(nèi)部服務(wù)器錯誤,/(ㄒoㄒ)/~~!");
}
/**
* 自定義異常處理
* @param e
* @return
*/
@ExceptionHandler(DujiaoshouException.class)
@ResponseBody
public R error(DujiaoshouException e){
log.error(e.getMessage());
e.printStackTrace();
return R.error().code(e.getCode()).message(e.getMsg());
}
}
統(tǒng)一結(jié)果返回:
package com.qykhhr.dujiaoshouservice.util;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
/**
* 統(tǒng)一返回結(jié)果的類
* @author 雨林
*/
@Data
public class R {
private Boolean success;
private Integer code;
private String message;
private Map<String,Object> data = new HashMap<>();
// 把構(gòu)造方法私有化,只能使用提供的靜態(tài)方法
private R(){
}
// 成功靜態(tài)方法
public static R ok(){
R r = new R();
r.setSuccess(true);
r.setCode(ResultCode.SUCCESS);
r.setMessage("成功");
return r;
}
// 失敗靜態(tài)方法
public static R error(){
R r = new R();
r.setSuccess(false);
r.setCode(ResultCode.ERROR);
r.setMessage("失敗");
return r;
}
public R message(String message){
this.setMessage(message);
return this;
}
public R code(Integer code){
this.setCode(code);
return this;
}
public R data(Map<String, Object> map){
this.setData(map);
return this;
}
public R data(String key, Object value){
this.data.put(key, value);
return this;
}
}
我有發(fā)現(xiàn)了一個問題,因為我配置了映射,當我訪問upload請求找不到文件時,依舊返回了SpingBoot的默認404頁面。
我的理解就是訪問/upload請求時,SpringBoot會自動到映射的文件夾里面去尋找文件,就會以為這個請求已經(jīng)被處理了,就不會報找不到處理的異常。而是報除了/error請求的錯誤。
upload.image.path=/util/images/ upload.apk.path=/util/apk/ upload.crash.exception.file.path=/util/crash/
/**
* 資源映射路徑,只能配置一個映射
*/
@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {
@Value("${upload.file.path}")
private String uploadPath;
@Value("${upload.image.path}")
private String uploadImagePath;
@Value("${upload.crash.exception.file.path}")
private String uploadCrashExceptionFilePath;
@Value("${upload.apk.path}")
private String uploadApkPath;
/**
* 將D:\\upload下的文件映射到當前項目/upload/下
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/static/");
//addResourceHandler()里配置需要映射的文件夾,此處代表映射文件夾user下的所有資源。
//addResourceLocations()配置文件夾在系統(tǒng)中的路徑,使用絕對路徑,格式為“file:你的路徑/” 后面的 / 必須加上,否則映射失效
// registry.addResourceHandler("/upload/**").addResourceLocations("file:D:/dujiaoshouapp/");
// registry.addResourceHandler("/upload/**").addResourceLocations("file:"+uploadPath);
registry.addResourceHandler("/upload/images/**").addResourceLocations("file:"+uploadImagePath);
registry.addResourceHandler("/upload/crash/**").addResourceLocations("file:"+uploadCrashExceptionFilePath);
registry.addResourceHandler("/upload/apk/**").addResourceLocations("file:"+uploadApkPath);
}
}

解決

可以看到SpringBoot最終保留了/error請求作為后備,未解決的請求都會走到/error路徑里面,我們可以定義一個攔截器,攔截這個/error請求,轉(zhuǎn)到我們自己定義的請求里面。
@Component
public class ExceptionInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate redisTemplate;
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
if (modelAndView != null){
// 防止出現(xiàn)空指針
// 請求轉(zhuǎn)到 /
modelAndView.setViewName("/");
}
}
}然后在WebConfig里面配置上攔截器
@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {
@Autowired
private ExceptionInterceptor exceptionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(exceptionInterceptor);
super.addInterceptors(registry);
}最后再定義一個Controller,處理 / 請求
package com.qykhhr.dujiaoshouservice.controller;
import com.qykhhr.dujiaoshouservice.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class ExceptionController {
@RequestMapping("/")
public R error() {
log.info("處理 /error 請求");
return R.error().message("訪問資源無效!");
}
}可以看到訪問的結(jié)果:

OK,我們現(xiàn)在完全是統(tǒng)一的返回格式了~!
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
各種格式的編碼解碼工具類分享(hex解碼 base64編碼)
這篇文章主要介紹了各種格式的編碼解碼工具類,集成Commons-Codec、Commons-Lang及JDK提供的編解碼方法2014-01-01

