Spring Boot学习笔记(十四)


在这里插入图片描述

Spring MVC的整合支持

  • Spring MVC自动配置介绍
    在Spring Boot项目中,一旦引入了Web依赖启动器spring-boot-starter-web,那么Spring Boot整合Spring MVC框架默认实现的一些XxxAutoConfiguration自动配置类就会自动生效,几乎可以在无任何额外配置的情况下进行Web开发。

Spring Boot整合Spring MVC的自动化配置功能特性

  1. 内置了两个视图解析器:ContentNegotitatingViewResolver和BeanNameViewResolver;
  2. 支持静态资源以及WebJars;
  3. 自动注册了转换器和格式化器;
  4. 支持Http消息转换器;
  5. 自动注册了消息代码解析器;
  6. 支持静态项目首页index.html;
  7. 支持定制应用图标favicon.ico;
  8. 自动初始化Web数据绑定器ConfigurableWebBindingInitializer。
  • 功能拓展的实现
    搭建步骤:
  1. 项目基础环境搭建
    使用Spring Initializr方式创建Spring Boot项目,并在Dependencies依赖选择中选择Web依赖启动器和Thymeleaf依赖启动器
    在这里插入图片描述
    项目初始化结构图如下:
    在这里插入图片描述
  2. 功能拓展实现
  • 注册视图管理器,创建一个实现WebMvcConfigurer接口的配置类MyMVCconfig,用于对MVC框架功能扩展:
@Configuration
public class MyMVCconfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 请求toLoginPage映射路径或者login.html页面都会自动映射到login.html页面
        registry.addViewController("/toLoginPage").setViewName("login");
        registry.addViewController("/login.html").setViewName("login");
    }
}

MyMVCconfig实现了接口WebMvcConfigurer的addViewControllers(ViewControllerRegistry registry)方法。

注:使用WebMvcConfigurer接口中的addViewControllers(ViewControllerRegistry registry)方法定制视图控制,只适合较为简单的无参数视图Get方式的请求跳转,对于有参数或需要业务处理的跳转需求,最好还是采用传统方式处理请求

  • 注册自定义拦截器MyInterceptor,实现HandlerInterceptor接口,在该类中编写如下方法:
@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        // 用户请求/admin开头路径时,判断用户是否登录
        String uri = request.getRequestURI();
        Object loginUser = request.getSession().getAttribute("loginUser");
        if (uri.startsWith("/admin") && null == loginUser) {
            response.sendRedirect("/toLoginPage");
            return false;
        }
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        request.setAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse
            response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

自定义拦截器类MyInterceptor实现了HandlerInterceptor接口。在preHandle()方法中,如果用户请求以"/admin"开头,则判断用户是否登录,如果没有登录,则重定向到"/toLoginPage"请求对应的登录页面。在postHandle()方法中,使用request对象向前端页面传递表示年份的currentYear数据。
在自定义配置类MyMVCconfig中,重写addInterceptors()方法注册自定义的拦截器:

@Configuration
public class MyMVCconfig implements WebMvcConfigurer {
    @Autowired
    private MyInterceptor myInterceptor;
    // 添加拦截器管理
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login.html");
    }

}

注:Spring Boot在整合MVC过程中提供了许多默认自动化配置和特性,如果想要绝对的自定义管理,可以编写一个@Configuration注解配置类,同时添加@EnableWebMvc注解,关闭Spring Boot提供的所有关于MVC功能的默认配置。

Spring Boot整合Servlet三大组件

在Spring Boot中,使用组件注册方式整合内嵌Servlet容器的Servlet、Filter、Listener三大组件时,只需将这些自定义组件通过ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean类注册到容器中即可,这些类相当于将组件配置在web.xml中。

  • 使用组件注册方式整合Servlet

搭建步骤:

  1. 使用组件注册方式整合Servlet

创建自定义Servlet类。

@Component
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().write("hello MyServlet");
    }
}

创建Servlet组件配置类。

@Configuration
public class ServletConfig {
     //注册Servlet组件
    @Bean
    public ServletRegistrationBean getServlet(MyServlet myServlet){
        ServletRegistrationBean registrationBean =
                new ServletRegistrationBean(myServlet,"/myServlet");
        return registrationBean;
    }
}
  1. 使用组件注册方式整合Filter

创建自定义Filter类。

@Component
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        System.out.println("hello MyFilter");
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {

    }
}

MyFilter类实现了Filter接口,并重写了init()、doFilter()和destory()方法,在doFilter()方法中向控制台打印了"hello MyFilter"字符串。

向Servlet组件配置类注册自定义Filter类。

    @Bean
    public FilterRegistrationBean getFilter(MyFilter filter){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setUrlPatterns(Arrays.asList("/toLoginPage","/myFilter"));
        return registrationBean;
    }

在getFilter(MyFilter filter)方法中,使用setUrlPatterns(Arrays.asList("/toLoginPage","/myFilter"))方法定义了过滤的请求路径为"/toLoginPage"和"/myFilter",同时使用@Bean注解将当前组装好的FilterRegistrationBean作为Bean组件返回。

  1. 使用组件注册方式整合Listener

创建自定义Listener类。

@Component
public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("contextInitialized ...");
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("contextDestroyed ...");
    }
}

