发布于 

SpringBoot的Web开发

1、拦截器-登录检查与资源放行

  1. 编写一个拦截器实现HandlerInterceptor接口
  2. 拦截器注册到容器中(实现WebMvcConfigureraddInterceptors()
  3. 指定拦截规则(注意,如果是拦截所有,静态资源也会被拦截)

编写一个实现HandlerInterceptor接口的拦截器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

/**
* 目标方法执行之前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String requestURI = request.getRequestURI();
log.info("preHandle拦截的请求路径是{}",requestURI);

//登录检查逻辑
HttpSession session = request.getSession();

Object loginUser = session.getAttribute("loginUser");

if(loginUser != null){
//放行
return true;
}

//拦截住。未登录。跳转到登录页
request.setAttribute("msg","请先登录");
// re.sendRedirect("/");
request.getRequestDispatcher("/").forward(request,response);
return false;
}

/**
* 目标方法执行完成以后
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle执行{}",modelAndView);
}

/**
* 页面渲染以后
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion执行异常{}",ex);
}
}

拦截器注册到容器中 && 指定拦截规则:

1
2
3
4
5
6
7
8
9
@Configuration
public class AdminWebConfig implements WebMvcConfigurer{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())//拦截器注册到容器中
.addPathPatterns("/**") //所有请求都被拦截包括静态资源
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**",
"/js/**","/aa/**"); //放行的请求
}

拦截器原理

  1. 根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有拦截器】
  2. 先来顺序执行所有拦截器的preHandle方法
    1. 如果当前拦截器preHandler返回为true,则执行下一个拦截器的preHandle
    2. 如果当前拦截器preHandler返回为false,则直接倒序执行所有已经执行了的拦截器的afterCompletion
  3. 如果任何一个拦截器执行false,直接跳出不执行目标方法
  4. 所有拦截器都返回true,执行目标方法
  5. 倒序执行所有拦截器的postHandle方法
  6. 前面的步骤有任何异常都会直接触发afterCompletion
  7. 页面成功渲染完成以后,也会倒序触发afterCompletion
image-20220324111931368
image-20220324111931368

2、文件上传-单文件与多文件上传的使用

前端代码:/static/form/form_layouts.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="exampleInputEmail1">邮箱</label>
<input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>

<div class="form-group">
<label for="exampleInputPassword1">名字</label>
<input type="text" name="username" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>

<div class="form-group">
<label for="exampleInputFile">头像</label>
<input type="file" name="headerImg" id="exampleInputFile">
</div>

<div class="form-group">
<label for="exampleInputFile">生活照</label>
<input type="file" name="photos" multiple>
</div>

<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>

控制层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* 文件上传测试
*/
@Slf4j
@Controller
public class FormTestController {

@GetMapping("/form_layouts")
public String form_layouts(){

return "form/form_layouts";
}

/**
* MultipartFile自动封装上传来的文件
* @param email
* @param username
* @param headerImg
* @param photos
* @return
*/
@RequestMapping("/upload")
public String upload(@RequestParam("email") String email,
@RequestParam("username") String username,
@RequestPart("headerImg") MultipartFile headerImg,
@RequestPart MultipartFile[] photos) throws IOException {

log.info("上传信息:email={},username={},headerImg={},photos={}",
email,username,headerImg.getSize(),photos.length);

if(!headerImg.isEmpty()){
//保存到文件服务器,OSS服务器
String originalFilename = headerImg.getOriginalFilename();
headerImg.transferTo(new File("E:\\StudyFiles\\SpringBoot\\FileTest\\headerImg\\"+originalFilename));
}

if(photos.length > 0){
for (MultipartFile photo : photos) {
if(!photo.isEmpty()){
String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("E:\\StudyFiles\\SpringBoot\\FileTest\\photos\\"+originalFilename));
}
}
}

return "main";
}
}

文件大小相关配置项:

1
2
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB

3、错误处理-SpringBoot默认错误处理机制

默认规则:

  • 默认情况下,Spring Boot提供/error处理所有错误的映射

  • 机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据

  • 要对其进行自定义,添加View解析为error

  • 要完全替换默认行为,可以实现 ErrorController并注册该类型的Bean定义,或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。

  • /templates/error/下的4xx,5xx页面会被自动解析

4、Web原生组件注入-原生注解与Spring方式注入

使用原生的注解

1
2
3
4
5
6
7
8
@WebServlet(urlPatterns = "/my")	//直接响应,没有Spring的拦截器
public class MyServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("66666");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Slf4j
@WebFilter(urlPatterns={"/css/*","/images/*"}) //my
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("MyFilter初始化完成");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("MyFilter工作");
chain.doFilter(request,response);
}

@Override
public void destroy() {
log.info("MyFilter销毁");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Slf4j
@WebListener
public class MyServletContextListener implements ServletContextListener {


@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("MySwervletContextListener监听到项目初始化完成");
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("MySwervletContextListener监听到项目销毁");
}
}

最后还要在主启动类添加注解@ServletComponentScan

1
2
3
4
5
6
7
8
@ServletComponentScan(basePackages = "com.lun")//
@SpringBootApplication(exclude = RedisAutoConfiguration.class)
public class Boot05WebAdminApplication {

public static void main(String[] args) {
SpringApplication.run(Boot05WebAdminApplication.class, args);
}
}

Spring方式注入

ServletRegistrationBean,FilterRegistrationBean,andServletListenerRegistrationBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Configuration(proxyBeanMethods = true)
public class MyRegistConfig {

@Bean
public ServletRegistrationBean myServlet(){
MyServlet myServlet = new MyServlet();

return new ServletRegistrationBean(myServlet,"/my","/my02");
}


@Bean
public FilterRegistrationBean myFilter(){

MyFilter myFilter = new MyFilter();
// return new FilterRegistrationBean(myFilter,myServlet());
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
return filterRegistrationBean;
}

@Bean
public ServletListenerRegistrationBean myListener(){
MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
return new ServletListenerRegistrationBean(mySwervletContextListener);
}
}

5、定制化原理-SpringBoot定制化组件的几种方式(小结)

定制化的常见方式

  • 修改配置文件

  • xxxxxCustomizer

  • 编写自定义的配置类 xxxConfiguration + @Bean替换、增加容器中默认组件,视图解析器

  • Web应用 编写一个配置类实现 WebMvcConfigurer 即可定制化web功能 + @Bean给容器中再扩展一些组件

1
2
3
@Configuration
public class AdminWebConfig implements WebMvcConfigurer{
}
  • @EnableWebMvc + WebMvcConfigurer@Bean 可以全面接管SpringMVC,所有规则全部自己重新配置; 实现定制和扩展功能(高级功能,初学者退避三舍)。

    • 原理:

      ​ 1. WebMvcAutoConfiguration默认的SpringMVC的自动配置功能类,如静态资源、欢迎页等。

      1. 一旦使用 @EnableWebMvc ,会@Import(DelegatingWebMvcConfiguration.class)
      2. DelegatingWebMvcConfiguration的作用,只保证SpringMVC最基本的使用
        1. 把所有系统中的WebMvcConfigurer拿过来,所有功能的定制都是这些WebMvcConfigurer合起来一起生效。
        2. 自动配置了一些非常底层的组件,如RequestMappingHandlerMapping,这些组件依赖的组件都是从容器中获取如。
        3. public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport。
        4. WebMvcAutoConfiguration里面的配置要能生效必须 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)。
        5. @EnableWebMvc 导致了WebMvcAutoConfiguration 没有生效。

原理分析套路

场景starter - xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties - 绑定配置文件项。


本站由 Cccccpg 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。