SpringBoot如何設置404、500返回統(tǒng)一格式json
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; /** * 異常處理機制 * 先找到特定異常處理機制,如果沒有就會調用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("數據庫主鍵沖突,如是本人,請聯(lián)系管理員"); }else if (e instanceof org.springframework.web.servlet.NoHandlerFoundException){ return R.error().message("找不到資源,/(ㄒoㄒ)/~~"); } return R.error().message("內部服務器錯誤,/(ㄒ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)一結果返回:
package com.qykhhr.dujiaoshouservice.util; import lombok.Data; import java.util.HashMap; import java.util.Map; /** * 統(tǒng)一返回結果的類 * @author 雨林 */ @Data public class R { private Boolean success; private Integer code; private String message; private Map<String,Object> data = new HashMap<>(); // 把構造方法私有化,只能使用提供的靜態(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會自動到映射的文件夾里面去尋找文件,就會以為這個請求已經被處理了,就不會報找不到處理的異常。而是報除了/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請求,轉到我們自己定義的請求里面。
@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)空指針 // 請求轉到 / 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("訪問資源無效!"); } }
可以看到訪問的結果:
OK,我們現(xiàn)在完全是統(tǒng)一的返回格式了~!
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
各種格式的編碼解碼工具類分享(hex解碼 base64編碼)
這篇文章主要介紹了各種格式的編碼解碼工具類,集成Commons-Codec、Commons-Lang及JDK提供的編解碼方法2014-01-01