创建项目

项目版本与依赖,从旧版开始了解

  • 生成器:spring initializr
  • 语言类型:java maven
  • jdk:20
  • java:8
  • spring boot:2.7.12
  • 依赖:spring web和lombok

Web整合

maven导入,web是tomcat服务器,security是权限验证框架

1
2
3
4
5
6
7
8
9
10
11
12
13
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

spring-boot支持yml或yaml格式,配置文件修改成application.yml,修改security的用户名与密码

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 80 #修改端口
test:
name: 幽蓝 #全局属性?
spring:
security:
user:
name: test # 用户名
password: 123456 # 密码
roles: # 角色
- user
- admin

@Value("${test.name}")从配置文件中取值给属性me;@RequestMapping@ResponseBody直接得到application/json响应数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Controller
public class MainController {
@Value("${test.name}")
String me;

@RequestMapping("/index")
@ResponseBody
public String index() {
return "欢迎欢迎👏" + me;
}

@RequestMapping("/student")
@ResponseBody
public Student student(){
Student student = new Student();
student.setName("小明");
student.setSex("男");
student.setSid(10);
return student;
}
}

登入验证,login路径所有人都能访问;spring5.7框架弃用WebSecurityConfigurerAdapter

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().hasRole("user")
.and()
.formLogin();
}
}

Mybatis整合

maven导入,创建项目时未勾选mysql与mybatis依赖,必须填写版本

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.1</version>
</dependency>

配置文件添加数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
security:
user:
name: test # 用户名
password: 123456 # 密码
roles: # 角色
- user
- admin
datasource:
url: jdbc:mysql://localhost:3306/study
username: root
password: d6NFV8SYsEWPgTvq
driver-class-name: com.mysql.cj.jdbc.Driver

添加实体类与映射器

1
2
3
4
5
6
7
8
9
10
11
12
13
@Data
public class UserData {
int uid;
String username;
String password;
String role;
}

@Mapper
public interface MainMapper {
@Select("select * from users where username = #{username}")
UserData findUserByName(String username);
}

通过MainMapper映射器查询username;return User根据给定的信息进行比对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Service
public class UserAuthService implements UserDetailsService {
@Resource
MainMapper mapper;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserData data = mapper.findUserByName(username);
if(data == null) throw new UsernameNotFoundException("用户 "+username+" 登录失败,用户名不存在!");
return User
.withUsername(data.getUsername())
.password(data.getPassword())
.roles(data.getRole())
.build();
}
}

修改hasAnyRole添加两个角色;configure方法会使配置文件里的默认用户失效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Resource
UserAuthService service;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().hasAnyRole("user", "admin")
.and()
.formLogin();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(service)
.passwordEncoder(new BCryptPasswordEncoder());
}
}

Thymeleaf整合

maven导入,创建项目时未勾选thymeleaf依赖,必须填写版本

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.7.12</version>
</dependency>

