拦截器
在SSM框架中我们使用拦截器的方法如下
- 创建一个类实现HandlerInterceptor 接口
- 在SpringMVC.xml文件中配置拦截器以及拦截路径等信息
在SpringBoot中没有配置文件,使用配置类代替了配置文件,方法如下
-
创建一个类实现HandlerInterceptor 接口
@Slf4j public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestURI = request.getRequestURI(); log.info("拦截到的请求路径是{}",requestURI); //获取登录信息 HttpSession session = request.getSession(); if(session.getAttribute("user") == null){ //拦截 request.setAttribute("msg","请先登录"); request.getRequestDispatcher("/login").forward(request,response); return false; } //放行 return true; } @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); } }
-
创建一个配置类,实现WebMvcConfigurer接口,重写addInterceptors方法
@Configuration public class AdminWebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { LoginInterceptor loginInterceptor = new LoginInterceptor(); registry.addInterceptor(loginInterceptor).addPathPatterns("/**") .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); } }
文件上传
文件上传在SpringBoot的帮助下,只需要一行语句即可实现,主要来讲解获取请求的工作。
文件上传分为多文件与单文件上传,无论哪种,我们都需要将表单设置为POST请求并且为他添加上enctype=“multipart/form-data”
<form role="form" method="post" action="/upload" 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="userName" name="userName" class="form-control" id="exampleInputPassword1" placeholder="UserName">
</div>
<div class="form-group">
<label for="exampleInputFile">头像</label>
<input type="file" name="headImg" id="exampleInputFile">
<p class="help-block">Example block-level help text here.</p>
</div>
<div class="form-group">
<label for="exampleInputFile">照片墙</label>
<input type="file" name="photos" multiple="multiple">
<p class="help-block">Example block-level help text here.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-primary">上传</button>
</form>
创建一个controller用于处理请求,客户端上传的文件信息我们可以用MultipartFile类接收,他会自动封装上传的文件,并且只需要调用MultipartFile.transferTo()即可实现文件上传
@PostMapping("/upload")
public String upload(@RequestParam("email") String email,
@RequestParam("userName") String userName,
@RequestPart MultipartFile headImg,
@RequestPart MultipartFile[] photos) throws IOException {
log.info("表单信息:邮箱为{},用户名为{},头像大小为{},照片数量为{}",
email,userName,headImg.getSize(),photos.length);
if (!headImg.isEmpty()){
String originalFilename = headImg.getOriginalFilename();
headImg.transferTo(new File("D:\\javatest\\" + originalFilename));
}
if (photos.length > 0){
for(MultipartFile photo : photos){
if(!photo.isEmpty()){
String name = photo.getOriginalFilename();
photo.transferTo(new File("D:\\javatest\\photos\\" + name));
}
}
}
return "index";
}
优化:文件上传肯定有文件的大小,而SpringBoot为我们提供的文件大小为(单个文件最大1MB,所有文件最大10MB),我们需要对他进行修改,只需要在配置文件中修改即可
spring:
servlet:
multipart:
#单个文件最大的大小
max-file-size: 10MB
#所有文件最大的大小
max-request-size: 100MB
异常处理
SpringBoot关于异常处理,做的简直不要太简单,对于普通的异常处理,看一下官方文档是怎么说的
对于机器客户端,服务器抛出异常后会将异常封装为JSON格式的数据显示;对于浏览器端,服务器抛出异常会创建一个白皮页将异常信息显示在上面
实际开发过程中,即使显示白皮页也对用户非常的不友好,我们需要使用自己编写的报错页面
对于404和5xx(例如500,接下来就称为500)的请求,我们可以在静态资源的templates下创建一个error文件夹,如404异常,我们将自己编写的页面命名为404.html放在error包下,如果服务器出现404异常,就会显示该页面。5xx就是显示异常为5开头的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2baM1PVT-1636965819295)(C:\Users\YellowStar\AppData\Roaming\Typora\typora-user-images\image-20211115155651292.png)]
我们也可以在页面上显示错误信息
<section class="error-wrapper text-center">
<h1><img alt="" src="images/500-error.png"></h1>
<h2>OOOPS!!!</h2>
<!--显示错误原因-->
<h3 th:text="${message}">Something went wrong.</h3>
<!--显示错误堆栈信息-->
<p class="nrml-txt" th:text="${trace}">Why not try refreshing you page? Or you can <a href="#">contact our support</a> if the problem persists.</p>
<a class="back-btn" th:href="@{/index.html}"> Back To Home</a>
</section>
Web原生组件注入(Servlet、Filter、Listener)
原生组件注入有两种方式,先来介绍第一种,也是推荐使用这种方式。
第一步:在主程序上添加扫描Servlet注解
@ServletComponentScan("com.yellowstar.boot")
@SpringBootApplication
public class Boot03WebApplication {
public static void main(String[] args) {
SpringApplication.run(Boot03WebApplication.class, args);
}
}
第二步:创建三大组件,并为他们分别添加@WebServlet(),@WebFilter(),@WebListener注解
注意:原生Servlet请求是可以跳过SpringBoot的拦截器的
@Slf4j
@WebServlet("/my") //参数为请求地址
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("66666");
log.info("原生Servlet请求");
}
}
@Slf4j
@WebFilter(urlPatterns = {"/css/*","/images/*"}) //拦截的请求地址
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("过滤器初始化");
}
@Override
public void destroy() {
log.info("过滤器销毁");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("过滤器正在工作");
filterChain.doFilter(servletRequest,servletResponse);
}
}
@Slf4j
@WebListener
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("MyListener监听到项目初始化完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("MyListener监听到项目销毁");
}
}
第二种方法,使用RegistrationBean
三大组件还是要创建,只不过使用配置类的形式将三大组件注入到容器中
@WebServlet(),@WebFilter(),@WebListener注解包括主程序上的@ServletComponentScan注解都可以不用谢
@Configuration
public class MyRegistConfig{
@Bean
public ServletRegistrationBean myServlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/my","/my2");
}
@Bean
public FilterRegistrationBean myFilter(){
MyFilter myFilter = new MyFilter();
//拦截地址和MyServlet方法一致
return new FilterRegistrationBean(myFilter,myServlet());
}
@Bean
public ServletListenerRegistrationBean myListener(){
MyListener myListener = new MyListener();
return new ServletListenerRegistrationBean(myListener);
}
}