欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 前端技术 > javascript >内容正文

javascript

springboot返回modelandview 找不到视图-凯发k8官方网

发布时间:2024/10/8 javascript 0 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 springboot返回modelandview 找不到视图_springboot错误处理机制及原理 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

springboot错误信息处理机制

★ 在一个web项目中,总需要对一些错误进行界面或者json数据返回,已实现更好的用户体验,springboot中提供了对于错误处理的自动配置

errormvcautoconfiguration这个类存放了所有关于错误信息的自动配置。

1. springboot处理错误请求的流程

访问步骤:

  • 首先客户端访问了错误界面。例:404或者500
  • springboot注册错误请求/error。通过errorpagecustomizer组件实现
  • 通过basicerrorcontroller处理/error,对错误信息进行了自适应处理,浏览器会响应一个界面,其他端会响应一个json数据
  • 如果响应一个界面,通过defaulterrorviewresolver类来进行具体的解析。可以通过模板引擎解析也可以解析静态资源文件,如果两者都不存在则直接返回默认的错误json或者错误view
  • 通过defaulterrorattributes来添加具体的错误信息

源代码

//错误信息的自动配置 public class errormvcautoconfiguration {//响应具体的错误信息@beanpublic defaulterrorattributes errorattributes() {return}//处理错误请求@beanpublic basicerrorcontroller basicerrorcontroller() {return }//注册错误界面@beanpublic errormvcautoconfiguration.errorpagecustomizer errorpagecustomizer() {return } //注册错误界面,错误界面的路径为/error private static class errorpagecustomizer implements errorpageregistrar, ordered {//服务器基本配置private final serverproperties properties;public void registererrorpages(errorpageregistry errorpageregistry) {//获取服务器配置中的错误路径/errorerrorpage errorpage = new errorpage(this.dispatcherservletpath.getrelativepath(this.properties.geterror().getpath()));//注册错误界面errorpageregistry.adderrorpages(new errorpage[]{errorpage});} //this.properties.geterror() public class serverproperties{//错误信息的配置文件private final errorproperties error = new errorproperties(); }//getpath public class errorproperties {@value("${error.path:/error}")private string path = "/error"; //处理/error请求,从配置文件中取出请求的路径 @requestmapping({"${server.error.path:${error.path:/error}}"}) public class basicerrorcontroller extends abstracterrorcontroller {//浏览器行为,通过请求头来判断,浏览器返回一个视图@requestmapping(produces = {"text/html"}public modelandview errorhtml(httpservletrequest request, httpservletresponse response) {httpstatus status = this.getstatus(request);map model = collections.unmodifiablemap(this.geterrorattributes(request, this.isincludestacktrace(request, mediatype.text_html)));response.setstatus(status.value());modelandview modelandview = this.resolveerrorview(request, response, status, model);return modelandview != null ? modelandview : new modelandview("error", model);}//其他客户端行为处理,返回一个json数据@requestmappingpublic responseentity> error(httpservletrequest request) {httpstatus status = this.getstatus(request);if (status == httpstatus.no_content) {return new responseentity(status);} else {map body = this.geterrorattributes(request, this.isincludestacktrace(request, mediatype.all));return new responseentity(body, status);}} //添加错误信息 public class defaulterrorattributes implements errorattributes, handlerexceptionresolver, ordered {public map geterrorattributes(webrequest webrequest, boolean includestacktrace) {map errorattributes = new linkedhashmap();errorattributes.put("timestamp", new date());this.addstatus(errorattributes, webrequest);this.adderrordetails(errorattributes, webrequest, includestacktrace);this.addpath(errorattributes, webrequest);return errorattributes;}

2. 响应一个视图

步骤:

  • 客户端出现错误
  • springboot创建错误请求/error
  • basicerrorcontroller处理请求
