• Spring Boot 之 web 开发


    使用 JSP

    • SpringBoot 中不推荐使用 JSP

      • 使用模板技术代替 JSP
    • 使用 JSP 需要配置后才能使用

      1. 添加处理 jsp 的依赖

        <dependency>
            <groupId>org.apache.tomcat.embedgroupId>
            <artifactId>tomcat-embed-jasperartifactId>
        dependency>
        
        • 1
        • 2
        • 3
        • 4
      2. 若要使用 servlet、jsp 、jstl 等的功能也需要添加相关依赖

        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
        dependency>
        <dependency>
            <groupId>javax.servlet.jspgroupId>
            <artifactId>javax.servlet.jsp-apiartifactId>
            <version>2.3.1version>
        dependency>
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>jstlartifactId>
        dependency>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
      3. 创建存放 jsp 的目录,一般为 webapp,设为项目中 jsp 资源目录

        • 创建 index.jsp
      4. 在 pom.xml 文件指定 jsp 文件编译后存放的目录

        • webapp 目录下所有文件编译到 target 目录下 META-INF/resources 目录

          • 包括子目录文件
        • <resources>
              <resource>
                  
                  <directory>src/mian/webappdirectory>
                  
                  <targetPath>META-INF/resourcestargetPath>
                  
                  <includes>
                      <include>**/*.*include>
                  includes>
              resource>
          resources>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
      5. 创建 Controller 访问 jsp

        • 方法参数 HttpRequestModel 对象来返回数据

          @RequestMapping
          public String doOther(Model model){
              //将数据放到 request 作用域;等价于 request.setAttribute()
              model.addAttribute("data", "废物");
              //返回 index.jsp 页面,页面的逻辑名,由视图解析器包装为完整视图
              return "index";
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
      6. application.properties 文件中配置视图解析器

        • # 配置视图解析器
          spring.mvc.view.prefix=/
          spring.mvc.view.suffix=.jsp
          
          • 1
          • 2
          • 3

    Web开发

    静态资源

    1. 通过 Maven 依赖导入 jar 包

      • 自动加载 jar 包中的 /META-INF/resources/webjars 路径找到静态资源
      • WebJars 是将 web 前端资源(如:jQuery、Bootstrap)打成 jar 包文件
        • 借助版本管理工具( Maven、gradle 等)进行版本管理
        • 保证这些 Web 资源版本的唯一性。避免了文件混乱、版本不一致等问题
    2. 加载 staticPathPattern = "/**" 路径

      • 默认到以下四个资源目录中查找静态资源:按优先级顺序排列

        1. "classpath:/META-INF/resources/"

        2. "classpath:/resources/"

          • 一般存放资源文件
        3. "classpath:/static/":默认生成目录

          • 一般存放静态资源
        4. "classpath:/public/"

          • 一般存放公共共享资源
      • 自定义加载静态资源文件的路径

        • 加载系统资源目录后查找自定义资源目录

          • spring.mvc.static-path-pattern:阐述 HTTP 请求路径

            • # 只有静态资源的访问路径为 /resources/** 时,才会处理请求
              spring.mvc.static-path-pattern=/resources/**,
              
              • 1
              • 2
          • spring.resources.static-locations:静态资源的存放位置

            • 添加静态资源文件路径:列表性的配置
              • 查找文件时会依赖于配置的先后顺序依次进行
          spring:
            # 资源请求路径
            mvc:
              static-path-pattern: \**
            # 资源访问地址
            resources:
              static-locations: [classpath: /META-INF/resources/, classpath: /resources/, classpath: /static/, classpath: /public/, file: ${web:vue-path}]
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

    MVC 扩展

    实现
    • 在 SpringBoot 中对 MVC 有默认的支持实现

      • 可以自定义实现 mvc 接管 框架的定义
    • 创建类实现不同的 mvc 组件接口以自定义拓展组件功能

      • 在类中重写方法自定义组件功能
    • 创建 MVC 配置类实现 WebMvcConfigurer 接口,此类就是 mvc 的配置类

      • 不能添加 @EnableWebMvc 注解
        • 该注解引入 @Import({DelegatingWebMvcConfiguration.class})
          • 这个类继承了 WebMvcConfigurationSupport
        • 添加此注解会使 WebAutoMvcConfigurer 自动装配失效
          • WebMvcAutoConfiguration 自动配置类生效需要所有配置类中不存在 WebMvcConfigurationSupport.class
      • 将自定义的组件类注册到容器中
    拦截器
    • 拦截器是 SpringMVC 中的一种对象
      • 能拦截对 controller 的请求
    • 拦截器框架中有系统的拦截器
      • 可以自定义拦截器
      • 实现对请求预先处理
    SpringMVC

    自定义拦截器使用

    1. 创建类实现 HandlerInterceptor 接口

      • 接口中有三个方法
        • 处理方法前执行
        • 处理方法后执行
        • 请求完成后执行
      • 根据需求选择方法重写使用
    2. 在 SpringMVC 配置文件中声明拦截器

      <mvc:interceptors>
      	<mvc:interceptor>
          	
              <bean class="拦截器全限定名">
          mvc:interceptor>
      mvc:interceptors>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    SpringBoot
    1. 创建类实现 HandlerInterceptor 接口
    2. 注册拦截器
      • 创建配置类实现 WebMvcConfigurer 接口
        • 此接口中有大量方法处理 SpringMVC 内容
      • 注解 @Configuration 使此类作为配置类作为配置类
      • 重写 addInterceptors 方法注册拦截器
        1. 创建拦截器对象放入
        2. 执行拦截的 url
        3. 排除拦截的 url
    3. 创建 controller 类方法处理请求测试拦截器
    // 拦截器定义
    public class MyInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("执行了拦截器");
            return true;
        }
    }
    // 注册拦截器,将拦截器对象放到容器中
    @Configuration
    public class WebConf implements WebMvcConfigurer {
        // 自动装配;对象赋值
        @Resource
        private MyInterceptor interceptor;
    
        //注册拦截器
        @Override
        public void addInterceptors( InterceptorRegistry registry) {
            // 将拦截器对象放到容器中,拦截 /doSome 请求,排除 /doOther 请求
            registry.addInterceptor(interceptor).addPathPatterns("/doSome"). excludePathPatterns("/doOther");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    Servlet

    自定义使用 servlet

    1. 定义 MyServlet 类继承 HttpServlet
      • 重写 doGet()doPost() 方法处理请求
    2. 创建配置类注册 servlet 对象
      • 注解 @Configuration 作为配置类使用
      • 定义方法注册 servlet 对象
        • 方法返回值为 ServletRegistrationBean 对象
        • 创建 ServletRegistrationBean 对象注册 myServlet
          • 使用有参构造传入 servlet 对象和对应请求的 url 地址
          • url 参数类型为可变长,可以传入多个 url
        • 方法上注解 @Bean 将对象存放到容器
    3. 自定义 servlet 类方法将会覆盖掉 controller 中的处理方法
    // MyServlet 类,注解创建对象
    @Component
    public class MyServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, 
                             HttpServletResponse resp) 
            throws ServletException, IOException {
            doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, 
                              HttpServletResponse resp) 
            throws ServletException, IOException {
            // 指定数据类型、编码格式
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter writer = resp.getWriter();
            // 输出数据
            writer.println("执行了 servlet");
            // 刷新并关闭流
            writer.flush();
            writer.close();
        }
    }
    
    // 配置类,注册 servlet 对象
    @Configuration
    public class ServletConf {
        // 自动赋值对象
        @Resource
        private MyServlet servlet;
        
        /*
        * 创建对象并放到容器中
        * 注册 servlet 对象并处理 /myServlet 请求,
        * 注册后 servlet 方法将会覆盖 controller 中对应请求处理方法
        */
        @Bean
        public ServletRegistrationBean<Servlet> servletRegistrationBean(){
            // 有参构造,传入 servlet 对象和对应的 url 地址(可变参数)
            return new ServletRegistrationBean<>(servlet, "/myServlet");
            /*
            无参构造注册 servlet
            ServletRegistrationBean bean =  new ServletRegistrationBean<>();
            bean.setServlet(servlet);
            bean.addUrlMappings("/myServlet", "/doSome", "/doOther");
            return bean;
            */
        }
    }
    
    • 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
    • 49
    • 50
    Filter
    使用方式
    • Filter 是 Servlet 中的过滤器

      • 可以处理请求:对请求的参数、属性进行调整

      • 常在过滤器中处理字符编码

    • 自定义使用 Filter,类似 servlet 的步骤

      1. 创建过滤器类实现接口 Filter
        • 实现方法 doFilter()
      2. 注册 Filter
        • 创建配置类
          • 添加注解 @Configuration
        • 定义方法注册过滤器对象
          1. 方法上添加注解 @Bean
          2. 方法返回值 FilterRegistratonBean<>
          3. 调用方法传入 filter 对象注册
          4. 设置过滤的 url 请求
    // 自定义过滤器类
    @Component
    public class MyFilter implements Filter {
        @Override
        public void doFilter(ServletRequest servletRequest, 
                             ServletResponse servletResponse, 
                             FilterChain filterChain) 
            throws IOException, ServletException {
            System.out.println("执行了过滤器方法");
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }
    // 定义配置类,注册 Filter 对象
    @Configuration
    public class FilterConf {
        @Resource
        private MyFilter filter;
        
        @Bean
        public FilterRegistrationBean<Filter> filterFilterRegistrationBean(){
          FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
            // 注册过滤器
            bean.setFilter(filter);
            // 添加过滤请求,相当于  标签
            bean.addUrlPatterns("/*");
            return bean;
        }
    }
    
    • 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
    字符集过滤器
    • CharacterEncodingFilter:字符集过滤器
      • 解决 post 请求中文乱码
        • 默认编码:ISO-8859-1
      • encoding:当前使用的编码方式
      • forceRequestEncoding:默认 false,不使用当前编码
      • forceResponseEncoding:默认 false,不使用当前编码
    配置类
    1. 直接在过滤器配置类中创建 CharacterEncodingFilter 对象

      • 设置对象属性

        • 指定编码格式
        • 指定使用编码格式
      • 将对象放到容器中

      • @Configuration
        public class FilterConf {
            @Bean
            public FilterRegistrationBean<Filter> filterFilterRegistrationBean(){
                // 创建返回对象
                FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
                // 创建字符集过滤器
                CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        	    // 设置编码格式,并指定使用:将属性赋值为 true
                encodingFilter.setEncoding("utf-8");
                encodingFilter.setForceEncoding(true);
                bean.setFilter(encodingFilter);
                bean.addUrlPatterns("/*");
                return bean;
            }
        
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
    2. 修改配置文件

      # SpringBoot 已经默认配置了 CharacterEncodingFilter
      # 但编码格式 ISO-8859-1,将此项设置为 false 以使用自定义过滤器
      server.servlet.encoding.enabled: false
      
      • 1
      • 2
      • 3
    配置文件指定
    # 使用 SpringBoot 的字符过滤器
    server.servlet.encoding.enabled=true
    # 设置字符格式为 utf-8
    server.servlet.encoding.charset=utf-8
    # 强制应答和请求使用 encoding 编码
    server.servlet.encoding.force=true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    页面

    • 页面配置
      • 将所有静态资源由 Tymeleaf 接管
        • 使用表达式动态获取数据
    • 国际化
      • 配置 i18n 文件:国际化文件
        • internationalization,国际化
        • L10N:localization,本地化
      • 通过按钮自定义切换语言版本
        • 需要自定义组件 LocaleResolver
      • 将组件放入容器中:通过 @Bean
    • 错误
      • templates 目录下创建 error 目录
      • 页面报错时会自动加载目录下页面
        • 例如:404 错误会加载 404 页面

    Thymeleaf

    介绍

    • Thymeleaf 模板

      • 一个流行的模板引擎,采用 Java 开发
        • Java 生态下模板引擎有 ThymeleafFreemakerVelocityBeetl(国产) 等
        • jsp 就是最早的模板技术
      • 模板做视图层显示数据
    • Thymeleaf 对网络环境没有严格要求

      • 能用于 web 环境和非 web 环境
        • 非 web 环境下能直接显示模板上的静态数据
        • web 环境下能像 jsp 一样从后台接收数据并替换模板的静态数据
      • 基于 html,以 html 标签为载体实现
        • 语法应用在 html 标签中
    • SpringBoot 集成了 Thymeleaf 模板技术

      • 官方推荐使用 Thymeleaf 代替 jsp 技术
        • jsp 需要编译运行,效率低

    配置

    • 创建 SpringBoot 项目添加 Thymeleaf 起步依赖

      • 自动引入最新版本 Thymeleaf 依赖
    • 基本都为默认配置,无需修改

      • 根据需求自定义修改
      # 模板缓存: 默认打开;开发阶段关闭模板缓存,使修改立即生效
      spring.thymeleaf.cache=false
      # 编码格式: 默认 UTF-8
      spring.thymeleaf.encoding=UTF-8
      # 模板类型: 默认 HTML 文件
      spring.thymeleaf.mode=HTML
      # 模板前缀: 默认类路径的前缀 classpath:/templates/
      spring.thymeleaf.prefix=classpath:/templates/
      # 模板后缀: 默认后缀 .html
      spring.thymeleaf.suffix=.html
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

    表达式

    ${key}
    • th:text="${key}":标准变量表达式
      • 获取 key 对应的文本数据
    • 在页面 html 标签中使用 tx:text="${key}"接收替换数据
      • th:test="":Thymeleaf 的属性,用于文本显示
    • key 是 request 作用域中的 key
      1. 使用 reque st.setAttribute(key, value); 添加数据
      2. model.addAttribute(key, value);
    
    <p th:text="${key}">正常的静态数据p>
    
    <body>
    <h1>标准变量表达式 ${} h1>
    <h2 th:text="${data}">全部信息h2>
    <div>
        
        <h3>id = h3><h3 th:text="${data.id}">idh3><br/>
        <h3>name = h3><h3 th:text="${data.name}">idh3><br/>
        <h3>age = h3><h3 th:text="${data.getAge()}">idh3><br/>
        <h3>date = h3><h3 th:text="${data.getDate()}">idh3><br/>
    div>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    *{key}
    • th:text="*{}":选择变量表达式
      • 获取 key 对应的 value 对象的属性
    • 需要和 th:object="${key}" 一起使用
      • 简单获取对象的属性值
      • th:object="${key}" 作用范围内可以直接使用 key 对应 value 对象的属性
        • *{field}:通过对象字段直接获取值
        • 等价于:th:text=${data.name}
    • 或通过完整名获取属性
      • th:text="{data.name}":和 ${key} 格式相同
    <body>
    <h1>选择变量表达式 *{}h1>
    <h2 th:text="${data}">全部信息h2>
        
    
    <div th:object="${data}">
        
        <h3>id = h3><h3 th:text="*{id}">idh3><br/>
        <h3>name = h3><h3 th:text="*{name}">nameh3><br/>
        <h3>age = h3><h3 th:text="*{getAge()}">ageh3><br/>
        <h3>date = h3><h3 th:text="*{getDate()}">dateh3><br/>
    div>
        
    <h3>ageh3><h3 th:text="*{data.age}">使用完整名h3>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    @{url}
    • th:href="@{url}":链接表达式

      • 表示链接,使用在链接中

        
        <script src=" ">script>    
        <link href=" ">link>
        <a href=" ">a>    		
        <form action=" ">form>
        <img src="">img>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
      • url 可以是绝对地址或相对地址

    • 传参

      • () 内传递参数:th:href="@{do4/(id=${id}, name=${name})}"
        • 多个参数使用 , 分隔
      • 嵌套表达式、拼接字符串:"@{'do3?id=' + ${id}}"
      <body>
      <h2>链接表达式 @{url}h2>
      <h3>链接绝对路径h3>
      <a th:href="@{https://www.baidu.com}">绝对地址,链接到百度a>
      
      <h3>链接相对路径h3>
      
      <a th:href="@{'do3?id=' + ${id}}">相对地址,传参a>
      
      <h3>相对地址,使用字符串传参h3>
      <a th:href="@{'do4?id=' + ${id} + '&name=' + ${name}}">相对地址,使用字符串传参a>
          
      
      <h3>推荐使用的传参方式h3>
      <a th:href="@{do3/(id=${id})}">单个参数a>
      <a th:href="@{do4/(id=${id}, name=${name})}">多参数a>
      body>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    属性

    • 大部分属性和 HTML 相同,作用和原来相同
      • 添加前缀 th
        • 添加 th 之后经过模板引擎处理
      • 可以使用变量表达式
    th:action
    • 定义后台控制器路径
      • 类似
        标签的 action 属性
      • 结合 URL 表达式,获取动态变量
    <form id="login" th:action="@{/login}" th:method="post">form>
    
    • 1
    th:method

    设置请求的方法

    <form id="login" th:action="@{/login}" th:method="post">form>
    
    • 1
    th:href

    定义超链接,结合 URL 表达式获取动态变量

    <a th:href="@{do3/(id=${id})}">单个参数a>
    
    • 1
    th:src
    • 用于外部资源引用
      • 比如: