SpringBoot基础篇

什么是 spring boot

-----简单的说, spring boot 就是整合了很多优秀的框架,不用我们自己手动的去写一堆 xml 来进行配置。
从本质上来说, Spring Boot 就是 Spring, 它做了那些没有它你也会去做的 Spring Bean 配置。它使用 “ 习惯优于配置 ” (项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)的理念让你的项目快速运行起来。使用 Spring Boot 很容易创建一个独立运行
(运行 jar, 内嵌 Servlet 容器)、准生产级别的基于 Spring 框架的项目,使用 Spring Boot 你可以不用或者只需要很少的 Spring 配置。
框架特点:
1 :创建独立的 spring 应用。
2 :嵌入 Tomcat, Jetty, Undertow 而且不需要部署他们。
3 :提供的 “starters” 来简化 Maven 配置
4 :尽可能自动配置 spring 应用 , 绝对没有代码生成和 XML 配置要求。
5 :提供生产指标 , 健壮检查和外部化配置
微服务架构 : 将子系统拆成一个一个的 jar 包运行就是微服务。 Spring Boot算是微服务 开发的入门级 框架

image.png

image.png

2.spring boot 优缺点:
优点:
快速构建项目
对主流的开发框架的无配置集成
项目可以独立运行,无须外部依赖 servlet 容器
提供运行时的应用监控
极大的提高了开发、部署效率
与云计算的天然集成
缺点:
入门易,精通难,它没有增强 spring 的功能,只是帮助我们做了很多本需要我们自己
做的配置整合工作,本质还是我们以前学习的那些框架知识的应用。

SpringBoot的入门案例

  1. 创建一个并配置项目
    1,创建一个Maven工程
    image.png

    处理中文乱码设置
    image.png

    image.png

2,进入官网,找到pom.xml配置文件
百度---搜索‘spring’---进入一个主页---project---spring boot,当前版本为3.x1(2023年1月)

image.png

image.png

image.png

image.png

maven配置,分别是启动器,web应用
image.png


    4.0.0

    cn.ybzy.spbtdemo
    springbootdemo
    1.0-SNAPSHOT
    
        org.springframework.boot
        spring-boot-starter-parent
        3.0.1
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
    
    
        8
        8
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

有可能有如下错误:
java: 无法访问org.springframework.boot.SpringApplication
错误的类文件: /E:/JavaWeb/maven/local_repository35/org/springframework/boot/spring-boot/3.0.1/spring-boot-3.0.1.jar!/org/springframework/boot/SpringApplication.class
类文件具有错误的版本 61.0, 应为 52.0
请删除该文件或确保该文件位于正确的类路径子目录中。

该版本号与jdk版本号存在对应关系,61.0对应jdk17,52.0对应jdk8。
所以是某个依赖的版本太高,降低版本即可,具体是哪个依赖就需要自己排查了
我的项目中是

        org.springframework.boot
        spring-boot-starter-parent
        3.0.0
         
    
改为2.0.0.RELEASE,再重新load [maven](就是点一下右上角的m字小按钮),就好了

        org.springframework.boot
        spring-boot-starter-parent
        2.7.1
    

3,写一个启动入口,并启动之。


image.png
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 这个注解就是告诉我们的springboot这个类就是我们主启动类
 */
@SpringBootApplication
public class ApplictionMain {
    //main程序的主入口
    public static void main(String[] args){
        SpringApplication.run(ApplictionMain.class,args);
    }
}

再在控制层写一个控制类IndexController.java

@Controller
public class IndexController {
    @ResponseBody             //这里没有做视图(index.html)模板,这里我们直接返json格式数据到浏览器
    @RequestMapping(value={"/index.html","/"},method = RequestMethod.GET)
    public String index(){
        return "hello spring boot project";
    }
}

4,启动

image.png

或打包复制到任何地方,再运行java -jar命令
image.png

image.png

cmd---输入如下命令,启动程序

E:\java>java -jar springbootdemo-1.0-SNAPSHOT.jar

浏览器中输入http://localhost:8080/index.html
如果端口号被占用,可用如下图所示处理

image.png

快速创建SpringBoot项目

在项目开发时候,我们不会自己创建一个maven项目,自己慢慢导入依
赖,有更方便的方法:

  1. idea快速创建spring boot项目:
    使用Spring Initializr
    注意1:需要联网
    注意2:resources里的目录结构:
    (1)static:是用来存放静态资源的,比如css,js,img....;
    (2)templates:用来存放freemarker或者thymeleaf的模板
    (3)application.properties: SpringBoot的配置文件,在这里可以修改SpringBoot的默认配置
    image.png

    image.png

    image.png

    注意:默认启动器为3.0.1(即现在最新稳定版2022/12/30),要匹配jdk15,但本人还用jdk 8,所以改一下pom.xml文件中的启动器为2.7.1版。

        org.springframework.boot
        spring-boot-starter-parent
        2.7.1

    
    
    
        8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    
image.png

image.png
  1. sts(eclipse)快速创建spring boot项目


    image.png

    image.png

对SpringBoot入门案例的关键点

我们SpringBoot的入门案例中,即做了两个重要工作:配置pom.xml文件,写启动类

  1. pom.xml依赖配置文件,这里两个关键点:
    ①帮助我们进行版本控制的父模块

  org.springframework.boot
  spring-boot-starter-parent
   2.7.1
 

在这个父模块的父模块里有spring boot的所有默认依赖的jar包的版本信息


image.png

②启动器的配置,这个启动器才是真正导入jar的配置



   org.springframework.boot
   spring-boot-starter-web

这种启动器, spring boot 有 44 个之多,每一个启动器就对应一个功能完整的应用场景所需要的一系列 jar
包:
spring-boot-starter-web :这个启动器就是与 web 应用有关的所有 jar 包, spring boot 配置了这个的启动器,
就会自动导入这个启动器对应 web 应用的所需要的所有 jar 包。

这两个核心配置,一个决定默认的jar包的版本,一个决定导入什么jar包!\

  1. 程序入口主类:ApplicationMain,这里也有两个注意的知识点:
    ①注解 @SpringBootApplication 声明有这个注解的类是主类,是spring boot的执行的入口,没有这个注解注解的类,就没有入口,没有入口,应用就启动不了
    ② SpringApplication.run( ApplicationMain .class, args); 的第一个参数的意义:让springboot知道 ApplicationMain 所在的包以及这个包下的所有子包,是spring的扫描组件范围,只有在这个范围的controller,service,dao里的组件类才能被spring扫描到,并且初始化对象,放入到spring的ioc容器里! 所以就意味着,主类所在的位置必须比controller,service,dao层的组件类所在的包结构的上层。


    image.png

