[Java框架]SpringBoot框架

目录

简介

特点

创建步骤

配置热部署

启动器入门

YAML/YML文件

读取spring boot配置文件

SpringBoot基本设置

对象管理

整合mybatis

整合mybatisplus

wrapper

lambda wrapper

整合JSP

Thymeleaf

引入thymeleaf

语法规则

标准表达式语法

文本操作

注释

运算符

循环

条件

定义局部变量

内联表达式

th:inline

整合Redis

Redis事务

设置二级缓存

springboot监控

Monitor监控页面

spring boot聚合工程

整合Shiro


简介

众所周知 Spring 应用需要进行大量的配置,也一度被称为“配置地狱”。 为了简化 Spring 应用的搭建和开发过程,在 Spring 基础上提供了一套全新的开源的框架 —— Spring Boot。 Spring Boot 具有 Spring 一切优秀特性,而且使用更加简单,功能更加丰富,性能更加稳定而健壮。随着近些年来微服务技术的流行,Spring Boot 也成为了时下炙手可热的技术。

特点

  1. Spring Boot 可以以 jar 包的形式独立运行,只需通过命令“ java–jar xx.jar” 即可运行。
  2. Spring Boot 内嵌 Servlet 容器,应用无需打成 WAR 包
  3. Spring Boot 提供了一系列的“starter”项目对象模型(POMS)来简化 Maven 配置。
  4. Spring Boot 提供了大量的默认自动配置,来简化开发,也可通过配置文件修改默认配置。
  5. Spring Boot自带应用监控可以对正在运行的项目提供监控。
  6. Spring Boot 不需要任何 xml 配置即可实现 Spring 的所有配置。

创建步骤

Maven和Spring Initializr:都是用于构建Spring Boot项目的工具。Maven提供了更多的自定义选项和灵活性,适用于需要更多配置和自定义的项目。而Spring Initializr则提供了快速创建Spring Boot项目的便利性,适用于简单和快速开始的项目。

maven创建:1.新建maven工程,选择JDK版本 2.填写工程名,存放路径、maven坐标等 3.导入spring boot依赖 4.编写启动类

Initializr创建:1.选择Spring Inittializr,填写工程存放路径,maven坐标等,选择JDK版本 2.选择spring boot版本和组件(DevTools和Web必须)

版本对应:spring boot 2.x <> JDK 8.0及以上;spring boot 3.x <> JDK 14.0以上。

maven依赖:

<!--继承springboot的父工程-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version>
    </parent>
    <!--引入web依赖 spring+springmvc-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <!--项目打jar包必要插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

启动类说明:1.不能直接放在main/java文件夹下; 2.启动类所在的包是最顶部的包。 springBoot默认包扫描机制:默认扫描启动类所在的包同级文件和子包下的文件。

/*注解说明:该注解是组合注解
@SpringBootConfiguration   用来自动配置spring相关环境  spring+springmvc
@EnableAutoConfiguration   开启自动配置 核心注解
@ComponentScan          组件扫描   只能扫描当前包和子包
*/
@SpringBootApplication
public class HelloSpringBoot {
    public static void main(String[] args) {
        SpringApplication.run(HelloSpringBoot.class, args);
    }
}

配置热部署

开启热部署可以提高开发效率,一般使用spring-boot-devtools,也可以使用 JRebel插件。

spring-boot-devtools配置热部署:

1.导入依赖

<dependency>
 <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

<!--如果devtools不生效,进行添加-->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork> <!-- 如果devtools不生效  请设置该属性 -->
            </configuration>
        </plugin>
    </plugins>
</build>

2.“File” > “Settings” > “Build, Execution, Deployment” > “Compiler” 菜单下的右侧面板中勾选“Build project automatically”选项来启用自动构建

3. 在主菜单中选择 “Run” > “Edit Configurations”,点击 “+ " 添加配置并选择"Spring Boot”,在该配置下的 “Configuration” 标签页中将 “On frame deactivation” 选项设置为 “Update classes and resources”

4.setting >Advanced Settings 勾选Compiler的Allow auto-make to start even if developed application is currently running

启动器入门

Spring Boot 将日常企业应用研发中的各种场景都抽取出来,做成一个个的 starter(启动器),starter 中整合了该场景下各种可能用到的依赖,用户只需要在 Maven 中引入 starter 依赖,SpringBoot 就能自动扫描到要加载的信息并启动相应的默认配置。starter 提供了大量的自动配置,让用户摆脱了处理各种依赖和配置的困扰。所有这些 starter 都遵循着约定成俗的默认配置,并允许用户调整这些配置,即遵循“约定大于配置”的原则。并不是所有的 starter 都是由 Spring Boot 官方提供的,也有部分 starter 是第三方技术厂商提供的。

