SpringBoot

文章目录

SpringBoot

  • pom.xml

每个springboot项目中都要引入父项目

在spring-boot-starter-parent 的 父项目 spring-boot-dependencies里有各种依赖的版本控制

复制代码
<parent>
    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>2.7.1</version>

</parent>

<!--
 在spring-boot-starter-parent 的 父项目 spring-boot-dependencies
 里有各种依赖的版本控制
 -->

<dependencies>
    <!-- spring-boot的场景启动器,关联该场景里的常用jar包 -->
    <!-- web场景启动器里 关联的有 日志,内嵌tomcat,json等 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-configuration-processor</artifactId>

        <optional>true</optional>

    </dependency>

    <!-- 配置属性类跟配置文件绑定的处理器 -->

    <dependency>
        <groupId>org.projectlombok</groupId>

        <artifactId>lombok</artifactId>

    </dependency>

</dependencies>

入门程序

spring-boot的场景启动器,关联该场景里的常用jar包

web场景启动器里 关联的有 日志,内嵌tomcat,json等

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

</dependency>
  • application.properties

    server.port=8080

    server.servlet.context-path=/ls

  • handler

    @RestController //返回json

    public class HelloHandler {

    @RequestMapping("/hello")

    public String hello(){

    return "springboot入门程序-hello!";

    }

    }

  • 创建启动类/向导类/主程序


    • *

      复制代码
          		注意包结构 :主包结构下 创建

    @SpringBootApplication//默认扫描所在包里的子包里的 各类注解

    public class MyRunner {

    public static void main(String[] args) {

    SpringApplication.run(MyRunner.class, args);

    }

    }

  • SpringBootApplication注解上 被SpringBootConfiguration 标注

  • SpringBootConfiguration 被 Configuration标注

  • Configuration 是 spring中的配置类,也是被扫描为组件的一个注解

  • Configuration注解上 被 Component 标注 会被扫描为spring容器里的组件/bean

  • 运行主程序,在浏览器输入localhost:8080/ls/hello即可访问

  • 添加spring-boot-maven-pluginpom.xml创建可执行jar

  1. 停止程序

  2. 添加插件

    复制代码
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
    
                <artifactId>spring-boot-maven-plugin</artifactId>
    
            </plugin>
    
        </plugins>
    
    </build>
  3. 运行maven 的打包命令

  4. 将jar拷贝入桌面文件夹abc内 (模拟任意文件夹)

  5. 使用命令运行jar

    java -jar sbt001-1.0-SNAPSHOT.jar

    java -jar -Dserver.port=8090 sbt001-1.0-SNAPSHOT.jar

依赖管理

1.jar包版本

每个SringBoot项目都需要引入父项目

复制代码
    <parent>
        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.6.6</version>

    </parent>

ctrl单击spring-boot-starter-parent查看父项目发现: 父项目 还有一个 父项目

复制代码
  <parent>
    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-dependencies</artifactId>

    <version>2.6.6</version>

  </parent>

ctrl单击spring-boot-dependencies查看,发现几乎声明了开发中常用各种jar的版本号:

复制代码
<properties>
    <activemq.version>5.16.1</activemq.version>

    <antlr2.version>2.7.7</antlr2.version>

    <appengine-sdk.version>1.9.86</appengine-sdk.version>

    <artemis.version>2.15.0</artemis.version>

    <aspectj.version>1.9.6</aspectj.version>

    ......
  • 版本号自动被父项目进行管理dependencyManagement ,在导包时可以不写版本号

  • 可以自行指定版本号

    复制代码
      <dependency>
            <groupId>mysql</groupId>
    
            <artifactId>mysql-connector-java</artifactId>
    
            <version>5.1.47</version>
    
        </dependency>
  • 可以在自己项目的pom中指定版本号属性

    复制代码
    <properties>
        <mysql.version>5.1.47</mysql.version>
    
    </properties>
2.场景启动器

springboot中有很多 形如: spring-boot-starter-XXX 的场景启动器 , 他会自动把XXX场景需要的所有jar包一同依赖进来.

复制代码
<!-- 引入web场景相关的依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

ctrl+单击 spring-boot-starter-web 可以看到 web场景的很多依赖被加入.