SpringBoot的配置文件

SpringBoot的有两种格式的全局配置文件,使用任何一个功能都是一样的, 注意:
SpringBoot的全局配置文件名都是固定的application.xxx
① application.properties, 这个是默认Spring initializr默认自动生成的配置文件,也是我们属性的文件格式
示例:在properties文件中写入对象值,通过model类关联,测试

image.png

server.port=8082
server.error.path=/error
server.servlet.session.timeout=30m
#server.srvlet.context-path=/chapter02  #这里是项目名称,没有则表示为'/',若写上,表示访问时要带上该名字。
server.tomcat.uri-encoding=utf-8
server.tomcat.max-threads=500
#server.tomcat.basedir=/home/sang/tmp
book.name=三国演义    //这里写第一篇或复帽粘贴过来时容易出现中文乱码,在已设置file encodings为utf-8后,还出现乱码,再重新输入一次中文。
book.author=罗贯中
book.price=30

Book.java

@Component
@ConfigurationProperties(prefix = "book")
public class book {
    private  String name;
    private  String author;
    private Float price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                '}';
    }
}

BookController.java

@RestController
public class BookController {
    @Autowired
    book book;

    @GetMapping("/book")
    public String book1(){
        return book.toString();
    }
}

5--测试
https://localhost:8080/book回车

image.png

② application.yml,除了properties文件可以做为SpringBoot的配置文件以外,SpringBoot还支持一种我们以前没接触过的配置文件,这就是YAML配置文件
YAML文件的语法格式
① 基本格式: key: value 注意:键值对中的值前面必须有空格,多少个无所
谓,但必须有,这是语法
② 靠键左对齐来区分层级关系,也就是说凡是左对齐的键值对都是一个层次的


image.png

③ 大小写敏感,严格区分大小写的
④ 字符串默认不用引号引起来,在值里用 “不会转义特殊字符,\n会换行”,‘会转
义特殊字符,\n会输出’
⑤ 对象或Map集合的表示方法有两种,一种是用换行+缩进,另一种是利用大括号


image.png

----YAML简洁强大,是一种专门用来书写配置文件的语言,可以替代properties文件。spring-boot-starter-web依敇间接地引入了snakeyaml依赖,snakeyaml会实现对YAML配置的解析。YAML的使用非常简单,利用缩进来表示层级关系,并且大小写敏感。在springboot项目中使用YAML只需要在resources目录下创建一个xxx.yml文件即可。如:application.yml

server:
  port: 80
#  servlet:
#    context-path: /springbootvue
  tomcat:
    uri-encoding: utf-8
my:
  name: 江南一点雨
  address: chian

User.java

@Component
@ConfigurationProperties(prefix = "my")
public class User{
    private String name;
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

这里会把 yml中定义的my对象注入到User属性中。

@RestController
public class UserController {
    @Autowired
    User user;
    @GetMapping("/user")
    public String user(){
        return user.toString();
    }
}

该控制类中,用做测试我们来显示对象的属性值。
http://localhost:80/user回车

image.png

示例2:配置Map,List变量,并且在测试类中测试打印对象的值
image.png

UserZhf.java

//alt+ins键,选择产生get,set,toString方法项
@Component                              //标记为组件,放到spring的IOC容器里
@ConfigurationProperties(prefix="user")
public class UserZhf {
    private int id;
    private String username;
    private String password;
    private Date birthday;
    private boolean sex;                         //true表示男,false表示女
    private List list;                        //这是测试,实际开发中没有意义
    private Map map;
    private Address address;                      //关联对象 Address

    public Address getAddress() {
        return address;
    }
.......set方法,toString()方法

Address.java----该类上没有任何注解

public class Address {
    private int id;
    private String detail;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    @Override
    public String toString() {
        return "Address{" +
                "id=" + id +
                ", detail='" + detail + '\'' +
                '}';
    }
}

application.yml

user:
  id: 100
  username: 张三
  password: 123456
  birthday: 2022/12/31
  sex: true
  list: {aaa,bbb,ccc,ddd}
  map: {aa:cexoit,bb:xuhuifeng}
  address:
    id: 200
    detail: 江西南昌

application.properties文件中的对象配置

image.png

打印结果:

userZhfUserZhf{id=100, username='张三', password='123456', birthday=Sat Dec 31 00:00:00 CST 2022, sex=true, list=null, map={aacexoit=, bbxuhuifeng=}, address=Address{id=200, detail='江西南昌'}}

通过注解@Vuale从全局配置文件中获取数据
-----除了通过注解@ConfigurationProperties让JavaBean的所有属性和全局配置文件中
配置项建立关联关系外,我们spring提供了一个@Value注解,获取全局配置文件中的某个配置项的数据,看例子:

image.png

@Component                              //标记为组件,放到spring的IOC容器里
//@ConfigurationProperties(prefix="user")     //注释它,我们用@Value获取全局文件中配置的属性值
public class UserZhf {
    @Value("#{11+22}")
    private int id;
    @Value(value="${user.username}")
    private String username;
    private String password;
    private Date birthday;
    @Value("true")
    private boolean sex;                         //true表示男,false表示女
    private List list;                        //这是测试,实际开发中没有意义
    private Map map;
    private Address address;
-------

接下来,我们重点说一下两个注解的的区别:
@ConfigurationProperties: 是和JavaBean的所有属性绑定
@Value: 是一个一个属性绑定
@ConfigurationProperties: 不支持spring表示式的写法
@Value: 支持spring的表达式的写法,#{12+13}
@ConfigurationProperties: 支持JSR303数据校验
@Value:不支持JSR303数据校验

image.png

@ConfigurationProperties: 支持复杂的类型绑定,比如Map,List
@Value:不 支持复杂的类型绑定,比如${user.map}是读不出数据的从区别中我们可以得到这样的结论或建议:
① 当我们有JavaBean与全局配置文件里的数据对应的时候,我们就用 @ConfigurationProperties 注解
② 当我们只是需要配置文件中某一个值的时候,就用 @Value 注解
三,注解@PropertiySource读取外部属性文件
首先:我们新建一个文件user.properties如下图位置。
image.png

其次:把UserZhf.java写成如下:

@Component                              //标记为组件,放到spring的IOC容器里
@ConfigurationProperties(prefix="user")     //似乎不能注释它,要用它定到一个叫user的名字止。
@PropertySource({"classpath:user.properties"})
public class UserZhf {
    private int id;
    private String username;
    private String password;
    private Date birthday;