spring-boot-starter-parent 是所有 Spring Boot 项目的父级依赖,它被称为 Spring Boot 的版本仲裁中心,可以对项目内的部分常用依赖进行统一管理。

YAML/YML文件

特点:

  • yml文件以缩进代表层级关系
  • 缩进不允许使用tab只能使用空格
  • 空格的个数不重要,只要相同层级的元素左对齐即可
  • 大小写敏感
  • 数据格式为,名称:(空格)
  • 字符串不需要使用双引号或单引号圈起来,如果数据里出现转义字符时需要双引号
  • YAML 仅支持单行注释,即在注释文本前使用(空格)#,# 后面的字符均为注释的内容

YAML插件:在settings>plugins 下载Convert YAML and Properties File,可以.properties、.yml文件相互转换。

消除yaml文件红色警告:导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

读取spring boot配置文件

1.基本属性的注入:在Spring中使用@Value可以对单个属性进行注入配置

2.对象的注入:有很多配置属性或者配置属性本身拥有层级结构时 @ConfigurationProperties("prefix") 将配置属性和一个Bean及其属性关联,从而实现类型安全配置。例:

//1.层级关系
user:
  name: lisi
  age: 20
  birth: 2021/11/24


//2.对象注入java类,需要有set方法,prefix=user
@Controller
@RequestMapping("xx")
@ConfigurationProperties("user")
@Data
public class InjectController2 {
    private String name;
    private Integer age;

    @RequestMapping("x")
    @ResponseBody
    public String inject(){
        System.out.println(name+age);
        return  "ok";
    }
}

SpringBoot基本设置

spring boot常见配置文件有三种:.properties、.yml、.yaml

优先级:properties>yml(常用)>yaml

不同配置文件的相同配置按优先级相互覆盖,不同配置全部保留。

在application.yml进行配置:1.设置服务器端口号 2.配置文件的拆分 3.配置日志的设置 等等

对象管理

1.使用@Configuration注解添加在配置类上,该类作为一个配置类,相当于spring的配置文件,该注解只能使用在类上。在配置类中方法上使用@Bean注解,相当于spring配置文件中的bean标签

2.使用原始的spring注解 @Component @Controller @Service @Repository

整合mybatis

步骤

1.导入依赖

        <!--mybatis-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.18</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.18</version>
        </dependency>
        <!--分页查询-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

2.yml配置数据库、mybatis、druid、分页:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/springboot?serverTimezone=UTC&characterEncoding=utf-8
    #德鲁伊连接池
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 5
      max-active: 20
      #获取连接时最大等待时间,单位毫秒。
      max-wait: 60000
      #有两个含义:
      #1) Destroy线程会检测连接的间隔时间
      #2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      #用来检测连接是否有效的sql,要求是一个查询语句。
      #如果validationQuery为null,testOnBorrow、testOnReturn、
      #testWhileIdle都不会其作用。
      validation-query: SELECT 1
      #执行validationQuery检测连接是否有效
      test-while-idle: true
      #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      test-on-borrow: false
      #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      test_on_return: false
      #是否缓存preparedStatement
      #在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。
      pool_prepared_statements: true
      #监控统计用的filter:stat
      #日志用的filter:log4j
      #防御sql注入的filter:wall
      filters: stat,log4j,wall
      #连接大小
      max_pool_prepared_statement_per_connectionsize: 20
      #合并多个DruidDataSource的监控数据
      use_global_data_source_stat: true
      #连接数据库的属性集合对象,该对象是 Properties 类的示例对象
      connection_properties: druid.stat.mergeSq
      filter:
        # 开启druiddatasource的状态监控
        stat:
          enabled: true
          db-type: mysql
          # 开启慢sql监控,超过2s 就认为是慢sql,记录到日志中
          log-slow-sql: true
          slow-sql-millis: 2000
        # 日志监控,使用slf4j 进行日志输出
        slf4j:
          enabled: true
          statement-log-error-enabled: true
          statement-create-after-log-enabled: false
          statement-close-after-log-enabled: false
          result-set-open-after-log-enabled: false
          result-set-close-after-log-enabled: false
      ########## 配置WebStatFilter,用于采集web关联监控的数据 ##########
      web-stat-filter:
        enabled: true # 启动 StatFilter
        url-pattern: /*  # 过滤所有url
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" # 排除一些不必要的url
        session-stat-enable: true # 开启session统计功能
        session-stat-max-count: 1000 # session的最大个数,默认100
      ########## 配置StatViewServlet(监控页面),用于展示Druid的统计信息 ##########
      stat-view-servlet:
        enabled: true # 启用StatViewServlet
        url-pattern: /druid/* # 访问内置监控页面的路径,内置监控页面的首页是/druid/index.html
        reset-enable: false # 不允许清空统计数据,重新计算
        login-username: root # 配置监控页面访问密码
        login-password: 123
        allow: 127.0.0.1 # 允许访问的地址,如果allow没有配置或者为空,则允许所有访问
        deny: # 拒绝访问的地址,deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝

mybatis:
  mapper-locations: classpath:mapper/*.xml  #设置mapper文件的位置
  type-aliases-package: com.example.springboot01.entity # 起别名
  configuration:
    map-underscore-to-camel-case: true #开启驼峰命名



  # pageHelper分页配置
pagehelper:
  helper-dialect: mysql  #数据库类型
  reasonable: true   #分页合理化 page<1 查询第一页 page >pageNumber 查询最后一页
  support-methods-arguments: true  # 支持mapper接口传递参数开启分页
  params: count=countSql  #用于从对象中根据属性名取值

3.启动类添加注解

@MapperScan("com.xx.springboot.mapper")//扫描dao接口所在的包 同时生成代理对象 

整合mybatisplus

MybatisPlus可以节省大量时间,所有的CRUD代码都可以自动化完成 MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。mybatisplus适合单表,多表这种复杂的sql还是需要mybatis。

尽量不要同时导入mybatis和mybatis_plus,可能会有版本冲突

1.导入依赖

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>

2.配置文件yml配置连接数据库的配置(),并在启动类上添加@MapperScan

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/springboot?serverTimezone=UTC&characterEncoding=utf-8

3.编写mapper、service、entity层代码,测试使用

mapper接口类继承BaseMapper<?>,service接口类继承IService<?>,serviceImpl实现类继承ServiceImpl<xxMapper, xx>实现service接口,实体类使用@TableName、@TableId、@TableField 映射数据表、主键、普通字段。其中,@TableId 注解必须要配置

 插入数据时id很大的解决:设置实体类里主键字段@TableId(type = IdType.AUTO),然后设置自增长,运行 alter table user AUTO_INCREMENT=10;重置自增长。

默认使用驼峰命名映射下划线:User》user、userId》user_id、username》user_name。

除了使用注解映射,还可以在配置文件配置

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: false #取消驼峰命名
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #数据库日志配置
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: org.xx.springboot.entity
  global-config:
    db-config:
      table-underline: false #取消字段下划线
      table-prefix: t_ #忽视前缀字段

mybatisplus生成的方法开头特点:查询:get;添加:save;更新:update;删除:delete。

wrapper

条件构造器,用来创建sql语句的where部分。

Wrapper : 条件构造抽象类,最顶端父类

AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件

QueryWrapper :对象封装操作类,用于查询

UpdateWrapper :条件封装操作类,用于更新

AbstractLambdaWrapper : AbstractWrapper下L的ambda 语法使用的Wrapper抽象类,解析 lambda 

LambdaQueryWrapper :Lambda语法使用的查询Wrapper

LambdaUpdateWrapper : Lambda 更新封装Wrapper

比较大小

  • eq(R column, Object val); // 等价于 =
  • ne(R column, Object val); // 等价于 <>
  • gt(R column, Object val); // 等价于 >
  • ge(R column, Object val); // 等价于 >=
  • lt(R column, Object val); // 等价于 <
  • le(R column, Object val); // 等价于 <=
  • allEq,基于 map 的比较

比较范围

  • between(R column, Object val1, Object val2); // 等价于 between a and b
  • notBetween(R column, Object val1, Object val2); // 等价于 not between a and b, 
  • in(R column, Object... values); // 等价于 字段 IN (v0, v1, ...) 
  • notIn(R column, Object... values); // 等价于 字段 NOT IN (v0, v1, ...)
  • inSql(R column, Object... values); // 等价于 字段 IN (sql 语句)
  • notInSql(R column, Object... values); // 等价于 字段 NOT IN (sql 语句)

模糊匹配

  • like(R column, Object val); // 等价于 LIKE '%值%'
  • notLike(R column, Object val); // 等价于 NOT LIKE '%值%'not like '%王%'
  • likeLeft(R column, Object val); // 等价于 LIKE '%值'
  • likeRight(R column, Object val); // 等价于 LIKE '值%'

空值比较

  • isNull(R column); // 等价于 IS NULL
  • isNotNull(R column); // 等价于 IS NOT NULL

拼接、嵌套 sql:

  • or()/and(); // 等价于 a or b, 例:eq("id",1).or()/and().eq("name","老王") ---> id = 1 or/and name = '老王'
  • or/and(Consumer<Param> consumer); // 等价于 or/and(a or/and b),or /and嵌套.例: or/and(i -> i.eq("name", "李白").ne("status", "活着")) ---> or/and (name = '李白' and status <> '活着')
  • exists/notExists(String existsSql); // 拼接 exists 语句。例: exists("select id from table where age = 1") ---> exists (select id from table where age = 1)
  • nested,正常嵌套 不带 AND 或者 OR
  • apply,拼接sql
  • last,在sql语句拼接自定义条件,有sql注入风险
//构建查询条件
QueryWrapper wrapper=new QueryWrapper<>()
                .select("username","password")
                .like("username","张三").or()
                .ge("age",20);

//查询
List<User> users=userMapper.selectList(wrapper);
users.forEach(System.out.println);
//第二种写法
QueryWrapper wrapper=new QueryWrapper<>();
List<User> users=userMapper.selectList(wrapperselect("username","password")
                .like("username","张三").or()
                .ge("age",20))

lambda wrapper

在我们使用 Mybatis 时会发现,每当要写一个业务逻辑的时候都要在 DAO 层写一个方法,再对应一个 SQL,即使是简单的条件查询、即使仅仅改变了一个条件都要在 DAO层新增一个方法,针对这个问题,Mybatis-Plus 就提供了一个很好的解决方案:lambda 表达式,它可以让我们避免许多重复性的工作。

//第一种创建
LambdaQueryWrapper wrapper=new LambdaQueryWrapper<>();
//第二种
QueryWrapper wrapper=new QueryWrapper<>();
wrapper.lambda().select(user::getUsername);//不再传字段而是传字段的get方法

自定义sql

1.使用wrapper构建查询条件,在mapper的自定义方法里使用

2.mapper方法参数使用注解@Param("ew")

整合JSP

1.导入依赖

        <!--标准标签库-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入SpringBoot内嵌Tomcat对jsp的解析依赖,不添加这个解析不了jsp -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>



<!--在build标签里添加,和plugins标签同级
    SpringBoot项目默认推荐使用的前端引擎是thymeleaf
    现在我们要使用SpringBoot集成jsp,手动指定jsp最后编译的路径
    同时SpringBoot集成jsp编译jsp的路径是规定好的:META-INF/resources
-->
<resources>
    <resource>
        <!-- 源文件夹 -->
        <directory>src/main/webapp</directory>
        <!-- 指定编译到的路径为 META-INF/resources -->
        <targetPath>META-INF/resources</targetPath>
        <!-- 指定源文件夹中的哪些资源需要进行编译 -->
        <includes>
            <include>*.*</include>
        </includes>
     </resource>
</resources>

2.配置视图解析器

spring:
  mvc:
    view:
      prefix: /
      suffix: .jsp


server:
  servlet:
    jsp:
      init-parameters:
        development: true  # 修改jsp页面无需重新启动项目

3.建立webapp目录

在src/main下建立webapp目录,右键选择Resources Root设置为资源根目录,在webapp下新建jsp文件(这里的jsp页面没有模板,可以设置)

模板:

<%@ page contentType="text/html;charset=utf-8" language="java" %> <html> <head>     <title>$</title> </head> <body> </body> </html>

Thymeleaf

Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为“.html”,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;当通过 Web 应用程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。Thymeleaf 通过在 html 标签中,增加额外属性来达到“模板+数据”的展示方式

特点

  • 动静结合:Thymeleaf 既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。
  • 开箱即用:Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
  • 多方言支持:它提供了 Thymeleaf 标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式;必要时,开发人员也可以扩展和创建自定义的方言。
  • 与 SpringBoot 完美整合:SpringBoot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器,因此 Thymeleaf 可以与 Spring Boot 完美整合。

引入thymeleaf

1.导入依赖

<dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring5</artifactId>
</dependency>

2.配置yml

spring:
  thymeleaf:
    mode: HTML
    cache: false

3.在resource目录下新建templates、存放页面资源;static目录存放js、css等静态资源

语法规则

使用 Thymeleaf 之前,首先要在页面的 html 标签中声明名称空间,这一步并非必须进行的,即使我们不声明该命名空间,也不影响 Thymeleaf 的使用。thymeleaf所有的指令都是th:开头

xmlns:th="http://www.thymeleaf.org"

 常用th:指令

th:id替换id<input th:id="'xxx' + ${collect.id}"/>
th:text文本替换

<p th:text="${collect.description}">description</p>

th:utext支持html的文本替换<p th:utext="${htmlcontent}">conten</p>
th:object替换对象<div th:object="${session.user}">
th:value属性赋值<input th:value="${user.name}" />
th:with变量赋值运算<div th:with="isEven=${prodStat.count}%2==0"></div>
th:style设置样式th:style="'display:' + @{(${sitrue} ? 'none' : 'inline-block')} + ''"
th:onclick点击事件th:onclick="'getCollect()'"
th:each属性赋值tr th:each="user,userStat:${users}">
th:if判断条件<a th:if="${userId == collect.userId}" >
th:unless和th:if判断相反<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
th:href链接地址<a th:href="@{/login}" th:unless=${session.user != null}>Login</a> />
th:switch多路选择 配合th:case 使用<div th:switch="${user.role}">
th:caseth:switch的一个分支<p th:case="'admin'">User is an administrator</p>
th:replace布局标签,替换整个标签到引入的文件<div th:replace="fragments/header :: title"></div>
th:selectedselected选择框 选中th:selected="(${xxx.id} == ${configObj.dd})"
th:src图片类地址引入<img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}" />
th:inline定义js脚本可以使用变量<script type="text/javascript" th:inline="javascript">
th:action表单提交的地址<form action="subscribe.html" th:action="@{/subscribe}">
th:remove删除某个属性<tr th:remove="all"> 1.all:删除包含标签和所有的孩子。2.body:不包含标记删除,但删除其所有的孩子。3.tag:包含标记的删除,但不删除它的孩子。4.all-but-first:删除所有包含标签的孩子,除了第一个。5.none:什么也不做。这个值是有用的动态评估。
th:attr设置标签属性,多个属性可以用逗号分隔比如 th:attr="src=@{/image/aa.jpg},title=#{logo}",此标签不太优雅,一般用的比较少。
th:classappend追加样式th:classappend="类选择器名"

标准表达式语法

Thymeleaf 模板引擎支持多种表达式:

  • 变量表达式:${...}
  • 选择变量表达式:*{...}
  • 链接表达式:@{...}
  • 国际化表达式:#{...}
  • 片段引用表达式:~{...}

常用的内置基本对象

  • #ctx :上下文对象;
  • #vars :上下文变量;
  • #locale:上下文的语言环境;
  • #request:HttpServletRequest 对象(仅在 Web 应用中可用);
  • #response:HttpServletResponse 对象(仅在 Web 应用中可用);
  • #session:HttpSession 对象(仅在 Web 应用中可用);
  • #servletContext:ServletContext 对象(仅在 Web 应用中可用);

内置的工具对象

  • #strings:字符串工具对象,常用方法有:equals、equalsIgnoreCase、length、trim、toUpperCase、toLowerCase、indexOf、substring、replace、startsWith、endsWith,contains 和 containsIgnoreCase 等;
  • #numbers:数字工具对象,常用的方法有:formatDecimal 等; bools:布尔工具对象,常用的方法有:isTrue 和 isFalse 等;
  • #arrays:数组工具对象,常用的方法有:toArray、length、isEmpty、contains 和 containsAll 等;
  • #lists/sets:List/Set 集合工具对象,常用的方法有:toList、size、isEmpty、contains、containsAll 和 sort 等;
  • #maps:Map 集合工具对象,常用的方法有:size、isEmpty、containsKey 和 containsValue 等;
  • #dates:日期工具对象,常用的方法有:format、year、month、hour 和 createNow 等;

1.${...}

获取对象的属性和方法 使用内置的基本对象 使用内置的工具对象

2.*{...}

与变量表达式功能基本一致,只是在变量表达式的基础上增加了与 th:object 的配合使用。当使用 th:object 存储一个对象后,我们可以在其后代中使用选择变量表达式(*{...})获取该对象中的属性,其中,"*"即代表该对象。th:object 用于存储一个临时变量,该变量只在该标签及其后代中有效

<div th:object="${session.user}" >
    <p th:text="*{fisrtName}">firstname</p>
</div>

 3.@{...}

不管是静态资源的引用,还是 form 表单的请求,凡是链接都可以用链接表达式。

无参请求:@{/xxx} ;有参请求:@{/xxx(k1=v1,k2=v2)} 。例:

<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">

4.#{...}

#符号取thymeleaf工具中的方法、文字消息表达式

5.~{...}

片段引用表达式用于在模板页面中引用其他的模板片段,该表达式支持以下两种中语法结构:

推荐:~{templatename::fragmentname}

支持:~{templatename::#id}

templatename:模版名,Thymeleaf 会根据模版名解析完整路径:/resources/templates/templatename.html,要注意文件的路径。 fragmentname:片段名,Thymeleaf 通过 th:fragment 声明定义代码块,即:th:fragment="fragmentname" id:HTML 的 id 选择器,使用时要在前面加上 # 号,不支持 class 选择器。

传递参数

在抽取和引入公共页面片段时,还可以进行参数传递

1.模板名::选择器名或片段名(参数1=参数值1,参数2=参数值2) (参数较时使用)

2.模板名::选择器名或片段名(参数值1,参数值2) (参数较时使用)

使用场景:在 Web 项目中,通常会存在一些公共页面片段(重复代码),例如头部导航栏、侧边菜单栏和公共的 js css 等。我们一般会把这些公共页面片段抽取出来,存放在一个独立的页面中,然后再由其他页面根据需要进行引用,这样可以消除代码重复,使页面更加简洁。

文本操作

可以对文本内容进行两种常用操作,字符串连接和替换。先传入在使用,有两种方式:

1.字符串连接

不管是常量还是表达式结果,都可以使用+连接起来。 如<p th:text="'Welcome to ' + ${location}">。

2.字符串替换

符号||可以将字面值和表达式包括起来,这样就可以方便替换变量的值,不需要使用+连接符。 如<p th:text="|Welcome to ${location}|">

注释

1.标准注释 语法:<!--内容--->。

2.解析器级注释 语法:<!--/*内容*/-->。

