前一篇说到了怎么自定错误页面:链接地址
在一些的错误页面需要一些自定的数据,需要同时将这些数据提交到了错误页面展示,
在此之前要先说一下SpringBoot是怎么获取到的错误信息:
在BasicErrorCOntroller
类中errorHtml
方法中有一段代码
Map<String, Object> model = Collections
.unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
在这里有getErrorAttributes
方法获取的错误参数,进入这个方法,这个方法是在AbstractErrorController
类中
protected Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
WebRequest webRequest = new ServletWebRequest(request);
return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace);
}
发现这个返回的值是errorAttributes
中的一个方法,这个errorAttributes
对象是一个ErrorAttributes
门面里的方法,而ErrorAttributes
是一个接中,所以要找一个这个接口的实现类.那么这个实现类在哪里呢?
private final ErrorAttributes errorAttributes;
在上一篇文章《SpringBoot的错误页面解析原理》中说到过这么一段代码,在ErrorMvcAutoConfiguration
自动配置错误的类中有如下这么一段代码,
public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver, Ordered {
这个DefaultErrorAttributes类就是ErrorAttributes接口的实现类
@Bean
@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
public DefaultErrorAttributes errorAttributes() {
return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());
}
这个类会自已的创建放入IOC容器中,在第二个注解
ConditionalOnMissingBean
,这个注解是如果在容器中有一个ErrorAttributes的实现类就不会使用下面的代码来将DefaultErrorAttributes放到容器中.
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> errorAttributes = new LinkedHashMap<>();
errorAttributes.put("timestamp", new Date());
addStatus(errorAttributes, webRequest);
addErrorDetails(errorAttributes, webRequest, includeStackTrace);
addPath(errorAttributes, webRequest);
return errorAttributes;
}
在getErrorAttributes里面可以看到有一些关于添加数据的方法,这些方法我就不粘出来了,可能自已查看
所以在自定数据的时候,我只要重写DefaultErrorAttributes类中的getErrorAttributes方法即可.
实现自定数据-这个例子通过异常来举例
@Controller
public class UserController {
@RequestMapping(path = {"hello/{username}"})
public String hello(@PathVariable("username") String user) {
if(user.equals("aaa")) {
throw new UserNotFIndExceaption();
}
return "index";
}
}
这段代码很容易看懂,就是一个控制器,通过hello/{username}
来访问,当username是aaa出现异常
创建一个异常继承RuntimeException
,这样可以抛出来
public class UserNotFIndExceaption extends RuntimeException{
public UserNotFIndExceaption() {
super("用户不存在");
}
}
创建一个全局的异常处理,当触发了UserNotFIndExceaption来执行下面的方法
@ControllerAdvice
public class MyExecaption{
@ExceptionHandler(UserNotFIndExceaption.class)
public String handleException(Exception e,HttpServletRequest request) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("code","user.notexist");
map.put("message", e.getMessage());
map.put("qwe","123");
request.setAttribute("javax.servlet.error.status_code", 404);
return "forward:/error";
}
}
继承DefaultErrorAttributes
类重写getErrorAttributes
方法
import java.util.Map;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
@Component
public class MyErrorAtt extends DefaultErrorAttributes{
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
map.put("com","123");
return map;
}
}
这样当在BasicErrorCOntroller
中获取错误的数据的时候就会调用这个方法
这样几乎就实现了自定数据,为什么说是几乎是因为现在还没有办法拿到在MyExecaption
类中定义的数据,
因为在里只是转发到了/error
,并没有将MyExecaption
里面定义的map数据携带过去,
这些数据可以能过request携带,因为放到request中有其它的放法中也可以得到,修改MyExecaption
代码中的handleException
.
@ExceptionHandler(UserNotFIndExceaption.class)
public String handleException(Exception e,HttpServletRequest request) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("code","user.notexist");
map.put("message", e.getMessage());
map.put("sgc","123");
request.setAttribute("javax.servlet.error.status_code", 404);
request.setAttribute("ext", map);
return "forward:/error";
}
在自已创建的MyErrorAtt
类中将数据得到就好了,在getErrorAttributes
的参数中有一个WebRequest
的对象,通过它就可以得到了,修改MyErrorAtt
中的getErrorAttributes
方法
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
map.put("com","123");
//通过webRequest得到放在reuqest中的方法
map.put("ext",webRequest.getAttribute("ext",0));
return map;
}
这样就可以在前端得到自定的数据了
在webRequest.getAttribute("ext",0)
中有第二个参数这个是表示通过什么得到这个数据,在RequestAttributes
有两个属性,在Rewqust中得到数据设置为0就好了
public interface RequestAttributes {
/**
* Constant that indicates request scope.
*/
int SCOPE_REQUEST = 0;
/**
* Constant that indicates session scope.
* <p>This preferably refers to a locally isolated session, if such
* a distinction is available.
* Else, it simply refers to the common session.
*/
int SCOPE_SESSION = 1;
注:我使用的是SpringBoot的2.1.9
的版本,这个里面有两个类的名字叫DefaultErrorAttributes
需要使用的是
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
这个包名要看清楚,不要导错了包.
本文链接:https://sangguangcan.cn/archives/11.html
转载时须注明出处及本声明