    private boolean sex;                         //true表示男,false表示女
    private List list;                        //这是测试,实际开发中没有意义
    private Map map;
    private Address address;
   get/set/toString方法
}

UserController.java不变
最后:测试,启动启动类,打印结果如下

2023-01-08 05:58:49.012  INFO 1104 --- [           main] c.y.spbtdemo.SpbtdemoApplicationTests    : Started SpbtdemoApplicationTests in 4.682 seconds (JVM running for 8.507)
userZhfUserZhf{id=111, username='aaa', password='123456', birthday=Mon Dec 13 00:00:00 CST 1999, sex=false, list=[aaaa, bbbb, cccc], map={gggg=tttt, uuu=kkkk}, address=Address{id=4000, detail='江西南昌市'}}

四,注解@ImportResource引入自定义spring的配置xml文件和配置类
首先:新建一个spring.xml文件,把类Address实例化放入IOC中。



    

然后:启动入口类中,加入如下

@ImportResource({"classpath:spring.xml"})
@SpringBootApplication
public class SpbtdemoApplication {

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

}

再然后:在控制类中或测试类中(写如下代码),本例是测试类中测试

@SpringBootTest
class SpbtdemoApplicationTests {
    @Autowired
    private Address address;
    @Test
    public  void getAddress() {
        System.out.println("address"+address);
    }
}

最后:启动启动类,可以看到如下结果,虽然没结果,但表时Address实例化了。

addressAddress{id=0, detail='null'}

五,Spirng Boot里的配置类
-----上面是四一种做法,但是spring boot不推荐这样子做,它推荐尽可能全部用注解完成配置,所有它使用了一种我们以前没玩儿过的“配置类”来替代我们的上面的spring.xml这种xml配置文件,具体做法:
① 定义一个类做为配置类,用这个配置类代替spring.xml,所有他们之间存在一个一一对应的关系,这里我们把Addressbean配置到IOC容器中

image.png

@Configuration                 //表明是配置类,这里我们把Addressbean配置到IOC容器中
public class MyConfig {
    @Bean
    public Address address(){
        return new Address();
    }
}

②,删除四配置的spring.xml文件,删除启动类中的@ImportResource,再同样的测试单元里看看,配置类起做用没的?
六,配置文件中使用随机值和使用变量
1、配置文件中使用随机值,看个例子就ok:user.properties.
-------在配置文件使用引用变量,如果没定义还可以设置默认值,看例子:

user.id=${random.int}
user.username=${random.value}
user.password=${random.uuid}
user.birthday=1999/12/13
user.list=aaaa,bbbb,cccc
user.map.gggg=${user.username}
user.map.uuu=${abcdef:默认值}
user.address.id=${random.int(10)}
user.address.detail=江西南昌市

2,UserZhf.java

@Component                              //标记为组件,放到spring的IOC容器里
@ConfigurationProperties(prefix="user")     //注释它,我们用@Value获取全局文件中配置的属性值
@PropertySource({"classpath:user.properties"})
public class UserZhf {

    private int id;
--------
}

3,看效果,在测试类或控制类中都可以。

@SpringBootTest
class SpbtdemoApplicationTests {
    @Autowired
    private UserZhf user;
   
    @Test
  public  void contextLoads() {
        System.out.println("userZhf"+user);
    }
    
}

在配置文件中使用Profile

----Profile ,译为“配置文件”,这种配置我们在讲Maven课程的时候,就已经遇到过了,回忆一下我们当初Maven里的配置:


                
      myProfile
      
        
          upload
          myfirstRepository
          http://124.222.48.147:8081/nexus/content/groups/public/
          
            true
          
          
            true
          
          default
        
      
     
     
        
          public
          myPlugins
          http://124.222.48.147:8081/nexus/content/groups/public/
         
            true
          
          
            true
          
          
          
                   
            
          
          
      jdk-1.8
      