运算符

算术运算符含义
+
-
*
/
%取余
布尔运算符含义
and且运算
or或运算
!/not
比较运算符含义
>/gt大于
>=/ge大于等于
</lt小于
<=/le小于等于
==/eq等于
!=/ne不等于
条件运算符含义
(if)?(then):else三目运算符,if条件为真则为then值,为假为else值
(value)?::defaultValuevalue为真则输出value,为假则输出默认值

循环

th:each

格式:th:each="自定义元素变量名称 : ${集合变量名称}"

属性th:each还提供了一个用于跟踪迭代的状态变量,有以下几个属性:

  • index:int类型,当前迭代的索引,从0开始
  • count:int类型,当前迭代的计数,从1开始,就是索引+1。
  • size:int类型,集合元素个数
  • current:Object类型,就是元素类型,当前元素对象
  • even:Boolean类型,当前迭代计数count是否为偶数
  • odd:Boolean类型,当前迭代的计数count是否为奇数
  • first:Boolean类型,当前元素是否是集合第一个元素
  • last:Boolean类型,当前元素是否为集合最后一个元素

加上状态变量,则使用th:each的语法是:th:each="自定义元素变量名称, 自定义状态变量名称 : ${集合变量名称}"。不定义状态变量名,Thymeleaf也会始终为每个th:each创建一个状态变量,默认状态变量名称就是自定义的元素变量名称加上Stat字符串