helloworld 的自动配置

  1. 自动引入并配置好了内嵌的tomcat

  2. 自动引入并配置好了web常见组件. 比如 示例里的中文没有乱码说明已经配置好了字符编码过滤器

    复制代码
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(MainInitiator.class, args);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }

在打印的容器中组件名的时候,我们发现了: 各种viewResolver , multipartResolver,dispatcherServlet,characterEncodingFilter,jackson等组件.

  1. 默认的包结构 约定>配置 目前必须这么做.

主程序(向导/启动类)所在包下及其子包里 带有注解的组件 都才会被扫描到容器中.

  1. 各种配置都有默认配置

比如: tomcat的端口号8080

我们可以在resources目录下的 application.properties文件中进行修改

复制代码
server.port=8088

在我们写的时候发现有快捷键提示. ctrl单击:server.port 跳转到配置属性类中: 转到setter方法

复制代码
@ConfigurationProperties(
    prefix = "server",
    ignoreUnknownFields = true
)
public class ServerProperties {
    private Integer port;
    ......

@ConfigurationProperties :配置属性类 , 前缀是server, springboot会自动绑定到属性配置文件中

而配置属性类 的 信息 会被 系统读取 .

  1. 按需加载自动配置.

注: 在配置文件中 配置: debug=true 则可以在启动界面中看到 条件评估报告: 哪些场景装配了.哪些场景没装配,缺少了哪些条件等

容器功能里的几个注解

1.@Configuration @SpringBootConfiguration
@AutoConfiguration 配置类

2.@Import

@Import注解 可以给容器中导入某个组件

复制代码
@Import(value = {Random.class, Date.class})
@Configuration
public class MyConfig {
    ...

默认的组件的名字 全路径类名 eg: java.util.Random

注: 一般的bean的id或名字 为 类名小写 比如 myRunner
3.@Conditional

满足指定的条件才生效. 可以添加到类或方法上
4.配置绑定

  • 配置文件里使用一些前缀 可以 直接绑定到配置属性类里的属性

  • 在 application.properties 中
  • handler
  • 成功运行

SpringInitializr

使用IDEA 的SpringInitializr 快速创建 springBoot应用 必须联网

  • 此处改为2.7.1,删除java17版本,使用java8

  • 目录结构

yml/yaml

  • YAML 的配置文件后缀为 .yml
  • 使用缩进和换行表示层级关系

yml

复制代码
server:
  port: 8082 # 属性和属性值之间 使用 冒号 空格 隔开
  servlet:
    context-path: '/ls' # 字符串可以使用引号 或 不使用


cat:
  name: 'tomcat'
  weight: 2.2D
dog:
  nick: 旺财
  age: 5
#
beauty:
  name: '李思'
  age: 28
  model: true
  cat:
    name: '大花猫'
    weight: 3.3D
  birthday: 2000/01/12 # yml里日期格式必须为 yyyy/MM/dd
 
 #数组 list set 都有两种写法
  hobbys: ['冬泳','羽毛球','烹饪']
  foods:
    - 大白菜
    - 胡萝卜
    - 冬枣
  salarys: [1000.0F,555.5F,6666.8F]
 
 # map或对象 都有两种写法
  sizes:
    height: 177cm
    weight: 55.9kg
    eye: 4.9
# 对象可以用{}jason格式 也可使用缩进列出的格式
  dogs:
    big: [{'nick':'大黄','age':7},{'nick':'二黄','age':6},{'nick':'小黄','age':5}]
    small:
      - {'nick':'蝴蝶1号','age':1}
      - {'nick':'蝴蝶2号','age':2}
      - nick: '蝴蝶3号'
        age: 3

controller

复制代码
@RestController
public class YMLController {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    @Autowired
    private Beauty beauty;
    
        @RequestMapping("/demo")
    public Map<String,Object> demo(){
        Map<String,Object> map = new HashMap<>();
        map.put("猫数据",cat);
        map.put("狗数据",dog);
        map.put("美女数据",beauty);
        return map;
    }
}

在浏览器访问 : http://localhost:8082/ls/demo

SpringMVC自动配置

1: springboot引入web场景以后, 会自动配置一些 springmvc的配置, 能够应对绝大多数的web场景.

2: 如果我们想继续使用 springboot的默认配置 , 以及还能自己添加一些配置, 那么我们可以

