紧接上一篇文章:
目录
2.SpringBoot监控检查_可视化工具SpringBoot Admin
一、Spring Boot简介
SpringBoot对Spring的缺点进行改善和优化,基于约定大于配置的思想,简化了Spring的开发,所谓简化是指简化了Spring中大量的配置文件和繁琐的依赖引入。所以SpringBoot是一个服务于框架的框架,它不是对Spring功能的增强,而是提供了一种快速使用 Spring框架的。
二、Spring Boot学习
1.Thymeleaf
Thymeleaf是一款用于渲染XML/HTML5内容的模板引擎,类似JSP。它可以轻易的与SpringMVC等Web框架进行集成作为Web应用的模板引擎。在SpringBoot中推荐使用Thymeleaf编写动态页面。
Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用。Thymeleaf在有网络和无网络的环境下皆可运行,它即可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。没有数据时,Thymeleaf的模板可以静态地运行;当有数据返回到页面时,Thymeleaf标签会动态地替换掉静态内容,使页面动态显示。
1.创建Springboot项目
2.引入SpringMVC和Thymeleaf起步依赖
3.在templates目录下创建视图index.xml
4.增加命名空间
<!DOCTYPE html>
<!--引入thymeleaf命名空间,方便使用thymeleaf属性-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>thymeleaf入门</title>
</head>
<body>
<!--在静态页面显示你好,动态页面使用后端传来的数据-->
<!--thymeleaf支持el表达式-->
<h2 th:text="${msg}">你好</h2>
</body>
</html>
5.template中的html文件不能直接访问,需要编写Controller跳转到页面中
@Controller
public class PageController {
@GetMapping("/show")
public String showPage(Model model){
model.addAttribute("msg","hello, thymeleaf");
return "index";
}
}
6.springboot设置application.properties的日志输出格式
#日志格式
logging.pattern.console=%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n
7.启动springboot项目,并在浏览器访问Controller的URL
1.变量输出
语法
th:text -将model中的值作为内容放入标签中
th:value -将model中的值放入 input 标签的 value 属性中
<input th:value="${msg}">
2.操作字符串
对model传过来的字符串进行判断:
${#strings.isEmpty(key)} -判断字符串是否为空,如果为空返回true,否则返回false
${#strings.contains(msg,'T')} -判断字符串是否包含指定的子串,如果包含返回true,否则返回false
${#strings.startsWith(msg,'a')} -判断当前字符串是否以子串开头,如果是返回true,否则返回false
${#strings.endsWith(msg,'a')} -判断当前字符串是否以子串结尾,如果是返回true,否则返回false
${#strings.length(msg)} -返回字符串的长度
${#strings.indexOf(msg,'h')} -查找子串的位置,并返回该子串的下标,如果没找到则返回-1
${#strings.substring(msg,2,5)} -截取子串,用法与JDK的 subString 方法相同
${#strings.toUpperCase(msg)} -字符串转大写
${#strings.toLowerCase(msg)} -字符串转小写
<span th:text="${#strings.isEmpty(msg)}"></span> <br/>
<span th:text="${#strings.contains(msg,'s')}"></span> <br/>
<span th:text="${#strings.length(msg)}"></span>
3.操作时间
操作时间的内置对象为dates
${#dates.format(key)} -格式化日期,默认的以浏览器默认语言为格式化标准
${#dates.format(key,'yyyy/MM/dd')} -按照自定义的格式做日期转换
${#dates.year(key)} -取年
${#dates.month(key)} -取月
${#dates.day(key)} -取日
1.数据:
model.addAttribute("date",new Date(130,01,01));
2.展示:
<span th:text="${#dates.format(date)}"></span> <br/>
<spanth:text="${#dates.format(date,'yyyy/MM/dd')}"></span> <br/>
<span th:text="${#dates.year(date)}"></span>
<span th:text="${#dates.month(date)}"></span>
<span th:text="${#dates.day(date)}"></span>
4.条件判断
语法
th:if -条件判断
1.数据:
model.addAttribute("sex","女");
2.展示:
<div>
<span th:if="${sex} == '男'">
性别:男
</span>
<span th:if="${sex} == '女'">
性别:女
</span>
</div> 12345678
th:switch/th:case -th:switch/th:case与Java中的switch语句等效。 th:case="*" 表示Java中
switch的default,即没有case的值为true时显示 th:case="*" 的内容。
1.数据:
model.addAttribute("id","12");
2.展示:
<div th:switch="${id}">
<span th:case="1">ID为1</span>
<span th:case="2">ID为2</span>
<span th:case="3">ID为3</span>
<span th:case="*">ID为*</span>
</div>
5.迭代遍历
语法
th:each -迭代器,用于循环迭代集合
1.实体类:
public class Users {
private String id;
private String name;
private int age;
// 省略getter/setter/构造方法
}
2.数据
List<Users> users = new ArrayList<>();
users.add(new Users("1","Jerry",23));
users.add(new Users("2","tom",22));
users.add(new Users("3","admin",25));
model.addAttribute("users",users);
3.展示
<table border="1" width="50%">
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
</tr>
<!-- 遍历集合的每一项起名为user -->
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
</tr>
</table>
thymeleaf将遍历的状态变量封装到一个对象中,通过该对象的属性可以获取状态变量:
index -当前迭代器的索引,从0开始
count -当前迭代对象的计数,从1开始
size -被迭代对象的长度
odd/even -布尔值,当前循环是否是偶数/奇数,从0开始
first - 布尔值,当前循环的是否是第一条,如果是返回true,否则返回false
last -布尔值,当前循环的是否是最后一条,如果是则返回true,否则返回false
使用状态变量 :
<!--冒号前的第一个对象是遍历出的对象,第二个对象是封
装状态变量的对象-->
<tr th:each="user,status : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
<td th:text="${status.index}"></td>
<td th:text="${status.count}"></td>
<td th:text="${status.size}"></td>
<td th:text="${status.odd}"></td>
<td th:text="${status.even}"></td>
<td th:text="${status.first}"></td>
<td th:text="${status.last}"></td>
</tr>
6.遍历Map
1. 数据:
Map<String,Users> map = new HashMap<>();
map.put("user1",new
Users("1","shangxuetang",23));
map.put("user2",new
Users("2","baizhan",22));
map.put("user3",new
Users("3","admin",25));
model.addAttribute("map",map);
2.遍历
<table border="1" width="50%">
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Key</th>
</tr>
<!-- 遍历出的是一个键值对对象,key获取键,value获取值 -->
<tr th:each="m : ${map}">
<td th:text="${m.value.id}"></td>
<td th:text="${m.value.name}"></td>
<td th:text="${m.value.age}"></td>
<td th:text="${m.key}"></td>
</tr>
</table>
7.获取域中的数据
thymeleaf也可以获取request,session,application域中的数据,方法如下:
1.数据:
request.setAttribute("req","HttpServletRequest");
session.setAttribute("ses","HttpSession");
session.getServletContext().setAttribute("app","application");
2.获取域数据
#表示内置对象
request1: <span th:text="${#request.getAttribute('req')}"/ >
request2:<span th:text="${#httpServletRequest.getAttribute('req')}"/><hr/>
session1: <span th:text="${session.ses}"/>
session2: <span th:text="${#httpSession.getAttribute('ses')}"/><hr/>
application1: <span th:text="${application.app}"/>
application2:<span th:text="${#servletContext.getAttribute('app')}"/>
8.URL写法
在Thymeleaf中路径的写法为 @{路径}
<a th:href="@{http://www.baidu.com}">百度</a>
在路径添加参数
1.准备数据
model.addAttribute("id","100");
model.addAttribute("name","Tom");
2.准备跳转后的controller
@GetMapping("/show2")
@ResponseBody
public String show2(String id,String name) {
return id+":"+name;
}
3.在URL添加参数
<a th:href="@{show2?id=1&name=jerry}">静态参数一</a>
<a th:href="@{show2(id=2,name=tom)}">静态参数二</a>
<a th:href="@{'show2?id='+${id}+'&name='+${name}}">动态参数一</a>
<a th:href="@{show2(id=${id},name=${name})}">动态参数二</a>
在RESTful风格路径中添加参数:
1.准备跳转访问的controller
@GetMapping("/show3/{id}/{name}")
@ResponseBody
public String show3(@PathVariable String id,@PathVariable String name){
return id+":"+name;
}
2.在URL添加参数
<a th:href="@{/show3/{id}/{name}(id=${id},name=${name})}">restful格式传递参数方式</a>
9.相关配置
在Springboot配置文件中可以进行Thymeleaf相关配置
在application.yaml文件配置
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
encoding: UTF-8
cache: false
servlet:
content-type: text/html
2.SpringBoot热部署
热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用。即修改完代码后不需要重启项目即可生效。在SpringBoot中,可以使用DevTools工具实现热部署
1.添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.7.2</version>
</dependency>
2.设置自动编译
3.在Idea设置自动运行
快捷键 Ctrl+Shift+Alt+/ 后点击 Registry ,勾选 complier.automake.allow.when.app.running
然后点击close
3.Spring Boot整合Mybatis
Spring整合MyBatis时需要进行大量配置,而SpringBoot整合MyBatis则可以简化很多配置:
1.创建项目添加起步依赖
2.编写实体类
public class Student {
private int id;
private String name;
private String sex;
private String address;
//省略getter、setter和构造方法
}
3.编写mapper接口
在entity包同目录下创建mapper\StudentMapper接口
package com.yygs.demo.mapper;
import com.yygs.demo.entity.Student;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface StudentMapper {
//查询所有学生
List<Student> findAll();
}
4.编写StudentMapper.xml映射文件
在resource创建与接口同级的mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yygs.demo.mapper.StudentMapper">
<select id="findAll" resultType="student">
select * from student;
</select>
</mapper>
5.编写配置yml文件(数据源
# 数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///student?severTimezone=UTC
username: root
password: abc123456
mybatis:
# 映射文件位置
config-location: com/yygs/demo/mapper/*Mapper.xml
# 别名
type-aliases-package: com.yygs.demo.entity
# 日志格式
logging:
pattern:
console: '%{HH:mm:ss.SSS} &clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
6.编写测试类
在test目录下创建测试类
package com.yygs.demo;
import com.yygs.demo.entity.Student;
import com.yygs.demo.mapper.StudentMapper;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.List;
// 测试类注解,可以在运行测试代码时加载Spring容器
@SpringBootTest
public class StudentMapperTest {
@Resource
private StudentMapper studentMapper;
public void testFindAll(){
List<Student> all = studentMapper.findAll();
all.forEach(System.out::println);
}
}
4.SpringBoot参数校验
SpringBoot自带了validation工具可以从后端对前端传来的参数进 行校验。
1.创建springboot项目(带web、validation依赖
2.编写controller类
类上必须放添加@Validated,参数前加@NotBlank
//该控制器开启参数校验
@Validated
@Controller
public class TestController {
@RequestMapping("/t1")
@ResponseBody
// 在参数前添加校验注解,意思时字符串不能为null,可以自己编写提示信息:@NotBlank(message= "用户名不能为空")
public String t1(@NotBlank String username){
System.out.println(username);
return "请求成功!";
}
}
1.SpringBoot参数校验_异常处理
当抛出 ConstraintViolationException 异常后,我们可以使用SpringMVC的异常处理器,也可以使用SpringBoot自带的异常处理机制。
当程序出现了异常,SpringBoot会使用自带的 BasicErrorController 对象处理异常。该处理器会默认跳转到/resources/templates/error.html页面。
1.添加thymeleaf依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.7.3</version>
</dependency>
2.编写error.html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>错误页面</title>
</head>
<body>
<h1>服务器开小差了。。</h1>
</body>
</html>
2.SpringBoot参数校验_校验相关注解
对简单参数进行校验必须在类上添加@Validated注解
package com.yygs.demo.controller;
import org.hibernate.validator.constraints.Length;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.constraints.*;
//该控制器开启参数校验
@Validated
@Controller
public class TestController {
@RequestMapping("/t1")
@ResponseBody
// 在参数前添加校验注解,意思时字符串不能为null,可以自己编写提示信息:@NotBlank(message= "用户名不能为空")
public String t1(@NotBlank @Length(min = 1,max = 5) String username,
@NotNull @Min(0) @Max(150) Integer age,
@NotBlank @Email String email){
System.out.println(username);
return "请求成功!";
}
}
3.SpringBoot参数校验_对象类型
SpringBoot也可以校验对象参数中的每个属性。
1.创建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@NotNull(message = "id不能为空")
private Integer id;
@NotNull(message = "姓名不能为空")
private String name;
}
2.编写controller类
需要在对象参数前添加@Validated注解,而不需要在类上方添加@Validated注解
@RequestMapping("/t3")
@ResponseBody
// 对象参数前添加@Validated,并将异常信息封装到BindingResult对象中
public String t2(@Validated Student student, BindingResult result){
// 判断是否又参数异常
if (result.hasErrors()) {
List<ObjectError> allErrors = result.getAllErrors();
// 遍历所有异常
for (ObjectError err: allErrors) {
FieldError fieldError = (FieldError) err;
System.out.println(fieldError.getDefaultMessage());
}
throw new RuntimeException("参数异常");
}
return "请求成功";
}
5.SpringBoot指标监控
1.SpringBoot监控检查_添加Actuator功能
Spring Boot Actuator可以帮助程序员监控和管理SpringBoot应用,比如健康检查、内存使用情况统计、线程使用情况统计等。我们在SpringBoot项目中添加Actuator功能,即可使用Actuator监控项目,
1.被监控的项目中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.编写application.properties配置文件
# 开启所有监控端点
management.endpoints.web.exposure.include=*
3.访问项目
通过URL可以调用actuator的功能:
例如查询健康数据,访问http://localhost:8080/actuator/health
2.SpringBoot监控检查_可视化工具SpringBoot Admin
Actuator使用JSON格式展示了大量指标数据,不利于我们查看,我们可以使用可视化工具Spring Boot Admin查看actuator生成指标数据。Spring Boot Admin是一个独立的项目,我们需要创建并运行该项目。
1.创建SpringBoot项目,添加web、admin服务端的依赖
2.修改applicaion.properties配置文件
# 修改端口号
server.port=9090
3.修改启动类,在类上添加@EnableAdminServer注解
@SpringBootApplication
@EnableAdminServer
public class SpringbootmyadminApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootmyadminApplication.class, args);
}
}
4.被监控项目连接Springboot admin项目
4.1 被监控项目添加客户端依赖
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.6.0</version>
</dependency>
4.2修改application.properties配置文件
# 开启所有监控端点
management.endpoints.web.exposure.include=*
# 连接springboot admin服务端
spring.boot.admin.client.url=http://localhost:9090
5.重启被监控的项目,浏览器访问admin项目
6.SpringBoot日志管理
SpringBoot默认使用Logback组件作为日志管理。Logback是log4j创始人设计的一个开源日志组件。在SpringBoot项目中我们不需要额外的添加Logback的依赖,因为在 spring-boot-parent 中已经包含了Logback的依赖。只需要在项目配置一个logback配置文件即可。
1.创建一个springboot项目,引入web依赖
2.配置application.propertis文件
日志文件输出在项目目录内。
<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
<configuration scan="true" scanPeriod="2 seconds">
<!--定义日志文件的存储地址-->
<property name="LOG_HOME" value="${catalina.base}/logs/"/>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%-5level:级别从左显示5个字符宽度,%t表示线程名,%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:-} --- [%t] %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- info级别日志文件输出 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件输出的文件名 -->
<File>${LOG_PATH}/info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每日生成日志文件或日志文件大小超出限制后输出的文件名模板 -->
<fileNamePattern>${LOG_PATH}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 日志文件保留天数 -->
<maxHistory>30</maxHistory>
<!-- 日志文件最大大小:10MB -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:-} --- [%t] %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- error级别日志文件输出 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志输出级别,优先级 > '<root level>' -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<File>${LOG_PATH}/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>30</maxHistory>
<maxFileSize>100MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:-} --- [%t] %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 默认日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
</configuration>
3.在代码中打印日志
package com.yygs.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class LogbackController {
// 获取logger对象
private final static Logger logger = LoggerFactory.getLogger(LogbackController.class);
@RequestMapping("/printLog")
@ResponseBody
public String showInfo(){
logger.info("记录日志");
return "Hello logback";
}
}
4.屏蔽包输出,配置application.properties
# 屏蔽org包中的日志输出
logging.level.org=off
7.Log4j2安全漏洞
在2021年12月,Log4j2爆出了极其严重的安全漏洞,攻击者可以让记录的日志包含指定字符串,从而执行任意程序。很多大型网站,如百度等都是此次Log4j漏洞的受害者,很多互联网企业连夜做了应急措施。Log4j2.0到2.14.1全部存在此漏洞,危害范围极其广泛,Log4j2.15.0-rc1中修复了这个 bug。
因Log4j2漏洞的反复无常,导致某些公司已经切换到Logback来记录日志,但在Log4j2漏洞爆出后,Logback也爆出漏洞:在Logback1.2.7及之前的版本中,具有编辑配置文件权限的攻击者可以制作恶意配置,允许从LDAP服务器加载、执行任意代码。
解决方案为将Logback升级到安全版本: Logback1.2.9+
SpringBoot2.6.2以上的Logback版本已经升到了1.2.9,Log4j2的版本也升到了2.17.0,所以我们使用SpringBoot2.6.2以上版本无需担心Log4j2和Logback安全漏洞。
8.SpringBoot项目部署_项目打包
SpringBoot项目是依赖于Maven构建的,但打包时如果只依赖Maven打包工具则会打包不完整,我们还需要在SpringBoot项目中引入SpringBoot打包插件 。
1.项目要有下面插件依赖,没有则需要添加
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在maven中:clean -》package
如果打包出现下列报错:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources) on project demo: Input length = 1 -> [Help 1]
将插件版本降为3.1.0或者更改为:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.3</version><!--与springboot版本号一致(spring-boot-starter-parent)-->
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</plugin>
打包后的jar包放在项目的target包中:demo-0.0.1-SNAPSHOT.jar
使用cmd打开命令行进入jar包所在目录,输入命令运行项目:
java -jar jar包名
1.SpringBoot项目部署_多环境配置
在真实开发中,在不同环境下运行项目往往会进行不同的配置,比
如开发环境使用的是开发数据库,测试环境使用的是测试数据库,
生产环境使用的是生产数据库。SpringBoot支持不同环境下使用不
同的配置文件,用法如下:
配置文件名:
application-环境名.properties/yml
1. application-dev.properties 开发环境配置文件
# 开发环境端口号为8080
server:
port: 8080
2. application-test.properties 测试环境配置文件
# 测试环境端口号为8081
server:
port: 8081
3. application-prod.properties 生产环境配置文件
# 生产环境端口号为80
server:
port: 80
运行jar包时选择环境
java -jar jar包名 --spring.profiles.active=环境名