       true
        jdk1.8
       
      
     1.8
     1.8
     1.8
     
    
    
                  
         

在这里的Spring Boot也是一样,我们可以配置很多个Profile,每个Profile都对应
一整个完整的全局配置,激活哪个,那个对应的全局配置就生效,具体的配置:
1,properties格式的全局配置文件的做法:
默认的application.properties文件还是不可少,但是我们可以多做几个配置文件,名字取为application-xxx.properties然后不做激活配置,默认就是使用application.properties,在application.properties做了激活配置,激活哪个,哪个生效:
我们可以在三个不同的文件中,设置不同的端口号,启动程序,看看端口号就可以看到效果了。

image.png

激活application-aaaa.properties的配置:
image.png

依次类推.....

2,yaml格式配置文件的做法,多文档块方式:
1.这样搞的话,好象现在过时了(2023年1月)但还能用。


image.png

2.这样搞还行。建了三个yml文件,分别进行了不同的配置。


image.png
application-prod.yml

# 需要部署上线的时候再用这个prod配置,记得把下面信息都改成你自己的
# 去application.yml里配置active: prod就可以运行本地prod环境
server:
  port: 443  #https加密端口号 443
  ssl: #SSL证书路径 一定要加上classpath:
    key-store: classpath:xiongshaowen.club.jks
    #SSL证书密码(密码在第一步的keystorePass.txt中)
    key-store-password: b8iun3805c8h
    #证书类型
    key-store-type: JKS
  servlet:
    context-path: /diancan

#    记得把数据库账号密码改为你服务器里mysql的账号和密码
spring:
  datasource:
    url: jdbc:mysql://localhost/diancan?characterEncoding=utf-8&useSSL=false&serverTimeZone=UTC
      &useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
    username: root
    password: xiong
    hikari:
      connection-init-sql: set names utf8mb4
    tomcat:
      init-s-q-l: SET NAMES utf8mb4 #这是最重要的一步
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update


application-test.yml

# 去application.yml里配置active: test就可以运行本地test环境
server:
  port: 8081
  servlet:
    context-path: /diancan
spring:
  datasource:
    url: jdbc:mysql://124.222.48.147/diancan?characterEncoding=utf-8&useSSL=false&serverTimeZone=UTC
      &useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
    username: root
    password: xiong
    hikari:
      connection-init-sql: set names utf8mb4
    tomcat:
      init-s-q-l: SET NAMES utf8mb4 #这是最重要的一
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update

3、除了在默认的配置文件里激活Profile以外,还可以用命令的方式激活,命令的方式激活时会忽略配置文件的激活配置
----① 在idea里配置命令行参数


image.png

[图片上传失败...(image-f4b7e2-1673822538435)]
----② 打成jar包后,启动是在启动命令后带激活命令参数


image.png

SpringBoot里的多配置文件优先级和运行时修改配置

在SpringBoot中默认会扫描好几个地方的默认配置文件:
项目的根目录/config/-----最高优先级
项目的根目录/-----第二优先级
类路径/config/-----第三优先级
类路径/-----第四优先级


image.png

如果这四个位置都有配置文件,那么四个配置文件都会生效,只不过四个配置文件中的相同配置项,生效的是高优先级的配置文件里的配置项!
----在项目已经打包运行后,我们有时候是需要修改配置的,这时还可以在jar的外面,新建一个配置文件,然后运行jar命令后面跟上 --spring.config.location=x:xxxx/application.properties,那么这个新配置文件会覆盖jar里的配置文件里的相同配置项的配置。 外面的这个配置文件优先级最最高!

image.png

SpringBoot全局配置文件里的配置项

---SpringBoot核心配置文件里可以配置的配置项,非常非常多!Spring BootReference Guide靠后的附件里看到所有配置项和说明
https://docs.spring.io/spring-boot/docs/2.7.7/reference/htmlsingle/----->https://docs.spring.io/spring-boot/docs/2.7.7/reference/htmlsingle/#appendix
① SpringBoot给我们做了很多默认配置,这些配置,具体配置在哪个文件里:
spring-boot-autoconfigure-2.0.5.RELEASE.jar里的META-INF/spring.factories/ EnableAutoConfiguration 属性里,在这个属性里指定了一大推的配置类 XxxxAutoConfiguration ,前面我们讲过,SpringBoot是用 配置类 来代替了我们在Spring中使用的xml格式的配置文件。

② 在这些配置类中都通过了一个注解 @EnableConfigurationProperties 指向了一个 XxxxxxProperties 的类,这个类又用注解 @ConfigurationProperties 关联上了我们SpringBoot的全局配置文件,从全局配置文件中读取数据!
③ SpringBoot默认写好的这些配置类是不是都在初始的状态下 已经生效?不
是 !SpringBoot里的默认的配置类里的配置项要生效都是有条件的,配置类中通过了一些列 @ConditionalXXX 注解进行判断,只有这些条件都返回true,这个配置才会起作用!


image.png

④ 我们在SpringBoot的全局配置文件中的具体配置项,其实就是前面介绍的 XxxxxxProperties 的类里的属性:


image.png

⑤ SpringBoot里有这么多默认的配置,那么那些是已经生效的,那些是没有生效的, 怎么查? 在全局配置文件application.properties/yml中设置 debug=true 运行主方法,会生成一份老长的默认配置生效的和没生效的报告:
============================
CONDITIONS EVALUATION REPORT
============================


Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.ClassProxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
      - found 'session' scope (OnWebApplicationCondition)

使用SpringBoot整合Servlet

SpringBoot和Servlet的整合,有两种玩法,第一种玩法是:
1、创建一个SpringBoot的web工程,在工程用创建一个Servlet,用注解 @WebServlet 配置Servlet映射
ALT+INSERT键去选择覆盖的方法,这里我用doGet方法。

@WebServlet(urlPatterns="/index.html")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("IndexServlet....的doget的方法被调用了");
    }
}

2、在SpringBoot的启动类上加注解@ServletComponentScan

@SpringBootApplication
@ServletComponentScan
public class SptdemoApplication {

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

}

3,测试
localhost:8080/index.html运行回车,空白没事,到控制台中我们可以看到

2023-01-19 11:01:36.557  INFO 7756 --- [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-01-19 11:01:36.557  INFO 7756 --- [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
IndexServlet....的doget的方法被调用了

第二种玩法,在SpringBoot的启动类上也不用加注解 @ServletComponentScan, 而是在启动类文件中可以用一个方法来代替前面的两个注解的作用

SpringBootApplication

public class SptdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SptdemoApplication.class, args);
    }
    @Bean        //把IndexServlet注入到IOC容器中
    public ServletRegistrationBean getMyServletBean(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new IndexServlet());
        bean.addUrlMappings("/index.html");
        return bean;
    }
}

使用SpringBoot整合filter

SpringBoot整合filter,和整合servlet类似,也有两种玩儿法
一,第一种方法
1、创建一个SpringBoot工程,在工程中创建一个filter过滤器,然后用注解 @WebFilter

image.png

上图extedns改为implements,因为Filter是一个接口,ALT+INSERT键去选择要实现的方法,这里三个方法全选中。

@WebFilter(filterName = "myFilter",urlPatterns={"/index.html"})  //可以拦截很多内容,用逗号隔开,这里我只拦截index.html
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter拦截器进来了。。。。");
        filterChain.doFilter(servletRequest,servletResponse);  //放行
        System.out.println("MyFilter拦截器进来了.....");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}

2、启动类还是使用 @ ServletComponentScan 注解来扫描拦截器 注解 @WebFilter

@SpringBootApplication
@ServletComponentScan
public class SptdemoApplication {

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

3,localhost:8080/index.html回车后,控制台显示,说明刚开始是拦截了,但又放行了。

MyFilter拦截器进来了。。。。
IndexServlet....的doget的方法被调用了
MyFilter拦截器进来了.....

二,另一种玩儿法,和Servlet一样也是做一个方法,来替代上面的两个注解的作用:

//拦截器类中没有@WebFilter注解
//@WebFilter(filterName = "myFilter",urlPatterns={"/index.html"})  //可以拦截很多内容,用逗号隔开,这里我只拦截index.html
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter拦截器进来了。。。。");
        filterChain.doFilter(servletRequest,servletResponse);  //放行
        System.out.println("MyFilter拦截器进来了.....");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}




//启动类中,没有了@ServletComponentScan注解
@SpringBootApplication