条件

条件判断语句有三种:th:if、th:unless、th:switch

th:if 当表达式结果为真时显示内容,否则不显示

th:unless 当表达式的判断结果为false时显示内容,否则不显示

th:switch 多路选择语句,与th:case来使用,例:

<div th:switch="${user.role}">    

   <p th:case="admin">管理员</p>    

   <p th:case="user">普通用户</p>

</div>

定义局部变量

使用th:with属性,可以定义局部变量,格式为:th:with="变量名=变量值" 定义多个局部变量时使用,分隔开。

内联表达式

内联表达式 [[...]] 允许直接在HTML文本中使用标准表达式,而不需要使用th:*标签属性。

  1. [[]]相当于th:text。不会对HTML标签转义。
  2. [()] 相当于th:utext,会对HTML标签自动转义。

th:inline

  • none:禁止内联表达式,可以原样输出[[]]和[()]字符串
  • text:文本内联,可以使用th:each等语法
  • css:样式内联,如<style th:inline="css">
  • javascript:脚本内联,如<style th:inline="javascript">

整合Redis

spring boot data redis中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是Redistemplate的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。

1.导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.yml配置文件

spring:
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    password:
    # 连接池最大连接数(使用负值表示没有限制)
    jedis.pool.max-active: 20
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    jedis.pool.max-wait: -1
    # 连接池中的最大空闲连接
    jedis.pool.max-idle: 10
    # 连接池中的最小空闲连接
    jedis.pool.min-idle: 0
    # 连接超时时间(毫秒)
    timeout: 1000