  • 使用@Configration 和 @Bean 自己做配置类 ,添加组件
  • 或实现 WebMvcConfirgure接口, 重写方法或添加 一些组件进去.
  • 或使用mvc已经绑定的前缀的配置属性类 在 配置文件里更改默认配置

3: 如果我们想弃用springboot的mvc的所有默认配置, 全面接管mvc场景的配置, 使用**@Configration + @EnableWebMvc**

WebMvcAutoConfigration 自动配置类有一个条件是 : spring容器里不能有这个类型的组件: WebMvcConfigurationSupport

@EnableWebMvc 注解:

发现 自动向spring容器添加一个组件: DelegatingWebMvcConfiguration

DelegatingWebMvcConfiguration 是 WebMvcConfigurationSupport 的子类型

静态资源

A.默认的静态资源目录

在static下的index.html会被默认访问


改变默认的静态资源路径:

复制代码
 # 配置springboot静态资源 存放的位置 为 类路径下的my文件夹下的(原来的static里的index.html就访问不了)
spring:
  web:
    resources:
      static-locations: ['classpath:/my/']
    # 配置springboot静态资源的 访问路径
  mvc:
    static-path-pattern: '/a/**'
B. WebJars 了解

除了前面提到的"标准"静态资源位置外,Webjars内容也有特殊情况。/webjars/**如果jar文件以Webjars格式打包,则从jar文件提供带有路径的所有资源。

在 webjars的网站上:https://www.webjars.org/ 搜索 jquery的jar包依赖 添加到 pom中

必须添加下面这个:

复制代码
<dependency>
    <groupId>org.webjars</groupId>

    <artifactId>jquery</artifactId>

    <version>3.6.0</version>

</dependency>



<button id="btn" type="button">点击</button>

<script src="/ls/webjars/jquery/3.7.1/jquery.slim.js"></script>

<script>
    $("#btn").click(function () {
        alert(1+2+3+4);
    })
</script>
C.默认欢迎页面

Spring Boot支持静态和模板欢迎页面。它首先index.html在配置的静态内容位置中查找文件。如果找不到,它将寻找一个index模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。
模板欢迎页: 走控制层,经视图解析器得到的欢迎页.

①.静态欢迎页

在static目录下 放入 index.html , 不使用任何的自定义的: 静态资源访问前缀 的前提下,

则可以测试看到默认欢迎页.

②.controller处理 /index请求 转发到 欢迎页 后面说到模板时再说.

请求参数处理

A.restful风格
  • html

  • yml

    spring:

    mvc:

    hiddenmethod:

    filter:

    enabled: true

  • controller

    @GetMapping("/user")

    public String get(){

    return "restful风格的get请求完成!";

    }

    @PostMapping("/user")

    public String post(String username){

    return "restful风格的post请求完成! - "+username;

    }

    @PutMapping("/user")

    public String put(String username){

    return "restful风格的put请求完成! - "+username;

    }

    @DeleteMapping("/user")

    public String delete(String username){

    return "restful风格的delete请求完成! - "+username;

    }

○ 让 mvc自动配置的restful过滤器失效,向容器里自己添加一个

复制代码
@Configuration
public class MyConfig {
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        hiddenHttpMethodFilter.setMethodParam("mym");
        return hiddenHttpMethodFilter;
    }
}


<h3><a href="/ls/user">GET请求</a></h3>

<form action="/ls/user" method="post">
    <input name="username" value="POST请求"/>
    <input type="submit" value="POST请求"/>
</form>

<form action="/ls/user" method="post">
    <input name="username" value="PUT请求"/>
    <input type="hidden" name="mym" value="PUT"/> 使用mym
    <input type="submit" value="PUT请求"/>
</form>

<form action="/ls/user" method="post">
    <input name="username" value="DELETE请求"/>
    <input type="hidden" name="mym" value="DELETE"/>
    <input type="submit" value="DELETE请求"/>
</form>
B.自定义类型转换器

在WebMvcConfigurer接口中可以进行很多配置. 下面添加自定义类型转换器: (Converter只用于 请求参数绑定到handler方法入参, 不会对配置文件里的有作用.)

  • html

    GET请求

  • 转换器

    @Configuration

    public class MyConfig implements WebMvcConfigurer {

    复制代码
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new Converter<String, Date>() {
    
            @Override
            public Date convert(String source) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    Date date = sdf.parse(source);
                    return date;
                } catch (ParseException e) {
                    e.printStackTrace();
                    throw new RuntimeException("不符合转换的日期格式! source = "+source);
                }
            }
        });
    }

    }

  • controller

数据访问

每一个XXXX-starter-XXX 都会有一个 XXXautoConfigration的类 做自动配置.一般自动配置类 还 绑定了在配置文件中的某个前缀

1.默认连接池是 Hikari 默认配置了JdbcTemplate
  • 添加 JDBC 启动器

    • 连接池的自动配置类 : DataSourceAutoConfigruation
  • 加入mysql的驱动 依赖

  • 修改配置文件

  • 在 test包下 进行测试 -

    @Resource

    private JdbcTemplate template;

    @Test

    void contextLoads() {

    String sql = "select count(*) cs from worker";

    Integer integer = template.queryForObject(sql, Integer.class);

    System.out.println(integer);

    }

2.修改连接池为 Druid
  • 引入 druid的 starter
  • 修改配置文件

监控功能的访问路径 是 /druid/index.html

  • controller

druid里有内置的DataSource,可以自动注入

复制代码
@Autowired
private DataSource dataSource;

@ResponseBody
@RequestMapping("/workers")
public List<Worker> workers(){
    JdbcTemplate template = new JdbcTemplate(dataSource);
    String sql = "select * from worker";
    List<Worker> workers = template.query(sql, new BeanPropertyRowMapper<>(Worker.class));
    return workers;
}
3.springboot的配置文件

1.可以放置 4个位置 加载顺序 由上到下

2.多配置文件形式

复制代码
多配置文件形式 采用 application-xxx.yml xxx表示不同阶段
如: dev prod test

dev: 开发环境

prod: 生产环境

test: 测试环境

  1. application.yml里 使用 - - - 多文档形式

    复制代码
     删除三个阶段的配置文件

日志

1.Log4j 介绍
复制代码
    Log4j是Apache是apache旗下的一款开源的日志框架,通过在项目中使用Log4j,我们可以控制信息输出到控制台,文件、甚至是数据库中。我们可以控制每一条日志的输出格式。通过定义日志的输出级别,可以更灵活的控制日志的输出过程。方便项目调试。
2.Log4j组件
复制代码
    log4j主要由Loggers(日志记录器),Appenders(输出器),和Layout(日志格式化器)。其中Loggers控制日志输出级别和日志是否输出;Appenders指定日志的输出方式(输出到控制台,文件等);Layout控制日志输出的格式。
Loggers:
复制代码
    日志记录器,负责收集处理日志记录,实例的命名是类"XX"的全限定类名,Loggers的名字大小写铭感,其命名有继承机制:例如:name为org.apache.commons的logger会继承为name为org.apache的logger。

    Log4j中有一个特殊的logger叫做"root",它是所有logger的根。也就意味着其他所有的logger都会直接会间接的继承root。root的logger可以用Logger.getRootLogger()方法获取。但是,自log4j1.2版以来,Logger类已经取代了Category类,对于熟悉早期版本的log4j的来说,Logger类可以被视为Category的别名。
Appensers:
复制代码
    Appensers用来指定日志输出到哪个地方,可以同时指定日志输出目的地,Log4j常用的输出目的地有一下几种:

ConsoleAppender : 将日志输出到控制台
FileAppender : 将日志输出到文件
DailyRollingFileAppender :将日志输出到一个文件,并且每天输出到一个新的文件。
RollingFileAppender :将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定的尺寸时,会自动把文件改名,同时产生一个新的文件。
JDBCAppender:将日志信息保存到数据库。

Layouts:
复制代码
    布局器Layouts用于控制日志输出内容的格式,让我们可以使用各种需要的格式输出日志。Log4j常用的Layouts:

HTMLLayout: 格式化日志输出HTML表格形式

SimpleLayout: 简单的日志输出格式化,打印的日志格式为(info - message)

PatternLayout:最强大的格式化期,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的转换格式。

3.案例



4.使用log4j & 日志适配
  • 使用log4j

    • 添加jar包,将lib文件夹添加为库
    • log4j.properties(建在src下)

    级别 , 自定义的输出源

    log4j.rootLogger=INFO,myConsole

    输出源的配置

    控制台输出

    log4j.appender.myConsole=org.apache.log4j.ConsoleAppender

    输出布局采用正则布局

    log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout

    正则布局格式

    log4j.appender.myConsole.layout.ConversionPattern=%p [%t] %l %m%n

  • java

    public class Show {

    // 日志对象

    public static Logger logger = Logger.getLogger(Show.class);

    复制代码
    public static void main(String[] args) throws InterruptedException {
        int cnt = 0;
        for (int i = 1; i <= 100; i++) {
            try {
                int div = new Random().nextInt(3);// 0 1 2
                logger.info("次数: " + i);
                int result = 100 / div;
                //日志输出
                logger.info("结果: " + result);// slf4j里的日志输出可以使用{}占位符
            } catch (ArithmeticException e) {
                logger.error(e.getMessage());
                cnt++;
            }
            Thread.sleep(1300);
        }
        logger.info("出现异常次数 即 随机到0的次数 : " + cnt);
    
    }

    }

  • 输出

  • 使用slf4j门面

    • jar
    • log4j.properties

    级别 , 自定义的输出源

    log4j.rootLogger=INFO,myConsole,myScrollFile

    myFile

    #log4j.appender.myFile=org.apache.log4j.FileAppender

    #log4j.appender.myFile.layout=org.apache.log4j.PatternLayout

    #log4j.appender.myFile.layout.ConversionPattern=%p [%t] %l %m%n

    #log4j.appender.myFile.File=logs/my.log

    #log4j.appender.myFile.Append=true

    log4j.appender.myScrollFile=org.apache.log4j.DailyRollingFileAppender

    log4j.appender.myScrollFile.layout=org.apache.log4j.PatternLayout

    log4j.appender.myScrollFile.layout.ConversionPattern=%p [%t] %l - %d - %m%n

    log4j.appender.myScrollFile.File=logs/my.log

    log4j.appender.myScrollFile.Append=true

    log4j.appender.myScrollFile.DatePattern='.'yyyy-MM-dd-HH-mm

  • 在项目下建包logs

  • Show

    public class Show {

    // 日志对象

    //public static Logger logger = Logger.getLogger(Show.class);

    public static Logger logger = LoggerFactory.getLogger(Show.class);

    复制代码
    public static void main(String[] args) throws InterruptedException {
        int cnt = 0;
        for (int i = 1; i <= 100; i++) {
            try {
                int div = new Random().nextInt(3);// 0 1 2
                logger.info("次数: " + i);
                int result = 100 / div;
                //日志输出
                logger.info("结果: {}",result);// slf4j里的日志输出可以使用{}占位符
            } catch (ArithmeticException e) {
                logger.error(e.getMessage());
                cnt++;
            }
            Thread.sleep(1300);
        }
        logger.info("出现异常次数 即 随机到0的次数 : {}",cnt);
    
    }

    }

  • 输出

  • 在SpringBoot中使用logbak

    • 在resource下添加logbak-spring.xml
    • 在application.xml中添加

    logging:

    config: 'classpath:logbak-spring.xml'

thymeleaf

springboot 默认不支持 JSP , 推荐使用thymeleaf.

使用详情参考使用文档

入门程序
  • pom.xml
  • 查看ThymeleafAutoConfiguration

  • 查看ThymeleafProperties

  • 在 ThHelloConytroller

    @Controller

    public class ThHelloController {

    复制代码
    @Autowired
    private Beauty beauty;
    
    @RequestMapping("/thindex")
    public String thindex(){
        return "thindex";
    }

    }

  • thindex

    thymeleaf入门

  • ThHelloController

    @Controller

    public class ThHelloController {

    复制代码
    @Autowired
    private Beauty beauty;
    
    @RequestMapping("/thhello")
    public String thhello(ModelMap map){
        map.addAttribute("msg","thymeleaf入门程序");
        map.addAttribute("beauty",beauty);
        return "success";
    }

    }

  • success.html

    Title

    文本中直接获取数据是: [[${msg}]]

    在标签里的数据是:

    美女名字:

    美女年龄:

    美女是不是模特:

    美女生日:

    美女的猫:

    :



    \[${entry.key}\]\] - *** ** * ** *** *** ** * ** *** -

    *** ** * ** *** *** ** * ** *** ### 美女是模特 ### 大学老师 *** ** * ** *** *** ** * ** *** 小学生

    大学生

    博士生

    院士

1. 新建项目-登录
  1. 使用初始化向导创建项目,勾选必要的场景依赖

  2. 将静态资源加入项目

  3. 将login.html放入templates目录下 并引入thymeleaf的命名空间 xmlns:th="http://www.thymeleaf.org"

  4. 创建 跳转登录页的controller 方法

    @Controller

    public class IndexController {

    /**

    * 跳转登录页

    * @return

    */

