摘要

文章是根据江南一点雨(松哥)的视频进行总结

江南一点雨博客

全局异常处理

通常情况下,我们都需要对自己定义的异常进行相应的处理。捕获指定的异常方式如下:

  1. @ControllerAdvice
  2. public class ExceptionHandlers {
  3. // 捕获自定义异常类进行处理
  4. @ExceptionHandler(CustomException.class)
  5. public ModelAndView handler(CustomException e) {
  6. ModelAndView modelAndView = new ModelAndView("customException"); //自定义异常错误页面
  7. modelAndView.addObject("msg", e.getMessage());
  8. // ...
  9. return modelAndView;
  10. }
  11. }

自定义错误页面

若服务器抛出404错误码(页面找不到)时,通常会返回如下页面:

而我们需要指定在服务器抛出相应的错误码时,跳转到指定的动态或静态页面。

源码阅读

参考默认的视图解析器org.springframework.boot.autoconfigure.web.servlet.error.DefaultErrorViewResolver源码,取出部分代码片段如下:

  1. public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
  2. private static final Map<Series, String> SERIES_VIEWS; // 存放不同错误码对应的视图
  3. // 添加默认的视图
  4. static {
  5. Map<Series, String> views = new EnumMap<>(Series.class);
  6. views.put(Series.CLIENT_ERROR, "4xx");
  7. views.put(Series.SERVER_ERROR, "5xx");
  8. SERIES_VIEWS = Collections.unmodifiableMap(views);
  9. }
  10. ...
  11. // 开始解析错误视图
  12. @Override
  13. public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
  14. // status.value() 得到的是错误码
  15. // 寻找错误码指定的页面,如404就找名为404的页面
  16. ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
  17. // 若找不到错误码指定的页面,则400,401,403,404...都会去找4xx的页面
  18. if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
  19. modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
  20. }
  21. // 若modelAndView还是null,那么就返回上面的那个图片了
  22. return modelAndView;
  23. }
  24. private ModelAndView resolve(String viewName, Map<String, Object> model) {
  25. String errorViewName = "error/" + viewName;
  26. //首先去动态资源中查看是否存在对应的页面
  27. TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,
  28. this.applicationContext);
  29. if (provider != null) {
  30. return new ModelAndView(errorViewName, model);
  31. }
  32. //若动态资源中找不到则到静态资源中寻找对应的页面
  33. return resolveResource(errorViewName, model);
  34. }
  35. //获取静态页面资源
  36. private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
  37. // 遍历静态资源,查找是否有对应的页面
  38. for (String location : this.resourceProperties.getStaticLocations()) {
  39. try {
  40. Resource resource = this.applicationContext.getResource(location);
  41. resource = resource.createRelative(viewName + ".html");
  42. if (resource.exists()) {
  43. return new ModelAndView(new HtmlResourceView(resource), model);
  44. }
  45. }
  46. catch (Exception ex) {
  47. }
  48. }
  49. return null;
  50. }
  51. ...
  52. }

阅读源码总结

1.首先会去找指定错误码的页面,若指定页面找不到则找4xx、5xx页面,(400、401...都会找4xx)

2.先到动态资源下的error目录寻找,再到静态资源中的error目录寻找

实现

如果为动态资源的页面,返回的ModelAttribute可以查看org.springframework.boot.web.servlet.error.DefaultErrorAttributes, 返回的数据如下:

timestamp

status

error

message

...

thymeleaf下页面使用如下:

  1. <table>
  2. <tr>
  3. <td th:text="${status}"></td>
  4. </tr>
  5. <tr>
  6. <td th:text="${message}"></td>
  7. </tr>
  8. </table>

若需要扩展,则继承DefaultErrorAttributes,对扩展类加@Component注释:

  1. @Component
  2. public class CustomErrorAttribute extends DefaultErrorAttributes {
  3. // 扩展
  4. }

CORS跨域

在前后端分离进行开发的情况下,一般都需要设置跨域访问,springBoot提供CORS跨域设置如下:

  1. @Configuration
  2. public class WebMvcConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addCorsMappings(CorsRegistry registry) {
  5. registry.addMapping("/**") //所有前缀
  6. .allowedOrigins("http://localhost:8081") //跨域地址(前端地址)
  7. .allowedHeaders("*") //允许所有请求头
  8. .allowedMethods("*") //允许通过所有方法
  9. .maxAge(30 * 1000); //探测请求的有效期
  10. }
  11. }

注册拦截器

拦截器可以拦截request请求,若自定义权限认证的功能,就可以使用拦截器去进行实现。

  1. public class MyInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. return false;
  5. }
  6. public void postHandle ...
  7. public void afterCompletion ...
  8. }

preHandler执行方法前调用,postHandler在返回视图前调用,afterCompletion 在方法执行完后调用。

添加拦截器到配置中,重写addInterceptors方法

  1. @Configuration
  2. public class WebMvcConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addInterceptors(InterceptorRegistry registry) {
  5. registry.addInterceptor(myInterceptor())
  6. .addPathPatterns("/**"); //拦截所有路径
  7. }
  8. @Bean
  9. MyInterceptor myInterceptor() {
  10. return new MyInterceptor();
  11. }
  12. }

整合Servlet

首先自定义的Servelt继承javax.servlet.http.HttpServlet;使用@WebServlet进行url映射

  1. @WebServlet(urlPatterns = "/myservlet")
  2. public class MyServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. System.out.println("doget");
  6. }
  7. }

在启动类xxxApplication对自定义的Servlet的目录进行扫描

  1. @ServletComponentScan(basePackages = "org.java.servlet")

这就可以成功访问到啦!localhost:8080/myservlet

扩展(怕忘记了,记一下):