3.使用RedisTemplate

maven依赖里的aotuconfig的redis里默认配置

Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。

Redis5种数据结构操作

  • redisTemplate.opsForValue(); //操作字符串
  • redisTemplate.opsForHash(); //操作hash
  • redisTemplate.opsForList(); //操作list
  • redisTemplate.opsForSet(); //操作set
  • redisTemplate.opsForZSet(); //操作有序set

或者:

  • redistempalate.boundValueOps
  • redistempalate.boundSetOps
  • redistempalate.boundListOps
  • redistempalate.boundHashOps
  • redistempalate.boundZSetOps

区别:opsForXXX和boundXXXOps的区别:XXX为value的类型,前者获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value;后者获取了一个指定操作对象(key)的operator,在一个连接(事务)内只能操作这个key对应的value

Redis事务

设置二级缓存

使用Redis做Mybatis的二级缓存

一级缓存:基于sqlSession的缓存,二级缓存:基于多个sqlSession 共享的namspace数据块通常一个mapper 都一个namespace,所有的相关二级缓存都存在该namespace 数据块下。

查询顺序:先去二级缓存,如果二级没有再去一级缓存,一级没有再去数据库

注意:在spring 配置的mybatis 中不存在一级缓存,二级缓存发生增删改,该namespace 下所有缓存数据 立即清空,目的是为了避免有脏数据存在