配置文件添加静态资源访问前缀;resources路径下,static文件夹存放css、js、image等资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
security:
user:
name: test # 用户名
password: 123456 # 密码
roles: # 角色
- user
- admin
datasource:
url: jdbc:mysql://localhost:3306/study
username: root
password: d6NFV8SYsEWPgTvq
driver-class-name: com.mysql.cj.jdbc.Driver
mvc:
static-path-pattern: /static/**

resources路径下,templates文件夹存放index.html与login.html页面
login页面需要关闭csrf防护

1
2
3
4
5
6
<html lang="en" xmlns:th=http://www.thymeleaf.org
xmlns:sec=http://www.thymeleaf.org/extras/spring-security>

<form action="/doLogin" method="post"></form>

<input th:name="${_csrf.parameterName}" th:value="${_csrf.token}" type="hidden">

login页面为用户名、密码、记住我添加name属性

1
2
3
<input name="username" type="text" placeholder="用户名" class="ad-input">
<input name="password" type="password" placeholder="密码" class="ad-input">
<input name="remember-me" type="checkbox" class="ad-checkbox">

没啥好说的,按照路径返回页面

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class MainController {
@RequestMapping("/login")
public String login() {
return "login";
}

@RequestMapping("/index")
public String index() {
return "index";
}
}

重新配置用户验证,记住我功能通过setDataSource方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/static/**").permitAll()
.anyRequest().hasAnyRole("user", "admin")
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/doLogin").permitAll()
.defaultSuccessUrl("/index", true)
.and()
.rememberMe()
.tokenRepository(new JdbcTokenRepositoryImpl(){{setDataSource(dataSource);}});
}

日志系统

默认日志系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//不要导错了
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Controller
public class MainController {
@RequestMapping("/login")
public String login() {
Logger logger = LoggerFactory.getLogger(MainController.class);
logger.info("第一种打印日志信息,有人访问了login页面");
return "login";
}

@RequestMapping("/index")
public String index() {
return "index";
}
}

lombok日志系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Slf4j
@Controller
public class MainController {
@RequestMapping("/login")
public String login() {
log.info("第二种打印日志信息,有人访问了login页面");
return "login";
}

@RequestMapping("/index")
public String index() {
return "index";
}
}

日志级别从低到高为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,SpringBoot默认打印INFO以上级别的信息

生成日志文件

resources路径下创建logback-spring.xml

  • configuration标签会替换默认配置
  • CONSOLE跟原本一样打印信息到控制台
  • FILE会在根目录下创建log文件夹,保存日志信息
  • root标签则是启动配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 导入其他配置文件,作为预设 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />

<!-- Appender作为日志打印器配置,这里命名随意 -->
<!-- ch.qos.logback.core.ConsoleAppender是专用于控制台的Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${CONSOLE_LOG_CHARSET}</charset>
</encoder>
</appender>

<!-- ch.qos.logback.core.rolling.RollingFileAppender用于文件日志记录,它支持滚动 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<!-- 自定义滚动策略,防止日志文件无限变大,也就是日志文件写到什么时候为止,重新创建一个新的日志文件开始写 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 文件保存位置以及文件命名规则,这里用到了%d{yyyy-MM-dd}表示当前日期,%i表示这一天的第N个日志 -->
<FileNamePattern>log/%d{yyyy-MM-dd}-spring-%i.log</FileNamePattern>
<!-- 到期自动清理日志文件 -->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
<!-- 最大日志保留时间 -->
<maxHistory>7</maxHistory>
<!-- 最大单个日志文件大小 -->
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
</appender>

<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>

多环境配置

maven支持环境切换,之后maven生命周期上方会出现配置文件选项,activeByDefault标签设置为true表示启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!--分别设置开发,生产环境-->
<profiles>
<!-- 开发环境 -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<environment>dev</environment>
</properties>
</profile>
<!-- 生产环境 -->
<profile>
<id>prod</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<environment>prod</environment>
</properties>
</profile>
</profiles>

maven支持排除文件,resources标签内填写排除文件,${environment}是占位符,能动态切换名字;plugins标签是插件,创建项目时自带的,无视无视

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<build>
<resources>
<!--排除配置文件-->
<resource>
<directory>src/main/resources</directory>
<!--先排除所有的配置文件-->
<excludes>
<!--使用通配符,当然可以定义多个exclude标签进行排除-->
<exclude>application*.yml</exclude>
</excludes>
</resource>

<!--根据激活条件引入打包所需的配置和文件-->
<resource>
<directory>src/main/resources</directory>
<!--引入所需环境的配置文件-->
<filtering>true</filtering>
<includes>
<include>application.yml</include>
<!--根据maven选择环境导入配置文件-->
<include>application-${environment}.yml</include>
</includes>
</resource>
</resources>

<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

创建application.yml,用来切换环境,active可以指定dev、prod环境;手动修改太麻烦了,设置成@environment@会从maven中寻找占位符进行替换

1
2
3
spring:
profiles:
active: '@environment@'

创建application-devapplication-prod分别设置成不同配置环境
日志系统也支持多环境,比如:开发环境打印控制台和日志文件,生产环境只打印日志文件

1
2
3
4
5
6
7
8
9
10
11
12
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</springProfile>

<springProfile name="prod">
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</springProfile>

打包运行

maven生命周期,点击clean、package打包成jar文件
不测试直接打包

1
mvn package  -DskipTests

启动jar文件,项目文件名修改成自己的

1
java -jar 项目文件名.jar