    @GetMapping(path = {"/","/login"})

    public String loginPage(){

    return "login";

    }

  5. 将index.html放入templates目录下 并引入thymeleaf的命名空间

  6. 修改login.html中登录表单的属性

    复制代码
    <form class="form-signin" th:action="@{/login}" method="post">
  7. 创建 处理登录 并 跳转首页的controller 方法

    复制代码
    @PostMapping(value = {"/login"})
    public  String indexPage(User user, HttpSession session,Model model){
        if (!StringUtils.isEmpty(user.getUsername())
            && !StringUtils.isEmpty(user.getPassword())){
            session.setAttribute("user", user);
        }else{
            model.addAttribute("msg", "用户名或密码不正确!");
            return "login";
        }
        return "redirect:/index.html";
    }
    
    @RequestMapping("/index.html")
    public  String redirectIndexPage(@SessionAttribute(name = "user",required = false) User user,Model model){
        if (user==null){
            model.addAttribute("msg", "未登录!请先登录!");
            return "login";
        }
        return "index";
    }

    //这里为了 防止表单 重复提交.

  8. 设计bean User类型

    @Data

    @ToString

    public class User {

    private String username;

    private String password;

    }

  9. login.html中添加一个 回显 msg信息的标签

    ... ...

2.抽取公共部分,让一个页面可以复用
  1. 创建table文件夹,存放所有表格页面
  1. 观察页面将 页面中公共的部分 抽取到 common.html中 ,使用thymeleaf语法可以让其他页面引用common.html中的 部分
  1. 在被抽取页面引用公共部分