request监听实现接口javax.servlet.ServletRequestListener, 然后对request监听类使用javax.servlet.annotation.WebListener注解;

request拦截器实现接口javax.servlet.Filter,然后对拦截器使用javax.servlet.annotation.WebFilter注解,如:

  1. @WebListener
  2. public class MyRequestListener implements ServletRequestListener {
  3. @Override
  4. public void requestDestroyed(ServletRequestEvent sre) {System.out.println("requestDestroyed");}
  5. @Override
  6. public void requestInitialized(ServletRequestEvent sre) {System.out.println("requestInitialized");}
  7. }
  8. @WebFilter(urlPatterns = "/*") //对所有目录进行拦截
  9. public class MyFilter implements Filter {
  10. @Override
  11. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  12. System.out.println("doFilter");
  13. chain.doFilter(request,response);
  14. }
  15. }

上述的监听器和拦截器一定要在@ServletComponentScan的扫描目录下或子目录。

若文章有错误或疑问,可在下方评论,Thanks♪(・ω・)ノ。

个人博客网址: https://colablog.cn/

如果我的文章帮助到您,可以关注我的微信公众号,第一时间分享文章给您

SpringBoot Web篇笔记(一)的更多相关文章

  1. SpringBoot Web篇(二)

    摘要 继上一篇 SpringBoot Web篇(一) 文件上传 当我们服务器需要接收用户上传的文件时,就需要使用MultipartFile作为参数接收文件.如下: @PostMapping(" ...

  2. SpringBoot Web学习笔记

    一.资源的访问: 情形一.所有的  /webjars/**  都会去 classpath:/META_INFO/resource/webjars/ 下找资源: webjars:以jar包的方式引入静态 ...

  3. [SpringBoot]Web综合开发-笔记

    Web开发 Json接口开发 @RestController 给类添加 @RestController 即可,默认类中的方法都会以 json 的格式返回. 自定义filter filter作用: 用于 ...

  4. SpringBoot系列教程web篇之过滤器Filter使用指南扩展篇

    前面一篇博文介绍了在 SpringBoot 中使用 Filter 的两种使用方式,这里介绍另外一种直接将 Filter 当做 Spring 的 Bean 来使用的方式,并且在这种使用方式下,Filte ...

  5. SpringBoot系列教程Web篇之开启GZIP数据压缩

    本篇可以归纳在性能调优篇,虽然内容非常简单,但效果可能出乎预料的好: 分享一个真实案例,我们的服务部署在海外,国内访问时访问服务时,响应有点夸张:某些返回数据比较大的接口,耗时在 600ms+上,然而 ...

  6. SpringBoot系列教程web篇Listener四种注册姿势

    java web三要素Filter, Servlet前面分别进行了介绍,接下来我们看一下Listener的相关知识点,本篇博文主要内容为SpringBoot环境下,如何自定义Listener并注册到s ...

  7. SpringBoot系列教程web篇Servlet 注册的四种姿势

    原文: 191122-SpringBoot系列教程web篇Servlet 注册的四种姿势 前面介绍了 java web 三要素中 filter 的使用指南与常见的易错事项,接下来我们来看一下 Serv ...

  8. SpringBoot系列教程web篇之过滤器Filter使用指南

    web三大组件之一Filter,可以说是很多小伙伴学习java web时最早接触的知识点了,然而学得早不代表就用得多.基本上,如果不是让你从0到1写一个web应用(或者说即便从0到1写一个web应用) ...

  9. SpringBoot系列教程web篇之自定义异常处理HandlerExceptionResolver

    关于Web应用的全局异常处理,上一篇介绍了ControllerAdvice结合@ExceptionHandler的方式来实现web应用的全局异常管理: 本篇博文则带来另外一种并不常见的使用方式,通过实 ...

随机推荐

  1. 总结下var、let 和 const 的区别

    一.var变量 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  2. CONVERT用法指南,时间字段截取方法

    语法: CONVERT(VARCHAR(7),<字段名称>,121) 时间转字符:select CONVERT(VARCHAR(7),dyxq,121),* from TBYPKC03-- ...

  3. Json模块(dumps、loads、dump、load)函数篇

    # dumps.loads函数 """json.dumps()用于将dict类型的数据转成strjson.loads()用于将str类型的数据转成dict. " ...

  4. Bitset改进你的程序质量

    1:Bitset介绍 BitSet 是用于存储二进制位和对二进制进行操作的 Java 数据结构, 此类实现了一个按需增长的位向量.位 set 的每个组件都有一个 boolean 值.用非负的整数将 B ...

  5. django开发中关于外键设置

    django开发中关于外键设置 我们建模型的时候会用到ForeignKey 而由于外键的约数会导致一些保存 所有我们ctrl+左键进入源码 源码 def __init__(self, to, on_d ...

  6. [Tyvj Jan]青蛙跳荷叶

    题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Local 题目描述 从前,有一个小青蛙决定去荷叶上练习跳跃.现在有n个荷叶排成一排,小青蛙一开始在最左 ...

  7. ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

    配置spring+shiro时,启动tomcat报错异常 严重: Context initialization failedorg.springframework.beans.factory.Bean ...

  9. MySQL GROUP_CONCAT()函数 -- 字段合并查询

    在做查询的时候遇到一个问题,今天分享一下解决方法. 先看一下我想要什么效果. 清单名称类型要点,后面两列为清单步骤(外键表) 但我并不想让主表的内容重复那么多遍,于是 distinct去重.子查询.左 ...

  10. day34作业

    作业 查看岗位是teacher的员工姓名.年龄 select name,age from teacher where post='teacher'; 查看岗位是teacher且年龄大于30岁的员工姓名 ...