1.导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.在配置文件yml的mybatis-plus的configuration下配置

cache-enabled: true #使用缓存

3.在spring中,只要实现或者继承xxAware接口或者类,在实例该对象时, 会调用实现xxAware接口的类的方法,把参数传递。该类主要是为了在spring环境中获取非spring容器管理的bean,即

@Component
public class ApplicationContextHolder implements ApplicationContextAware {

    //spring容器
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextHolder.applicationContext = applicationContext;
    }

    public static RedisTemplate getRedisTemplate(){
        return ApplicationContextHolder.applicationContext
                .getBean("redisTemplate",RedisTemplate.class);
    }
}

4.编写RedisCache二级缓存工具类

@Component调用的是无参构造器初始化对象,这里需要有参构造,无法使用@Component,所以无法通过spring注册bean,所以需要ApplicationContextHolder

public class MyBatisCache implements Cache {
    /*@Autowired*/
    //RedisTemplate对象
    private RedisTemplate redisTemplate;

    //id相当于当前sql对应的cache的命名空间 namespace="com.qf.mapper.xxxMapper"
    private String id;

    //读写锁:多线程中可以共享锁,如果大家都是读操作,提高数据的读的并发能力
    //如果有一个人进行了写操作,其他人都不能进行读写操作了
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    //获取RedisTemplate对象
    public RedisTemplate getRedisTemplate(){
        //判断
        if(redisTemplate == null){
            synchronized (MyBatisCache.class){
                if(redisTemplate == null){
                    RedisTemplate redisTemplate = ApplicationContextHolder.getRedisTemplate();
                    //设置key使用string类型的序列化方式
                    redisTemplate.setKeySerializer(RedisSerializer.string());
                    return redisTemplate;
                }
                return this.redisTemplate;
            }

        }
        return redisTemplate;
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }
    //构造器:用作mybatis缓存实现类时,mybaits会自动调用该有参构造器,并且把namespace当作id传入该构造器哦
    public MyBatisCache(String id) {
        System.out.println("id:"+id);
        this.id = id;
    }

/*    public MyBatisCache(){

    }*/

    //id相当于当前sql对应的cache的命名空间
    @Override
    public String getId() {
        System.out.println("getId:"+id);
        return id;
    }

    /**
     * 将结果放入缓存,当访问查询方法时调用,所以这里必须通过getRedisTemplate()方法来获取redisTemplate对象
     * @param key -> 命名空间 + sql + 参数 = 组成的字符串
     * @param value -> sql查询的结果
     */
    @Override
    public void putObject(Object key, Object value) {
        System.out.println("putObject中的key:"+key);
        System.out.println("putObject中的value:"+value);
        getRedisTemplate().opsForValue().set(key.toString(),value);
    }

    /**
     * 获取缓存中的数据,当访问查询方法时调用,所以这里必须通过getRedisTemplate()方法来获取redisTemplate对象
     * @param key
     * @return
     */
    @Override
    public Object getObject(Object key) {
        System.out.println("getObject:"+key);
        return getRedisTemplate().opsForValue().get(key.toString());
    }

    /**
     * 从缓存中移除数据,当访问查询方法时调用,所以这里必须通过getRedisTemplate()方法来获取redisTemplate对象
     * @param key
     * @return
     */
    @Override
    public Object removeObject(Object key) {
        System.out.println("removeObject:"+key);
        return getRedisTemplate().delete(key.toString());
    }

    /**
     * 清空缓存
     */
    @Override
    public void clear() {
        System.out.println("clear");
        Set keys = getRedisTemplate().keys("*" + id + "*");
        System.out.println("清空缓存keys:"+keys);
        getRedisTemplate().delete(keys);
    }

    /**
     * 获取缓存数据长度
     * @return
     */
    @Override
    public int getSize() {
        Set keys = getRedisTemplate().keys("*" + id + "*");
        return keys.size();
    }
}

5.配置RedisTemplate序列化工具类,实体也需要实现序列化接口

springboot 默认帮我们创建的RedisTemplate的key和value的序列化方式是jdk默认的方式, 我们有时候手动向redis中添加的数据可能无法被查询解析出来,所以我们需要修改序列化方式

