SpringBoot的Web开发
1、拦截器-登录检查与资源放行
- 编写一个拦截器实现
HandlerInterceptor
接口
- 拦截器注册到容器中(实现
WebMvcConfigurer
的addInterceptors()
)
- 指定拦截规则(注意,如果是拦截所有,静态资源也会被拦截)
编写一个实现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","请先登录");
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/**"); }
|
拦截器原理
- 根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有拦截器】
- 先来顺序执行所有拦截器的preHandle方法
- 如果当前拦截器preHandler返回为true,则执行下一个拦截器的preHandle
- 如果当前拦截器preHandler返回为false,则直接倒序执行所有已经执行了的拦截器的afterCompletion
- 如果任何一个拦截器执行false,直接跳出不执行目标方法
- 所有拦截器都返回true,执行目标方法
- 倒序执行所有拦截器的postHandle方法
- 前面的步骤有任何异常都会直接触发afterCompletion
- 页面成功渲染完成以后,也会倒序触发afterCompletion
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"; }
@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()){ 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") 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/*"}) 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();
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定制化组件的几种方式(小结)
定制化的常见方式
1 2 3
| @Configuration public class AdminWebConfig implements WebMvcConfigurer{ }
|
原理分析套路:
场景starter - xxxxAutoConfiguration
- 导入xxx组件 - 绑定xxxProperties
- 绑定配置文件项。