@requestmapping(produces = {"text/html"})public modelandview errorhtml(httpservletrequest request, httpservletresponse response) {httpstatus status = this.getstatus(request);map model = collections.unmodifiablemap(this.geterrorattributes(request, this.isincludestacktrace(request, mediatype.text_html)));response.setstatus(status.value());//解析错误界面,返回一个modelandview,调用父类abstracterrorcontroller的方法modelandview modelandview = this.resolveerrorview(request, response, status, model);return modelandview != null ? modelandview : new modelandview("error", model);} public abstract class abstracterrorcontroller{private final list errorviewresolvers;protected modelandview resolveerrorview(httpservletrequest request, httpservletresponse response, httpstatus status, map model) {iterator var5 = this.errorviewresolvers.iterator();//遍历所有的错误视图解析器modelandview modelandview;do {if (!var5.hasnext()) {return null;}errorviewresolver resolver = (errorviewresolver)var5.next();//调用视图解析器的方法,modelandview = resolver.resolveerrorview(request, status, model);} while(modelandview == null);return modelandview;} } public interface errorviewresolver {modelandview resolveerrorview(httpservletrequest request, httpstatus status, map model); }
  • 处理具体的视图跳转
//处理视图跳转 public defaulterrorviewresolver{public modelandview resolveerrorview(httpservletrequest request, httpstatus status, map model) {//将状态码作为视图名称传入解析modelandview modelandview = this.resolve(string.valueof(status.value()), model);if (modelandview == null && series_views.containskey(status.series())) {modelandview = this.resolve((string)series_views.get(status.series()), model);}return modelandview;} //视图名称为error文件夹下的400.html等状态码文件private modelandview resolve(string viewname, map model) {string errorviewname = "error/" viewname;//是否存在模板引擎进行解析templateavailabilityprovider provider = this.templateavailabilityproviders.getprovider(errorviewname, this.applicationcontext);//存在则返回解析以后的数据,不存在调用resolveresource方法进行解析return provider != null ? new modelandview(errorviewname, model) : this.resolveresource(errorviewname, model);} //如果静态资源文件中存在,返回静态文件下的,如果不存在返回springboot默认的private modelandview resolveresource(string viewname, map model) {string[] var3 = this.resourceproperties.getstaticlocations();int var4 = var3.length;for(int var5 = 0; var5 < var4; var5) {string location = var3[var5];try {resource resource = this.applicationcontext.getresource(location);resource = resource.createrelative(viewname ".html");if (resource.exists()) {return new modelandview(new defaulterrorviewresolver.htmlresourceview(resource), model);}} catch (exception var8) {}}return null;}

应用:

  • 在模板引擎文件下创建error文件夹,里面放置各种状态码的视图文件,模板引擎会解析
  • 在静态资源下常见error文件夹,里面放置各种状态码的视图文件,模板引擎不会解析
  • 如果没有状态码文件,则返回springboot默认界面视图

3.响应一个json数据

在basicerrorcontroller处理/error请求的时候不适用浏览器默认请求

@requestmappingpublic responseentity> error(httpservletrequest request) {httpstatus status = this.getstatus(request);if (status == httpstatus.no_content) {return new responseentity(status);} else {//调用父类的方法获取所有的错误属性map body = this.geterrorattributes(request, this.isincludestacktrace(request, mediatype.all));return new responseentity(body, status);}} 父类方法: protected map geterrorattributes(httpservletrequest request, boolean includestacktrace) {webrequest webrequest = new servletwebrequest(request);//调用errorattributes接口的geterrorattributes方法,return this.errorattributes.geterrorattributes(webrequest, includestacktrace);} 添加错误信息 public class defaulterrorattributes{public map geterrorattributes(webrequest webrequest, boolean includestacktrace) {map errorattributes = new linkedhashmap();errorattributes.put("timestamp", new date());this.addstatus(errorattributes, webrequest);this.adderrordetails(errorattributes, webrequest, includestacktrace);this.addpath(errorattributes, webrequest);return errorattributes;}

返回的json数据有:

  • status
  • error
  • exception
  • message
  • trace
  • path

可以通过模板引擎获取这些值

4.自定义异常返回自定义的异常数据

4.1@controlleradvice注解

★ springmvc提供的注解,可以用来定义全局异常,全局数据绑定,全局数据预处理

@controlleradivice定义全局的异常处理

  • 通过@exceptionhandler(xxxexception.class)执行该方法需要处理什么异常,然后返回什么数据或者视图
//json数据返回 ,处理自定义用户不存在异常@responsebody@exceptionhandler(userexception.class)public map userexceptionmethod(userexception us){map map = new hashmap<>();map.put("message",us.getmessage());return map ;}

@controlleradvice定义全局数据

  • 通过@modelattribute(name="key")定义全局数据的key
  • 默认方法的返回值的名称作为键
  • 在controller中通过model获取对应的key的值
@controlleradvice public myconfig{@modelattribute(name = "key")public map defineattr(){map map = new hashmap<>();map.put("message","幻听");map.put("update","许嵩");return map ;}@controller public usercontroller{@getmapping("/hello")public map hello(model model){map asmap = model.asmap();system.out.println(asmap);//{key={message='上山',update='左手一式太极拳'}}return asmap ;} }

@controlleradvice处理预处理数据(当需要添加的实体,属性名字相同的时候)

  • 在controller的参数中添加modelattribute作为属性赋值的前缀
  • 在controlleradvice修饰的类中,结合initbinder来绑定对应的属性(该属性为modelattribite的value值
  • 在@initbinder修饰的方法中通过webdatabinder添加默认的前缀
@getter@setter public class book {private string name ;private int age ;@getter@setter public class music {private string name ;private string author ;//这种方式的处理,spring无法判断name属性给哪个bean赋值,所以需要通过别名的方式来进行赋值 @postmapping("book")public string book(book book , music music){system.out.println(book);system.out.println(music);return "404" ;}//使用以下的方式 @postmapping("/book")public string book(@modelattribute("b")book book , @modelattribute("m")music music){system.out.println(book);system.out.println(music);return "404" ;}public myconfiguration{@initbinder("b")public void b(webdatabinder webdatabinder){webdatabinder.setfielddefaultprefix("b.");}@initbinder("m")public void m(webdatabinder webdatabinder){webdatabinder.setfielddefaultprefix("m.");} }

4.2自定义异常json

浏览器和其他客户端都只能获取json数据

@controlleradvice public class myexceptionhandler {//处理userexception异常@responsebody@exceptionhandler(userexception.class)public map userexceptionmethod(userexception us){map map = new hashmap<>();map.put("message",us.getmessage());map.put("status","500");return map ;}

4.2自定义异常返回一个视图,拥有自适应效果

@exceptionhandler(userexception.class)public string allexception(userexception e,httpservletrequest request){map map = new hashmap<>();map.put("message",e.getmessage());map.put("load","下山");request.setattribute("mymessage",map);//设置状态码,springboot通过java.servlet.error.status_code来设置状态码request.setattribute("javax.servlet.error.status_code",400);return "forward:/error" ;}

当抛出userexception异常的时候,来到这个异常处理器,给这个请求中添加了数据,再转发到这个error请求中,交给errorpagecustomizer处理,由于设置了请求状态码400则返回的视图为400或4xx视图,或者直接返回一个json数据

{"timestamp": "2020-02-19t04:17:43.394 0000","status": 400,"error": "bad request","message": "用户名不存在异常","path": "/crud/user/login" }
  • 不足:json数据中没有显示我们自己定义的错误信息

4.3自定义错误信息

★ 前面提到springboot对错误信息的定义存在于defaulterrorattributes类的geterrorattributes中,我们可以直接继承这个类,或者实现errorattributes接口,然后将我们自己实现的错误处理器添加到容器中即可。

继承defaulterrorattributes和实现errorattributes接口的区别是,继承以后仍然可以使用springboot默认的错误信息,我们仅仅对该错误信息进行了增强;实现了errorattributes接口,完全自定义错误信息

  • 实现errorattributes接口
public class myerrorhandler implements errorattributes {public map geterrorattributes(webrequest webrequest, boolean includestacktrace) {map errorattributes = new linkedhashmap();errorattributes.put("timestamp", new date());errorattributes.put("status",500);errorattributes.put("message","用户不存在异常");return errorattributes;}@overridepublic throwable geterror(webrequest webrequest) {return null;}
  • 继承defaulterrorattributes的方法
public class myerrorhandler extends defaulterrorattributes {public map geterrorattributes(webrequest webrequest, boolean includestacktrace) {//调用父类方法,直接在默认错误信息的基础上添加map errorattributes = super.geterrorattributes(webrequest,includestacktrace);errorattributes.put("timestamp", new date());errorattributes.put("message","用户不存在异常");return errorattributes;}}
  • 将定义的错误信息器添加到容器中
    • 通过@component组件直接将myerrorhandler组件添加到容器中
    • 通过@bean在配置类中将组件添加到容器中
@beanpublic defaulterrorattributes geterrorhandler(){return new myerrorhandler();}
  • 下面解决上一节中没有出现我们自定义的异常信息
map errorattributes = super.geterrorattributes(webrequest,includestacktrace);errorattributes.put("timestamp", new date());errorattributes.put("message","用户不存在异常");//指定从哪个作用域中取值webrequest.getattribute("mymessage", requestattributes.scope_request);return errorattributes;

将在异常处理器中定义的错误信息取出,然后添加到错误信息中。

总结

以上是凯发k8官方网为你收集整理的springboot返回modelandview 找不到视图_springboot错误处理机制及原理的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

  • 上一篇:
  • 下一篇:
网站地图