    复制代码
    <!-- 引入相同的头部部分 -->
    <th:block th:include="common::commonHead"/>
    <!-- 引入相同的左侧导航栏 -->
    <th:block th:replace="common::commonLeftNav"></th:block>    

三种引入公共片段的方式的区别:

复制代码
公共部分: 
<footer th:fragment="copy">
  &copy; 2011 The Good Thymes Virtual Grocery
</footer>


使用三种引入方式:
<body>

  <div th:insert="footer :: copy">2</div>

  <div th:replace="footer :: copy">2</div>

  <div th:include="footer :: copy">2</div>

  
</body>

结果:
<body>

  整个片段插入 到 当前标签里
  <div>
    <footer>
      &copy; 2011 The Good Thymes Virtual Grocery
    </footer>

  </div>

  整个片段替换 当前标签
  <footer>
    &copy; 2011 The Good Thymes Virtual Grocery
  </footer>

   只有片段里的内容 替换到 当前标签内 
  <div>
    &copy; 2011 The Good Thymes Virtual Grocery
  </div>

  
</body>
3.拦截器(登录拦截)

1.创建拦截器实现类

复制代码
/**
 * 在访问诸如 /tables/** 这种特殊路径下的内容时 需要有登录权限
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        if (user == null){
            log.warn("正在访问的资源为: {}",request.getRequestURI());
            //重定向到登录页面的handler方法 不放行
            response.sendRedirect(request.getContextPath()+"/login");
            return false;
        }
        return true;
    }
}

2.配置拦截器,将拦截器注入容器,并添加拦截规则

复制代码
@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LoginInterceptor loginInterceptor = new LoginInterceptor();
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**") // 添加拦截路径
                .excludePathPatterns("/","/login","/js/**","/images/**",
                        "/fonts/**","/css/**","/error/**");// 排除拦截路径
    }

    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}
4. 文件上传
  1. 添加上传表单页面 form_layouts.html 添加 thymeleaf的 命名空间

    Username

    复制代码
                                <input type="text" class="form-control" name="username" id="username" placeholder="username">
                            </div>
    
                            <div class="form-group">
                                <label for="password">Password</label>
    
                                <input type="password" class="form-control" name="password" id="password" placeholder="Password">
                            </div>
    
                            <div class="form-group">
                                <label for="headimg">头像</label>
    
                                <input type="file" id="headimg" name="headimg">
                                <p class="help-block">Example block-level help text here.</p>
    
                            </div>
    
                            <div class="form-group">
                                <label for="liveimg">生活照</label>
    
                                <input type="file" id="liveimg" name="liveimg" 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">Submit</button>
    
                        </form>
5.错误处理

1.自定义错误页面

可以在静态文件夹下创建 error文件夹 也可以在 模板文件夹下 创建 error文件夹,给页面 添加 thymeleaf的命名空间

2.在5xx页面上 可以使用 ${message}来获取 异常信息.

${status} 取响应状态码

3.异常处理自动配置原理

4.定义全局异常处理器 @ControllerAdvice + @ExceptionHandler 默认优先级高

复制代码
@ControllerAdvice // 有@Component
@Slf4j
public class MyGlobalExceptionHandler {

    @ExceptionHandler({ArithmeticException.class,NullPointerException.class})
    //这是处理 异常的方法,用起来其实就是handlere方法
    public ModelAndView exceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error/myxx");
        mv.addObject("status", "9527");
        mv.addObject("message","出现了算术或空指针异常");
        log.warn("全局异常处理器工作了,异常: {}",e.getMessage());
        return mv;
    }
}

5.自定义异常 @ResponseStatus 定义状态码 和 错误原因信息 (因为springboot 异常和错误要带着http响应状态码)

复制代码
@ResponseStatus(code = HttpStatus.BAD_REQUEST,reason = "请求语法有问题")
public class CustomException extends Exception{
}

6.自定义异常解析器 默认优先级低 , 使用@order注解 设置优先级

复制代码
@Component
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error/myxx");
        mv.addObject("status",9999);
        mv.addObject("message","异常解析器处理了!");
        return mv;
    }
}
6.国际化

1.提供国际化资源配置文件

复制代码
title=默认标题
user=默认用户
pass=默认密码
title=登录
user=用户
pass=密码
title=Login
user=Username
pass=Password
  1. yaml配置指定资源配置文件位置

    spring:

    messages:

    basename: ls

3.自定义国际化解析器

复制代码
public class MyLocaleResolver implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String lan = request.getParameter("lan");
        if (lan != null && lan.contains("_")){
            String[] data = lan.split("_");
            // data[0] zh  data[1] CN
            Locale locale = new Locale(data[0],data[1]);
            return locale;
        }
        // 返回默认国际化信息对象 或者 自定义一个
        return Locale.getDefault();
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

4.配置为组件, 组件名必须为 localeResolver

复制代码
@Configuration
public class MyConfig implements WebMvcConfigurer {
 @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

5.thymeleaf里结合消息表达式一起使用

复制代码
<a th:href="@{/index(lan='zh_CN')}">中文</a>

<a th:href="@{/index(lan='en_US')}">英文</a>

<h2 th:text="#{index.login}"></h2>

<h2 th:text="#{index.register}"></h2>
相关推荐
Lizhihao_7 分钟前
JAVA-堆 和 堆排序
java·开发语言
极客先躯12 分钟前
高级java每日一道面试题-2025年3月21日-微服务篇[Nacos篇]-什么是Nacos?
java·开发语言·微服务
工业互联网专业20 分钟前
基于springboot+vue的动漫交流与推荐平台
java·vue.js·spring boot·毕业设计·源码·课程设计·动漫交流与推荐平台
雷渊23 分钟前
深入分析Spring的事务隔离级别及实现原理
java·后端·面试
Smilejudy32 分钟前
不可或缺的相邻引用
后端
惜鸟33 分钟前
Elasticsearch 的字段类型总结
后端
rebel34 分钟前
Java获取excel附件并解析解决方案
java·后端
微客鸟窝36 分钟前
Redis常用数据类型和命令
后端
熊猫片沃子38 分钟前
centos挂载数据盘
后端·centos
微客鸟窝39 分钟前
Redis配置文件解读
后端