@Configuration
public class RedisConfig {
  /**
     * 重写Redis序列化方式,使用Json方式:
     * 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。
     * RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。
     * Spring Data JPA为我们提供了下面的Serializer:
     * GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。
     * 在此我们将自己配置RedisTemplate并定义Serializer。
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 配置连接工厂
        redisTemplate.setConnectionFactory(connectionFactory);
        // 使用StringRedisSerializer来序列化和反序列化Redis的key值
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // 使用Jackson2JsonRedisSerializer来序列化和反序列化Redis的value值
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        // 配置对象映射器
        ObjectMapper objectMapper = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围。ANY指包括private和public修饰符范围
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入类型,类的信息也将添加到json中,这样才可以根据类名反序列化。
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        // 将对象映射器添加到序列化器中
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        // 配置key,value,hashKey,hashValue的序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }
}

6.启动类开启二级缓存支持

@EnableCaching

7.Mapper接口和xml中,更改默认的缓存方式(mybatis-plus只对自动生成的有效)

@CacheNamespace(implementation = MybatisCache.class)

mapper.xml配置(mybatis-plus只对手动添加的有效)

<cache type="org.kgc.springboot.cache.MybatisCache"/>

注解sql的使用注解mapper类的方式;Sql配置在xml中的,使用xml配置。两个同时配置会冲突

如果xml和注解方式需要同时使用,注解需要改成如下配置:

@CacheNamespaceRef(UserMapper.class)

springboot监控

Monitor监控页面

Spring Boot Monitor是一个对Spring boot admin监控工具做修改并适配单机的监控工具,完美继承了Spring boot admin的风格,直接使用actuator的指标进行显示。

Spring Boot Monitor官网:https://www.pomit.cn/SpringBootMonitor

导入依赖后无需其他配置

<dependency>
    <groupId>cn.pomit</groupId>
    <artifactId>spring-boot-monitor</artifactId>
    <version>0.0.1</version>
</dependency>

spring boot聚合工程

多模块聚合工程:按照MVC的思想,将应用分成三层web、service、mapper/dao这三个主要模块,在实际的开发过程中可能会根据实际的业务将聚合工程分成如下的形式: common:通用工具类模块,专门用于项目中使用的一些工具类。 entity:实体类模块,专门存放实体类对象,例如:DTO、BO、AO、VO等等对象。 mapper:dao接口模块,专门存放操作数据库的dao接口。 service:业务逻辑模块,专门进行业务逻辑的处理。 web:控制器模块,用于页面请求控制模块。

步骤

1.新建一个spring boot项目为父工程,删除src目录,只保留pom

在父工程坐标下添加:

<packaging>pom</packaging>

 删除pom里parent标签下的(父子工程都要删除)

<relativePath/>

2.右键父工程,新建module(spring boot子工程)

更改子工程pom.xml的父工程名

  <!--用父工程的坐标覆盖子工程的parent坐标-->
<groupId>com.xk</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>

在父工程的pom里添加子工程的module标签 

<modules>
  <module>common</module>
  <module>service</module>
  <module>mapper</module>
  <module>controller</module>
  <module>entity</module>
  <module>redis</module>
</modules>

在子工程的pom文件下的build标签下的plugin标签里添加

<!--跳过启动类-->
<configuration>
   <skip>true</skip>
</configuration>

3.删除子工程的依赖、src下的test目录、启动类、resouces目录,删除没用的.mvn、HELP.MD、mvnw、mvnw.cmd。controller模块不需要怎么做

4.配置各模块间的依赖关系(---->表示依赖)

  • web/controller----->service
  • service----->mapper,app-common
  • mapper----->entity

5.在父工程的pom.xml里使用dependenceManagement 配置版本号

父工程配置的依赖是所有模块都使用的,配置的依赖版本

整合Shiro

1.导入依赖,配置文件和启动类无需修改

 <!--shiro-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.12.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.12.0</version>
</dependency>
 <!-- thymeleaf-->
<dependency>
   <groupId>org.thymeleaf</groupId>
   <artifactId>thymeleaf-spring5</artifactId>
</dependency>
 <!--redis-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
 <!--thymeleaf-shiro-->
<dependency>
   <groupId>com.github.theborakompanioni</groupId>
   <artifactId>thymeleaf-extras-shiro</artifactId>
  <version>2.1.0</version>
</dependency>
 <!--Shiro-Redis-->
<dependency>
    <groupId>org.iherus.shiro</groupId>
    <artifactId>shiro-redis</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>org.crazycake</groupId>
    <artifactId>shiro-redis</artifactId>
    <version>3.3.1</version>
</dependency>

2.thyme leaf页面加入Shiro命名空间,即可使用Shiro标签

xmlns:shiro="http://www.w3.org/1999/xhtml"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值