摘要

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

江南一点雨博客

全局异常处理

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

@ControllerAdvice
public class ExceptionHandlers { // 捕获自定义异常类进行处理
@ExceptionHandler(CustomException.class)
public ModelAndView handler(CustomException e) {
ModelAndView modelAndView = new ModelAndView("customException"); //自定义异常错误页面
modelAndView.addObject("msg", e.getMessage());
// ...
return modelAndView;
}
}

自定义错误页面

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

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

源码阅读

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

public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {
private static final Map<Series, String> SERIES_VIEWS; // 存放不同错误码对应的视图 // 添加默认的视图
static {
Map<Series, String> views = new EnumMap<>(Series.class);
views.put(Series.CLIENT_ERROR, "4xx");
views.put(Series.SERVER_ERROR, "5xx");
SERIES_VIEWS = Collections.unmodifiableMap(views);
}
... // 开始解析错误视图
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
// status.value() 得到的是错误码
// 寻找错误码指定的页面,如404就找名为404的页面
ModelAndView modelAndView = resolve(String.valueOf(status.value()), model); // 若找不到错误码指定的页面,则400,401,403,404...都会去找4xx的页面
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
}
// 若modelAndView还是null,那么就返回上面的那个图片了
return modelAndView;
} private ModelAndView resolve(String viewName, Map<String, Object> model) {
String errorViewName = "error/" + viewName;
//首先去动态资源中查看是否存在对应的页面
TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,
this.applicationContext);
if (provider != null) {
return new ModelAndView(errorViewName, model);
}
//若动态资源中找不到则到静态资源中寻找对应的页面
return resolveResource(errorViewName, model);
} //获取静态页面资源
private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
// 遍历静态资源,查找是否有对应的页面
for (String location : this.resourceProperties.getStaticLocations()) {
try {
Resource resource = this.applicationContext.getResource(location);
resource = resource.createRelative(viewName + ".html");
if (resource.exists()) {
return new ModelAndView(new HtmlResourceView(resource), model);
}
}
catch (Exception ex) {
}
}
return null;
}
...
}

阅读源码总结

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

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

实现

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

timestamp

status

error

message

...

thymeleaf下页面使用如下:

<table>
<tr>
<td th:text="${status}"></td>
</tr>
<tr>
<td th:text="${message}"></td>
</tr>
</table>

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

@Component
public class CustomErrorAttribute extends DefaultErrorAttributes {
// 扩展
}

CORS跨域

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

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

注册拦截器

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

public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return false;
}
public void postHandle ...
public void afterCompletion ...
}

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

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

@Configuration
public class WebMvcConfig implements WebMvcConfigurer { @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor())
.addPathPatterns("/**"); //拦截所有路径
} @Bean
MyInterceptor myInterceptor() {
return new MyInterceptor();
}
}

整合Servlet

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

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

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

@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注解,如:

@WebListener
public class MyRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {System.out.println("requestDestroyed");}
@Override
public void requestInitialized(ServletRequestEvent sre) {System.out.println("requestInitialized");}
} @WebFilter(urlPatterns = "/*") //对所有目录进行拦截
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter");
chain.doFilter(request,response);
}
}

上述的监听器和拦截器一定要在@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. SpringBootSecurity学习(22)前后端分离版之OAuth2.0自定义授权码

    使用JDBC维护授权码 前面的代码中,测试流程第一步都是获取授权码,然后再携带授权码去申请令牌,授权码示例如下: 产生的授权码默认是 6 位的,产生以后并没有做任何管理,可以说是一个临时性的授权码,o ...

  2. mobaxterm使用手册

    Mobaxterm V14使用手册 文章出处    https://blog.51cto.com/937761/2372598 简介 MobaXterm 一款Windows系统下全功能终端软件.以下将 ...

  3. javascript生成规定范围的随机整数

    Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返回值是一个伪随机选择的数,在该范围内(近似)均匀分布. 我 ...

  4. Java描述设计模式(15):责任链模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景描述 1.请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批 当 3<day<= ...

  5. [Luogu3868] [TJOI2009]猜数字

    题目描述 现有两组数字,每组k个,第一组中的数字分别为:a1,a2,...,ak表示,第二组中的数字分别用b1,b2,...,bk表示.其中第二组中的数字是两两互素的.求最小的非负整数n,满足对于任意 ...

  6. MySQL的远程连接问题 错误1130

    解决办法:将localhost改成%. 在远程主机上--> 登陆mysql服务执行如下代码: mysql -u root -p mysql>use mysql; mysql>upda ...

  7. 剑指Offer(十九)——顺时针打印矩阵

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 例如,如果输入如下4 X 4矩阵: 1   2    3     4 5   6    7     8 9   10  11  ...

  8. oracle中创建用户、角色、权限简单使用

    Oracle关于用户.权限.角色简单使用 创建数据库用户(在system用户下)create user 用户名 identified by 密码; 授权grant 权限名 to 用户名; 查看当前用户 ...

  9. .NET中国开发者峰会11.9 下午分会场1 内容解析

    China .NET Conf 2019中国 .NET 开发者峰会即将在上海召开,这次大会是一届完全由社区组织举办的中国.NET 开发者盛会,我们筹备大会之初就定下了大会的主题是“开源.共享.创新”. ...

  10. 使用animate.css

    今天有个一前辈来看了一下我的小程序啊,说写的还行就是可以不用只按照ui给的图写界面,自己可以添加一些动态的炫酷效果,不用不知道一用吓一跳啊,用之前觉得好好一个界面为什么要搞那些花里胡哨的东西,单纯一点 ...