public class SptdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SptdemoApplication.class, args);
    }
    @Bean        //把IndexServlet注入到IOC容器中
    public ServletRegistrationBean getMyServletBean(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new IndexServlet());
        bean.addUrlMappings("/index.html");
        return bean;
    }
    @Bean
    public FilterRegistrationBean getFilterBean(){
        FilterRegistrationBean bean = new FilterRegistrationBean(new MyFilter());
        bean.addUrlPatterns("/index.html");
        return bean;
    }
}

问题:有时,拦截器配置拦截有所url地址的时候/*,会出现连续拦截两次的情况,原因是因为浏览器发出访问了图标favicon.ico的请求,本人还没遇到这种情部况
处理办法:

image.png

使用SpringBoot整合Listener监听器

常用的Web事件的监听接口如下:
ServletContextListener:用于监听Web的启动及关闭
ServletContextAttributeListener:用于监听ServletContext范围内属性的改变
ServletRequestListener:用于监听用户请求
ServletRequestAttributeListener:用于监听ServletRequest范围属性的改变
HttpSessionListener:用于监听用户session的开始及结束
HttpSessionAttributeListener:用于监听HttpSession范围内的属性改变

第一种方法,例:web系统初始化的监听
1.新建一个监听器

image.png

2.启动类中加@ServletComponentScan注解
3.测试效果

2023-01-19 12:17:18.509  INFO 7208 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 605 ms
系统初始化了!。。。。。
2023-01-19 12:17:18.703  INFO 7208 --- [ 

第二种方法
1.去掉第一种方法中的两个注解@WebListener和@ServletComponentScan.
2.启动类中,加一个方法,把监听器对象注入到IOC容器中。

image.png

SpringBoot访问web中的静态资源

总体来讲SpringBoot访问web中的静态资源,有两个方式:

  1. SpringBoot默认指定了一些固定的目录结构,静态资源放到这些目录中的某一个,
    系统运行后浏览器就可以访问到
    ① 关键是SpringBoot默认指定的可以存放静态资源的目录有哪些?
    a. classpath:/META-INF/resources/
    b. classpath:/resources/
    c. classpath:/static/ 这个是工具自动帮我们生成目录,用的最多的目录
    d. classpath:/public/
    e. / 当前项目的跟路径
    f. src/main/webapp/
    ----当一个index.html是自建的话,放进/static/下后,启动系统时,只输入ip+端口号后,回车,会显示它。但当动态控制类中有返回的 index.html时,会优先访问。
    ----本人一般不会去改变这些目录,一般把静态资源放在static下。
    ② 这些默认的目录是可以在全局配置文件中修改,修改后,除配置的目录以外其他目录就不可以再访问静态资源了:
    spring.resources.static-locations=classpath:resources,classpath:static
    ③ SpringBoot默认的首页是放在任一个静态资源目录下的index.html
    ------当然了,如果有动态index.html,则会显示它,不会显示静态的的index.html.
    ④ SpringBoot默认的web页面图标是放在任一静态资源目录下的favicon.ico
    我们在这里目录下选两个放一个index.html和一张图片实验一下就ok!
    ico图片我们可以在网上搜ico在线制作,即可找到相应的网站,我们制一个即可
    2、把静态资源打成jar包引入系统后供访问
    http://www.webjars.org 这个网站上提供了常用的静态资源的jar包的maven依赖:
    image.png

    把依赖配置到maven的pom.xml中,就可以在 网站根目
    录/webjars/jquery/1.12.4/jquery.js 访问到资源!
    http://localhost:8080/webjars/jquery/1.12.4/jquery.js
    image.png

SpringBoot整合web中使用jsp

SpeingBoot官方是不推荐使用jsp这个引擎模板的,所有它的默认配置中是没有配置jsp支持的,但是jsp应该是我们学习JavaWeb技术以来最熟悉的视图引擎,依赖性还是很强,还是来讲讲怎么在SpringBoot中整合它:
1、在pom.xml文件中导入jsp依赖的jar包,一个是jstl标签,一个是jsp的引擎


        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        

        
        
            org.apache.taglibs
            taglibs-standard-spec
            1.2.5
        
        
            org.apache.taglibs
            taglibs-standard-impl
            1.2.5
        
        
            org.apache.tomcat.embed
            tomcat-embed-jasper
          
            9.0.64   
        

2、在SpringBoot的全局配置文件中修改SpringBoot的默认视图解析器的前缀和后缀。spring.mvc.view相当天src/main/webapp目录。webapp下有WEB-INF目录,它下面我们又建jsp目录,以便存放jsp视图。

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

image.png

注意:要把webapp目录添加到springboot的web服务中。
image.png

3,控制层中与jsp中的代码
IndexController.java

@Controller
public class IndexController {
    @GetMapping("/index")
    public String index(Model model){
        model.addAttribute("aaa","jsp视图引擎!!");
        return "index";
    }
}

index.jsp----用到了jstl标签与EL

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    jsp测试


   jsp首页 ${12+12}  
aaa的值: ${aaa}

测试
http://localhost:8080/index

image.png

SpringBoot整合Freemarker(类似jsp视图)

Freemarker和jsp一样是一个视图的引擎模板,其实所有的模板引擎的工作原理都是类似的,如下图:

image.png

SpringBoot默认就支持这个模板,下面看看怎么把他们整合在一起:
中文在线手册http://freemarker.foofun.cn/dgui_quickstart_basics.html
1、配置freemarker的启动器


        org.springframework.boot
        spring-boot-starter-parent
        2.0.4.RELEASE   


   org.springframework.boot
   spring-boot-starter-freemarker

image.png

2、编写controller类和Model类
User.java

public class User {
    private int id;
    private String username;
    private String password;

    public int getId() {
        return id;
    }

    public User() {
    }

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
-------------

IndexController.java

@Controller
public class IndexController {
    @RequestMapping(value="/index.html",method= RequestMethod.GET)
    //@GetMapping("/index.html")
    public String index(Model model){
        List users = new ArrayList();
        users.add(new User(1,"aaa","aaa123"));
        users.add(new User(2,"bbb","bbb123"));
        users.add(new User(3,"ccc","ccc123"));
        model.addAttribute("users",users);   //把users注入的视图中
        return "users";             //返回到一个视图中
    }
}

3,编写ftl模板文件,注意:模板文件必须放在src/resources/templates目录下
users.ftl



    
    freemarker视图模板


    

<#list users as user> 用户id: ${user.id} 用户名: ${user.username} 用户密码: ${user.password}

4,测试 http://localhost:8080/index.html
----freemarker常用的标签语法
<1>freemarker的标签种类

${..}:FreeMarker will replace it in the output with the actual value of the thing in the
curly brackets. They are called interpolation s.
<#.. , 代表是 FTL tags ( FreeMarker Template Language tags ) , hey are instructions to
FreeMarker and will not be printed to the output
<#if ...>
<#list totalList as elementObject>...
<@ , 代表用户自定义的标签
<#-- --> 注释标签,注意不是 

<2>一些特殊的指令:

r 代表原样输出: ${r"C:\foo\bar"}
<#list ["winter", "spring", "summer", "autumn"] as x>${x}
?引出内置指令
String 处理指令:
html : 特殊的 html 字符将会被转义,比如 "<" ,处理后的结果是 <
cap_first 、 lower_case 、 upper_case
cap_first: 将字符串的第一个字符或者字母 ( 仅前几个字符是空格的情况 ) 大写 ( 如果第一个字符是字母 );
  如果字符串的第一个字符不是字母 ( 空格除外 ) ,将按照原来字符串的格式返回 ; 若第一个字符是字母并且是大写的情况,结果同上。
trim : 除去字符串前后的空格
sequences 处理指令
    size :可以用于返回 list 集合的元素个数
numbers 处理指令
    int : number 的整数部分, (e.g. -1.9?int is -1)

举例:
1.r,#list的用法。


image.png
用户id: 1 用户名: aaa 用户密码: aaa123 用户id: 2 用户名: bbb 用户密码: bbb123 用户id: 3 用户名: ccc 用户密码: ccc123

c:\foo\bar

winter
spring
summer
autumn

2.?的用法,先用assign定义一个变量aaa,再显示。

<#assign aaa="

xiongshaowen

"/> ${aaa} ${aaa?html} ${aaa?upper_case} ${users?size} ${125.3658?int}

结果:


image.png

<3>对于null,freemarker会报错处理

! :默认值操作符,语法结构为: unsafe_expr ! default_expr ,
    比如 ${mouse!"No mouse."} 当 mouse 不存在时,返回 default value ;
   (product.color)!"red" 这种方式,能够处理 product 或者 color 为 missvalue 的情况;
   而 product.color!"red" 将只处理 color 为 miss value 的情况
?? : Missing value test operator , 测试是否为 missing value
   unsafe_expr?? : product.color?? 将只测试 color 是否为 null
  (unsafe_expr)?? : (product.color)?? 将测试 product 和color 是否存在 null

举例:
1.设默认值

${mouse!"xiongshaowen"}

2.判断是否为空

<#if mouse??>
    Mouse found
<#else>
    No mouse found

No mouse found

<#assign mouse="xiong">
<#if mouse??>
    Mouse found
<#else>
    No mouse found

mouse found

<3>分支语句
1.if分支

语法:
<#if condition>
...
<#elseif condition2>
...
<#elseif condition3>
...
<#else>
...

例子:
<#if x = 1>
x is 1

---------------------------------
<#if x = 1>
x is 1
<#else>
x is not 1

2.switch分支

语法:
<#switch value>
   <#case refValue1>
    ...
   <#break>
   <#case refValue2>
   ...
   <#break>
   <#case refValueN>
   ...
   <#break>
  <#default>
    ...

举例:

<#assign size="large"/>
<#switch size> 
    <#case "small">
        This will be processed if it is small
        <#break>
    <#case "medium">
        This will be processed if it is medium
        <#break>
    <#case "large">
        This will be processed if it is large
        <#break>
    <#default>
        This will be processed if it is neither

<4>list循环,它可以用用if语句跳出循环。

<#list sequence as item>
   ...
   <#if item = "spring"><#break>
  ...

举例:

<#assign seq = ["winter", "spring", "summer", "autumn"]>
<#list seq as x>
    ${x_index + 1}. ${x}<#if x_has_next>,
----------------------------------------------结果------------------------------------------------------------------------------------ 1. winter, 2. spring, 3. summer, 4. autumn

关键字:item_index: 是 list 当前值的下标,从 0 开始 item_has_next: 判断 list 是否还有值

<5>macro, nested, return宏的应用

语法
<#macro name param1 param2 ... paramN>
   ...
   <#nested loopvar1, loopvar2, ..., loopvarN> //有了这和标签:调用宏的时候,必须用双标签
   ...
  <#return>
  ...

宏举例应用:先定义宏,再调用宏,宏里面可以有html标签,这样的话我们可以把一系列标签放在一起重复利用。

<#macro test foo bar="Bar" baaz=-1>
    Test text, and the params: ${foo}, ${bar}, ${baaz}

<@test foo="a" bar="b" baaz=5*5-2/> <@test foo="a" bar="b"/> <@test foo="a" baaz=5*5-2/> <@test foo="a"/> ---------------------------------------------------------------------结果---------------------------------------------------------------- Test text, and the params: a, b, 23 Test text, and the params: a, b, -1 Test text, and the params: a, Bar, 23 Test text, and the params: a, Bar, -1

循环的宏


<#macro list title items> ${title?cap_first}:
<#list items as x> *${x?cap_first}
<@list items=["mouse", "elephant", "python"] title="Animals"/> ---------------------------------------------------------------------结果---------------------------------------------------------------- Animals: *Mouse *Elephant *Python

包含body 的宏

image.png

上图中的1..count as x表示从1到count(传来了值5)的循环,contant等是自定义的名字



<#macro repeat count> <#list 1..count as x> <#nested x, x/2, x==count>
<@repeat count=5; contant,contant_half,is_last> 有一个有body的宏,宏里给我传来了三个值: ${contant},${contant_half},<#if is_last> 这是最后一个值 ----------------------------------------------------------------结果----------------------------------------------- 有一个有body的宏,宏里给我传来了三个值: 1, 0.5, 有一个有body的宏,宏里给我传来了三个值: 2, 1, 有一个有body的宏,宏里给我传来了三个值: 3, 1.5, 有一个有body的宏,宏里给我传来了三个值: 4, 2, 有一个有body的宏,宏里给我传来了三个值: 5, 2.5, 这是最后一个值


<#macro repeat count> <#list 1..count as x> <#nested x, x/2, x==count>
<#if x==3> <#return> <@repeat count=5; contant,contant_half,is_last> 有一个有body的宏,宏里给我传来了三个值: ${contant}, ${contant_half},<#if is_last> 这是最后一个值 ----------------------------------------------------------------结果----------------------------------------------- 有一个有body的宏,宏里给我传来了三个值: 1, 0.5, 有一个有body的宏,宏里给我传来了三个值: 2, 1, 有一个有body的宏,宏里给我传来了三个值: 3, 1.5,

<6>include关键字

语法:
<#include filename options>
options包含两个属性:
    encoding="GBK" 编码格式;
    parse=true 是否作为ftl语法解析,默认是true,false就是以文本方式引入

举例:在user.ftl同目录下建一个copyright.ftl文件,内容如下
copyright.ftl

Copyright 2018-2023 ${me} 
All rights reserved.

user.ftl加如下内容


include的应用
<#assign me="江西南昌市xxx公司"/> <#include "./copyright.ftl" encoding="UTF-8"/> ----------------------------------------------------------------------------效果------------------------------------------------------------- include的应用 Copyright 2018-2023 江西南昌市xxx公司 All rights reserved.

《7》Import关键字
语法
<#import path as hash>
类似于 java 里的 import, 它导入文件,然后就可以在当前文件里使用被导入文件里的宏组件
用例假设 mylib.ftl 里定义了宏 copyright 那么我们在其他模板页面里可以这样使用

<#import "/libs/mylib.ftl" as my>
<@my.copyright date="1999-2002"/>
<#-- "my"在freemarker里被称作namespace -->

举例:
-------先在mylib.ftl中定义如下内容(宏的定义,mmm为宏名,pp为它的一个参数用于传值)

<#macro mmm pp="abc">
    mmm宏被调用了,传进来的参数pp的值是:${pp}

-------然后在引入的文件中加入如下内容(users.ftl中)


import的引入mylib.ftl的定义的mmm宏

<#import "./mylib.ftl" as my/> <@my.mmm pp="123"/> ----------------------------------------------------------------------结果------------------------------------------------------------------- import的引入mylib.ftl的定义的mmm宏 mmm宏被调用了,传进来的参数pp的值是:123

《8》compress关键字
语法
<#compress>
...

----用来压缩空白空间和空白的行,这里页面显示没有效果,但在源文件代码中可以看到效果。

《9》escape, noescape
语法
<#escape identifier as expression>
...
<#noescape>...
...

-------主要使用在相似的字符串变量输出,比如某一个模块的所有字符串输出都必须是 html 安全的,这个时候就可以使用,说白了 escape 包裹的内容,会被转义比如<>会编程 <> 而noescape noescape包裹的字符不会被转义,会被当成html代码执行

<#escape x as x?html>
    First name: ${firstName}
  <#noescape> Last name: ${lastName} 
   Maiden name: ${maidenName}

等同于:
First name: ${firstName?html}
Last name: ${lastName}
Maiden name: ${maidenName?html}

<10>assign语法

1.<#assign name=value>
2.<#assign name1=value1 name2=value2 ... nameN=valueN>
3.<#assign name>
      capture this
  
4.给aaa赋予序列值(数组一样)
  <#assign aaa= ["winter", "spring", "summer", "autumn"]>
5.给变量 test 加 1
  <#assign test = test + 1>
6.给 my namespace namespace 赋予一个变量 bgColor, 下面可以通过 my.bgColor 来访问这个变量
   <#import "/mylib.ftl" as my>
   <#assign bgColor="red" in my>
   ${my.bgcolor}
//这样输出的

举例:以3为例,将一段输出的文本量保存在 xx 变量里。


assign应用
<#assign xx> Copyright 2018-2023 江西南昌市xxx公司 All rights reserved.

assign又标签定义局部变量的语法测试

assign双标签定义局部变量的语法测试大大点点滴滴

assign又标签定义局部变量的语法测试

${xx}
image.png

《11》global语法,global可以跨越命名空间的。

1.<#global name=value>
2.<#global name1=value1 name2=value2 ... nameN=valueN>
3.<#global name>
     capture this
  
全局赋值语法,利用这个语法给变量赋值,那么这个变量在所有的 namespace 中是可见的 , 如果这个变量被当前的 assign 语法覆盖 
如 <#global x=2> <#assign x=1> 在当前页面里 x=2 将被隐藏,或者通过 ${.globals.x} 来访问

举例:在mylib.ftl中定义两个变理,aaa为assign变理,ggg为global变量(全局),在users.ftl中分别输出之,注意他们的用法,一个要用到命名空间的名。

<#assign aaa="aaa">
<#global ggg="ggg">

users.ftl


import的引入mylib.ftl的定义的mmm宏

<#import "./mylib.ftl" as my/> ${my.aaa} ${ggg} ---------------------------------------------------------------------------结果-------------------------------------------------------------- aaa ggg

<12>setting
语法
<#setting name=value>
用来设置整个系统的一个环境
locale
number_format
boolean_format
date_format , time_format , datetime_format
time_zone
classic_compatible, 默认值 false ,改成 true , ${aaa}
举例1:设置数字为百分比显示,如1显示100%,10显示1000%


setting的应用,下面的dd是由IndexController.java注入进来的--model.addAttribute("dd",new Date());?datetime告诉freemarker这个dd是时间日期变量
<#setting number_format="percent"/> ${1} <#setting date_format="yyyy-MM-dd HH:mm:ss"> ${dd?datetime} ---------------------------------------------------------------------------结果-------------------------------------------------------------- 100% 2023-2-15 11:14:55

<13>t, lt, rt 只影响源码,不影响页面显示。
<#t> 去掉左右空白和回车换行
<#lt>去掉左边空白和回车换行
<#rt>去掉右边空白和回车换行


1 <#t>
2<#t>
3<#lt>
4
5<#rt>
6

------一些常用方法或注意事项

表达式转换类
${expression} 计算 expression 并输出
#{ expression } 数字计算 #{ expression ;format} 安格式输出数字 format 为 M 和 m
M 表示小数点后最多的位数 ,m 表示小数点后最少的位数如 #{121.2322;m2M2} 输出 121.23
数字循环


1..5 表示从 1 到 5 ,原型 number..number
给变量默认值
${var?default("hello world")?html} 如果 var is null 那么将会被 hello world 替代


解决输出中文乱码问题:
freemarker 乱码的原因:
没有使用正确的编码格式读取模版文件 , 表现为模版中的中文为乱码
解决方法:在 classpath 上放置一个文件 freemarker.properties ,在里面写上模版文件的
  编码方式,比如default_encoding=UTF-8
locale=zh_CN
注意: eclipse 中除了 xml 文件、 java 文件外,默认的文件格式 iso8859-1


提高 freemarker 的性能
在 freemarker.properties 中设置:
template_update_delay=60000
避免每次请求都重新载入模版,即充分利用 cached 的模版


关于输出的一些问题
对于数值,会自动根据 local 确定格式,可以 "?c", 比如, Details..., 因此这里的 id 是? c 于数字转换为字符串,不会进行
格式化,注意 ?c 只对数值有效,
对于日期,会使用默认的日期格式转换,因此需要事先设置好默认的转换格式,包括
date_format , time_format , datetime_format
对于布尔值,不能输出,会报错并停止模版的执行,比如 ${a == 2} 会出错,但是 可
以 foo?string("yes","no") 来进行

SpringBoot中使用Thymeleaf模板引擎

和使用freemarker差不多的方式:
1、导入thymeleaf的启动器


  org.springframework.boot
  spring-boot-starter-thymeleaf

2、编写Controller类(IndexController.java)和模块类(User.java)
3、编写模板页面(扩展名为html), 注意:模板文件必须放在src/resources/templates目录下
①加上名称空间,加后就会有thymeleaf的代码提示

②使用thymeleaf标签实现显示数据
每一种视图引擎模板,都有最基本的功能,变量的输出
强调的知识点:
1.thymeleaf的输出和前面的freemarker,jsp都不一样,它们可在body中直接使用类似EL输出,但在这不能这样独立
使用${}输出,要么是依附在某一个标签上,写在标签属性位置上,要么写在双中括号中。
2.写thymeleaef标签时会暴红,这是没有代码提示与自动补全,这时我们要在标签中写上thymeleaf的命名空间网址

image.png
用户名id: 用户名称: 用户密码:

4、thymeleaf的常用标签语法总结:
①变量输出和字符串操作

th:text     在页面上输出值,会把特殊字符进行转义后输出,注意: [[ ]] 和 th:text 等价
th:utext    在页面上输出值,不会把特殊字符转义,注意: [()] 和 th:utext 等价
th:value    在 input 标签中显示数值  xiongshaowen");
---------------------------------------------------------------html页面---------------------------------------------------------------------


image.png

5,(符号),在thymeleaf中表示调用内置对象,dates,strings。。。。下面就通过内置对象stirngs对字符串的一些常用操作说明:
image.png


字符串的操作,利用控制层注入的str
判断是否为空
image.png

时间日期的格式化,利用制制层类IndexController.java注入到视图的时间对象dd
------------------------------------------------------------结果------------------------------------------------- 时间日期的格式化,利用制制层类IndexController.java注入到视图的时间对象dd 2023年2月15日 下午07时30分34秒

③条件分支标签
IndexController.java中注入两个变量sex,id

@Controller
public class IndexController {
   // @RequestMapping(value="/index.html",method= RequestMethod.GET)
    @GetMapping("/index.html")
    public String index(Model model){
        model.addAttribute("sex","女");
        model.addAttribute("id",3);
        return "users";             //返回到一个视图中
    }
}

users.html

th:if

   性别:女

th:switch
id 为 1 id 为 2 id 为 3
----------------------------------------------------------------结果--------------------------------------------- 性别:女 th:switch id 为 3

④迭代
普通迭代,即控制层注入对象到list集合中,遍历List集合。
IndexController.java

@GetMapping("/index.html")
    public String index(Model model){
        List users = new ArrayList();
        users.add(new User(1,"aaa","aaa123"));
        users.add(new User(2,"bbb","bbb123"));
        users.add(new User(3,"ccc","ccc123"));
        model.addAttribute("users",users);   //把users注入的视图中
        return "users";
}

users.html

用户ID 用户名 用户密码

结果:

用户ID    用户名     用户密码
1           aaa     aaa123
2           bbb     bbb123
3           ccc     ccc123

状态变量属性



  
  
  
   当前循环的索引,从0开始
   当前循环的次数,从1开始
   被循环的集合或数组的长度
   布尔值,当前循环是偶数? 从0开始
   布尔值,当前循环是奇数? 从0开始
   布尔值,当前循环是不是第一条,是返回true
   布尔值,当前循环是不是最后一条,是返回true

-------------------------------------------------------------------------------------------------------------------
1   aaa     aaa123  0   1   3   false   true    true    false
2   bbb     bbb123  1   2   3   true    false   false   false
3   ccc     ccc123  2   3   3   false   true    false   true

迭代Map型的集合
IndexController.java

@GetMapping("/index.html")
    public String index(Model model){
        Map maps = new HashMap();
        maps.put("001",new User(1,"aaa","aaa123"));
        maps.put("002",new User(2,"bbb","bbb123"));
        maps.put("003",new User(3,"ccc","ccc123"));
        model.addAttribute("maps",maps);
        return "users";             //返回到一个视图中
    }
}

users.html

用户ID 用户名 用户密码

⑤域对象操作
HttpServletRequet:

request.setAttribute("req", "HttpServletRequest")
Request:

HttpSession:

request.getSession().setAttribute("sess", "HttpSession");
Session:

ServletContext:

request.getSession().getServletContext().setAttribute("app","Applic
ation");
Application:

⑥URL 表达式
用在th:href标签或th:src标签上
url 表达式基本语法:@{}
URL 类型
a、绝对路径
绝对路径
b、相对路径
1)相对于当前项目的根,相对于项目的上下文的相对路径
相对路径

  1. 相对于服务器路径
    相对于服务器的根
    c、 在 url 中实现参数传递
    相对路径-传参
    d、 在 url 中通过 restful 风格进行参数
    相 对 路径 - 传 参-restful
    举例:

URL表达式的应用(用在th:href标签或th:src标签上)
绝对路径
绝对路径 相对路径
1)相对于当前项目的根,相对于项目的上下文的相对路径
相对路径 2) 相对于服务器路径
相对于服务器的根 传参数

相对路径传参 相对路径-传参-restful

image.png

若我们在全局配置文件中,在服务器根目录下加相对目录abc
image.png

http://localhost:8080/abc/index.html回车
image.png

所以,我们推荐开发中使用thymeleaf视图模板,因为更改相对目录或转移服务器后,会自动给我们增加相应的目录,十分方便

你可能感兴趣的:(SpringBoot基础篇)