当前位置: 首页 > 后端技术 > Java

2.spring系列404异常的捕获

时间:2023-04-01 23:10:19 Java

想起之前发过一篇spring统一返回的文章,最后提到404异常是抓不到的。这里我们将测试@RestControllerpublicclassTestController{@GetMapping("/test")publicStringinsert22(){return"hello";}}浏览器请求尝试http://localhost:8080/xxxerror#WhitelabelErrorPageThisapplicationhasnoexplicitmappingfor/error,soyouareseeingthisasafallback.WedDec2910:14:36CST2021Therewas意外错误(类型=未找到,状态=404)。springboot的处理方式springboot处理这个404的异常在BasicErrorController@Controller@RequestMapping("${server.error.path:${error.path:/error}}")publicclassBasicErrorControllerextendsAbstractErrorController{...........@OverridepublicStringgetErrorPath(){返回空值;}@RequestMapping(produces=MediaType.TEXT_HTML_VALUE)publicModelAndViewerrorHtml(HttpServletRequestrequest,HttpServletResponseresponse){HttpStatusstatus=getStatus(request);Map模型=集合.unmodifiableMap(getErrorAttributes(请求,getErrorAttributeOptions(请求,MediaType.TEXT_HTML)));response.setStatus(status.value());ModelAndViewmodelAndView=resolveErrorView(请求、响应、状态、模型);返回(modelAndView!=null)?modelAndView:newModelAndView("错误",模型);}//包含请求头“Accept”:“application/json”将放在这里@RequestMappingpublicResponseEntity>error(HttpServletRequestrequest){如果(状态==HttpStatus.NO_CONTENT){返回新的ResponseEntity<>(状态);}Mapbody=getErrorAttributes(request,getErrorAttributeOptions(request,MediaType.ALL));返回新的ResponseEntity<>(正文,状态);}..........}只要请求路径/error,就可以进入errorHtml方法,在浏览器中请求http://localhost:8080/error就可以进入这个方法解决了我用的springboot版本是2.3.7.RELEASE方案一:重写/错误请求该方案会直接丢弃HTML响应方式,但是在前后端分离模式下,后端很少使用ModelAndView@ControllerpublicclassNoFoundControllerextendsAbstractErrorController{publicNoFoundController(ErrorAttributeserrorAttributes){超级(错误属性);}/***默认路径/error可以通过server.error.path配置*/@RequestMapping(("${server.error.path:/error}"))publicResponseEntity>notFoundError(HttpServletRequest请求,HttpServletResponse响应){Mapmap=newHashMap<>(3);HttpStatus状态=getStatus(请求);map.put("code",status.value());map.put("数据",null);map.put("消息",status.toString());返回新的ResponseEntity<>(地图,状态);}/***springboot2.3.0新增server.error.path用于配置,这个被丢弃,之前的版本可以通过设置这个返回值直接修改默认的/error路径*/@OverridepublicStringgetErrorPath(){返回空值;}}方案二:重写BasicErrorController中的错误处理不能改变html响应为json返回,请求必须有"Accept":"application/json"才能响应json@Controller@RequestMapping("${server.error.path:${error.path:/error}}")publicclassMyBasicErrorControllerextendsBasicErrorController{publicMyBasicErrorController(ServerPropertiesserverProperties){//importorg.springframework.boot.web.servlet.error.DefaultErrorAttributes;super(newDefaultError,Attributes)serverProperties.getError());}/***JSON响应*/@OverridepublicResponseEntity>error(HttpServletRequestrequest){Mapmap=newHashMap<>();HttpStatus状态=getStatus(请求);map.put("code",status.value());map.put("数据",null);map.put("消息",status.toString());返回新的ResponseEntity<>(地图,状态);}/***HTML响应,根据需要自行处理*/@OverridepublicModelAndViewerrorHtml(HttpServletRequest请求,HttpServletResponse响应){returnsuper.errorHtml(请求,响应);}}其中MyBasicErrorController的构造函数可以参考spring自动配置ErrorMvcAutoConfiguration中的参数//源码:publicclassErrorMvcAutoConfiguration{privatefinalServerPropertiesserverProperties;publicErrorMvcAutoConfiguration(ServerPropertiesserverProperties){this.serverProperties=serverProperties;}@Bean@ConditionalOnMissingBean(value=ErrorAttributes.class,search=SearchStrategy.CURRENT)publicDefaultErrorAttributeserrorAttributes(){//ErrorAttributesreturnnewDefaultErrorAttributes();}@Bean@ConditionalOnMissingBean(value=ErrorController.class,search=SearchStrategy.CURRENT)publicBasicErrorControllerbasicErrorController(ErrorAttributeserrorAttributes,ObjectProvidererrorViewResolvers){//serverProperties.getError返回新的BasicErrorController(errorAttributes,this.serverProperties.getError(),errorViewResolvers.orderedStream().collect(Collectors.toList()));}.........}最后附加上完整代码:@GetterpublicclassBusinessExceptionextendsRuntimeException{privateIntegercode;publicBusinessException(整数代码,字符串消息){super(消息);这个。代码=代码;}publicBusinessException(Stringmessage){super(message);}}--------------------------------------------------------------------------------------@ControllerAdvice@ResponseBody@Slf4jpublicclassGlobalException{@ExceptionHandler(value=BusinessException.class)publicResponseModelbusinessExceptionError(BusinessExceptione){log.error("业务异常",e);if(e.getCode()!=null){返回ResponseModel.error(e.getCode(),e.getMessage());}返回ResponseModel.error(e.getMessage());}@ExceptionHandler(value=Exception.class)publicResponseModelexceptionError(Exceptione){log.error("系统异常",e);返回ResponseModel.error();}}--------------------------------------------------------------------------------------@GetterpublicenumResponseEnum{成功(0,"OK"),PARAMETER_ERROR(1,"参数异常"),NO_FOUND(404,"未找到"),SYSTEM_ERROR(500,"服务器异常,请联系系统管理员");ResponseEnum(整数代码,字符串消息){this.code=code;this.message=消息;}私有最终整数代码;私有最终字符串消息;}--------------------------------------------------------------------------------------公开课ResponseModel{私有整数代码;私人字符串消息;私有T数据;publicResponseModel(整数代码,字符串消息,T数据){this.code=code;this.message=消息;这个。数据=数据;}公共静态ResponseModelok(){返回ok(null);}publicstaticResponseModelok(Tdata){returnnewResponseModel<>(ResponseEnum.SYSTEM_ERROR.getCode(),ResponseEnum.SYSTEM_ERROR.getMessage(),数据);}publicstaticResponseModelok(Tdata,Stringmessage){returnnewResponseModel<>(ResponseEnum.SYSTEM_ERROR.getCode(),message,data);}publicstaticResponseModelerror(IntegerstatusCode,Stringmessage){returnnewResponseModel<>(statusCode,message,null);}publicstaticResponseModelerror(Stringmessage){returnerror(ResponseEnum.SYSTEM_ERROR.getCode(),message);}publicstaticResponseModelerror(){returnerror(ResponseEnum.SYSTEM_ERROR.getCode(),ResponseEnum.SYSTEM_ERROR.getMessage());}}---------------------------------------------------------------------------------------@ControllerpublicclassNoFoundControllerextendsAbstractErrorController{publicNoFoundController(ErrorAttributeserrorAttributes){super(errorAttributes);}/***默认路径/error可以通过server.error.path配置*/@RequestMapping(("${server.error.path:/error}"))publicResponseEntity>notFoundError(HttpServletRequest请求,HttpServletResponse响应){Mapmap=newHashMap<>(3);HttpStatus状态=getStatus(请求);map.put("code",status.value());map.put("数据",null);map.put("消息",status.toString());返回新的ResponseEntity<>(地图,状态);}/***在springboot2.3.0中,新增了一个server.error.path进行配置。这个被丢弃了。之前的版本可以通过设置这个返回值直接修改默认的/error路径*/@OverridepublicStringgetErrorPath(){returnnull;}}感谢大家阅读到最后,如有错误欢迎指正。