SpringBoot Web篇笔记(一)
摘要
文章是根据江南一点雨(松哥)的视频进行总结
全局异常处理
通常情况下,我们都需要对自己定义的异常进行相应的处理。捕获指定的异常方式如下:
@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篇笔记(一)的更多相关文章
- SpringBoot Web篇(二)
摘要 继上一篇 SpringBoot Web篇(一) 文件上传 当我们服务器需要接收用户上传的文件时,就需要使用MultipartFile作为参数接收文件.如下: @PostMapping(" ...
- SpringBoot Web学习笔记
一.资源的访问: 情形一.所有的 /webjars/** 都会去 classpath:/META_INFO/resource/webjars/ 下找资源: webjars:以jar包的方式引入静态 ...
- [SpringBoot]Web综合开发-笔记
Web开发 Json接口开发 @RestController 给类添加 @RestController 即可,默认类中的方法都会以 json 的格式返回. 自定义filter filter作用: 用于 ...
- SpringBoot系列教程web篇之过滤器Filter使用指南扩展篇
前面一篇博文介绍了在 SpringBoot 中使用 Filter 的两种使用方式,这里介绍另外一种直接将 Filter 当做 Spring 的 Bean 来使用的方式,并且在这种使用方式下,Filte ...
- SpringBoot系列教程Web篇之开启GZIP数据压缩
本篇可以归纳在性能调优篇,虽然内容非常简单,但效果可能出乎预料的好: 分享一个真实案例,我们的服务部署在海外,国内访问时访问服务时,响应有点夸张:某些返回数据比较大的接口,耗时在 600ms+上,然而 ...
- SpringBoot系列教程web篇Listener四种注册姿势
java web三要素Filter, Servlet前面分别进行了介绍,接下来我们看一下Listener的相关知识点,本篇博文主要内容为SpringBoot环境下,如何自定义Listener并注册到s ...
- SpringBoot系列教程web篇Servlet 注册的四种姿势
原文: 191122-SpringBoot系列教程web篇Servlet 注册的四种姿势 前面介绍了 java web 三要素中 filter 的使用指南与常见的易错事项,接下来我们来看一下 Serv ...
- SpringBoot系列教程web篇之过滤器Filter使用指南
web三大组件之一Filter,可以说是很多小伙伴学习java web时最早接触的知识点了,然而学得早不代表就用得多.基本上,如果不是让你从0到1写一个web应用(或者说即便从0到1写一个web应用) ...
- SpringBoot系列教程web篇之自定义异常处理HandlerExceptionResolver
关于Web应用的全局异常处理,上一篇介绍了ControllerAdvice结合@ExceptionHandler的方式来实现web应用的全局异常管理: 本篇博文则带来另外一种并不常见的使用方式,通过实 ...
随机推荐
- UWP开发入门(二十四)—— Win10风格的打印对话框
虽然经常看到阿迪王发“看那个开发UWP的又上吊了”的图……还是忍不住重启一下这个系列.最近有用到UWP的print API,特地来写一篇给某软的这个伟大构想续一秒. 之前的打印对话框差不多长成这样: ...
- 并发新构件之DelayQueue:延时队列
DelayQueue:延时队列,首先是一个队列,所以可以持有对象,但是仅限于实现了Delayed接口的对象.重写getDelay()和compareTo()(因为要比较)方法: 通俗来讲:延时队列的就 ...
- Redis开发与运维:数据迁移(下)
上一篇,有朋友留言redis-port,借此机会我尝试使用一下redis-port这个同步工具 redis-port 已编译版 https://github.com/CodisLabs/redis-p ...
- 就个人银行账户管理程序谈谈C++和Java的异同
4_9 同: Java和C++都是面向对象的语言.都有数据成员,方法,访问权限的概念. 异: 访问权限上,非private时Java的默认访问权限是包.而C++的默认访问权限是private.Java ...
- CSS中重要的BFC
CSS中有个重要的概念BFC,搞懂BFC可以让我们理解CSS中某些原本看似诡异的地方. 简介 在解释BFC之前,先说一下文档流.我们常说的文档流其实分为定位流.浮动流.普通流三种.而普通流其实就是指B ...
- SpringBoot 配置提示功能
目的 配置自动提示的辅助功能可以让配置写起来更快,准确率大大提高. springboot jar 包含提供所有支持的配置属性细节的元数据文件.文件的目的是为了让 IDE 开发者在用户使用 applic ...
- Mysql数据库(四)表记录的更新操作
一.插入表记录 1.使用INSERT...VALUES语句插入新纪录 (1)插入完整数据 mysql> desc tb_manager; +-------+------------------+ ...
- Vuforia添加虚拟按键
AR虚拟按键为真实识别图上的按键,通过按键可以实现真实与虚拟之间的按键交流 (一)添加按键 点击target,打开advance,添加虚拟按键,即可在此target下添加虚拟按键 注:虚拟按键无法旋转 ...
- django-URL重定向(八)
HttpResponseRedirect()不常用 redirect(to,permanent=False,*args,**kwargs) to:指重定向的位置,可以是视图,也可以是url地址,也可以 ...
- 一:XMind