MyListener类实现了ServletContextListener接口,并重写了contextInitialized()和contextDestroyed()方法。
注:Servlet容器提供了很多Listener接口,在自定义Listener类时根据自身需求选择实现对应接口即可。

向Servlet组件配置类注册自定义Listener类。

    @Bean
    public ServletListenerRegistrationBean getServletListener(MyListener myListener){
        ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean(MyListener);
        
        return registrationBean;
    }
  • 路径扫描整合Servlet三大组件
    在MyServlet、MyFilter、MyListener组件中分别使用@WebServlet、@WebFilter和@WebListener注解声明并配置相关属性。

MyServlet.java

@WebServlet("/annotationServlet")
//@Component
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().write("hello MyServlet");
    }
}

MyFilter.java

@WebFilter(value = {"/antionLogin","/antionMyFilter"})
//@Component
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        System.out.println("hello MyFilter");
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {

    }
}

MyListener.java

@WebListener
//@Component
public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("contextInitialized ...");
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("contextDestroyed ...");
    }
}

在对应组件上分别使用@WebServlet("/annotationServlet")注解来映射"/annotationServlet"请求的Servlet类,使用@WebFilter(value = {"/antionLogin","/antionMyFilter"})注解来映射"/antionLogin"和"/antionMyFilter"请求的Filter类,使用@WebListener注解来标注Listener类。
在主程序启动类上添加@ServletComponentScan注解,开启基于注解方式的Servlet组件扫描支持。

@ServletComponentScan  // 开启基于注解方式的Servlet组件扫描支持
@SpringBootApplication
public class Chapter05Application extends SpringBootServletInitializer {
    // 3、程序主类继承SpringBootServletInitializer,并重写configure()方法
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(Chapter05Application.class);
    }

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

}

文件上传

浏览器通过表单形式将文件以流的形式传递给服务器,服务器再对上传的数据解析处理。
整合步骤:

  1. 编写文件上传的表单页面
    在项目根路径下的templates模板引擎文件夹下创建一个用来上传文件的upload.html模板页面。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>动态添加文件上传列表</title>
    <link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet">
    <script th:src="@{/login/js/jquery.min.js}"></script>
</head>
<body>
<div th:if="${uploadStatus}" style="color: red" th:text="${uploadStatus}">上传成功</div>
<form th:action="@{/uploadFile}" method="post" enctype="multipart/form-data">
    上传文件:&nbsp;&nbsp;<input type="button" value="添加文件" onclick="add()"/>
    <div id="file" style="margin-top: 10px;" th:value="文件上传区域">  </div>
    <input id="submit" type="submit" value="上传"
           style="display: none;margin-top: 10px;"/>
</form>
<script type="text/javascript">
    // 动态添加上传按钮
    function add(){
        var innerdiv = "<div>";
        innerdiv += "<input type='file' name='fileUpload' required='required'>" +
            "<input type='button' value='删除' οnclick='remove(this)'>";
        innerdiv +="</div>";
        $("#file").append(innerdiv);
        // 打开上传按钮
        $("#submit").css("display","block");
    }
    // 删除当前行<div>
    function remove(obj) {
        $(obj).parent().remove();
        if($("#file div").length ==0){
            $("#submit").css("display","none");
        }
    }
</script>
</body>
</html>

导入了一个css文件和一个js文件。
表单上传三要素:

  • 文件上传项:id=“file” style=“margin-top: 10px;” th:value=“文件上传区域”
  • 提交方式为post:method=“post”
  • enctype属性要修改成multipart/form-data,只有修改成multipart/form-data才支持多部分上传:enctype=“multipart/form-data”
  1. 在全局配置文件中添加文件上传的相关配置
# 单个上传文件大小限制(默认1MB)
spring.servlet.multipart.max-file-size=10MB
# 总上传文件大小限制(默认10MB)
spring.servlet.multipart.max-request-size=50MB

  1. 进行文件上传处理实现文件上传功能
    在controller包下创建一个管理文件上传下载的控制类FileController,用于实现文件上传功能。
@Controller
public class FileController {
    // 向文件上传页面跳转
    @GetMapping("/toUpload")
    public String toUpload(){
        return "upload";
    }
    // 文件上传管理
    @PostMapping("/uploadFile")
    public String uploadFile(MultipartFile[] fileUpload, Model model) {
        // 默认文件上传成功,并返回状态信息
        model.addAttribute("uploadStatus", "上传成功!");
        for (MultipartFile file : fileUpload) {
            // 获取文件名以及后缀名
            String fileName = file.getOriginalFilename();
            // 重新生成文件名(根据具体情况生成对应文件名)
            fileName = UUID.randomUUID()+"_"+fileName;
            // 指定上传文件本地存储目录,不存在需要提前创建
            String dirPath = "F:/file/";
            File filePath = new File(dirPath);
            if(!filePath.exists()){
                filePath.mkdirs();
            }
            try {
                file.transferTo(new File(dirPath+fileName));
            } catch (Exception e) {
                e.printStackTrace();
                // 上传失败,返回失败信息
                model.addAttribute("uploadStatus","上传失败: "+e.getMessage());
            }
        }
        // 携带上传状态信息回调到文件上传页面
        return "upload";
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值