springboot默认访问不存在资源就会出现404
解决后:
主要是添加下面配置:
# 自定义 #出现错误时, 直接抛出异常 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 { /** * 指定出现什么异常来执行这个方法 * @param e * @return */ @exceptionhandler(exception.class) @responsebody public r error(exception e){ e.printstacktrace(); if (e instanceof sqlintegrityconstraintviolationexception){ return r.error().message("数据库主键冲突,如是本人,请联系管理员"); }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()); } }
统一结果返回:
package com.qykhhr.dujiaoshouservice.util; import lombok.data; import java.util.hashmap; import java.util.map; /** * 统一返回结果的类 * @author 雨林 */ @data public class r { private boolean success; private integer code; private string message; private map<string,object> data = new hashmap<>(); // 把构造方法私有化,只能使用提供的静态方法 private r(){ } // 成功静态方法 public static r ok(){ r r = new r(); r.setsuccess(true); r.setcode(resultcode.success); r.setmessage("成功"); return r; } // 失败静态方法 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; } }
我有发现了一个问题,因为我配置了映射,当我访问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()配置文件夹在系统中的路径,使用绝对路径,格式为“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){ // 防止出现空指针 // 请求转到 / 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,我们现在完全是统一的返回格式了~!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论