Compare commits
No commits in common. "58e0b5f4d1605ced9cd1979a16330c48731fc1cf" and "da5a5d13149bd11a30b2f2a972ddf80cff692671" have entirely different histories.
58e0b5f4d1
...
da5a5d1314
|
@ -9,7 +9,6 @@
|
||||||
<file url="file://$PROJECT_DIR$/multithreading1/src/main/resources" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/multithreading1/src/main/resources" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/multithreading1/src/main/resources-filtered" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/multithreading1/src/main/resources-filtered" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/mvc/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/mvc/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/spring-demo/src/main/java" charset="UTF-8" />
|
|
||||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/src/main/resources-filtered" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/src/main/resources-filtered" charset="UTF-8" />
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
<list>
|
<list>
|
||||||
<option value="$PROJECT_DIR$/pom.xml" />
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
<option value="$PROJECT_DIR$/mvc/pom.xml" />
|
<option value="$PROJECT_DIR$/mvc/pom.xml" />
|
||||||
<option value="$PROJECT_DIR$/spring-demo/pom.xml" />
|
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
<option name="ignoredFiles">
|
<option name="ignoredFiles">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# `Spring`笔记
|
# `SpringMVC`笔记
|
||||||
|
|
||||||
- 公共AI网站:https://chatgptplus.cn/
|
- 公共AI网站:https://chatgptplus.cn/
|
||||||
- vue3官网:https://cn.vuejs.org/
|
- vue3官网:https://cn.vuejs.org/
|
||||||
|
@ -147,90 +147,6 @@ public class FooController {
|
||||||
|
|
||||||
在这个例子中,如果访问 `/foo/bar`,它会首先匹配 `/foo/{id}`,因为它更精确。
|
在这个例子中,如果访问 `/foo/bar`,它会首先匹配 `/foo/{id}`,因为它更精确。
|
||||||
|
|
||||||
## 编写Spring应用
|
|
||||||
|
|
||||||
### `@SpringBootApplication` 注解
|
|
||||||
|
|
||||||
1. **`@EnableAutoConfiguration`**:
|
|
||||||
- 这个注解让 Spring Boot 根据项目中的依赖,自动配置 Spring 应用程序。Spring Boot 提供了大量的自动配置支持,帮助我们省去手动配置许多常见的功能。
|
|
||||||
- 例如,如果你的项目中加入了 `spring-boot-starter-web` 依赖,Spring Boot 会自动配置一个嵌入式的 Tomcat 服务器和一些常见的 Web 功能。
|
|
||||||
2. **`@ComponentScan`**:
|
|
||||||
- 这个注解启用 Spring 的组件扫描机制。它会扫描当前类所在的包及其子包,自动发现并注册 `@Component`、`@Service`、`@Repository`、`@Controller` 等注解标注的类。
|
|
||||||
- 通过 `@ComponentScan`,你不需要手动指定要扫描的包,Spring Boot 会自动扫描当前包及其子包下的所有组件。
|
|
||||||
3. **`@Configuration`**:
|
|
||||||
- 这个注解表示该类是一个 Spring 配置类,类似于 XML 配置文件,用于定义 Spring 应用的 Bean 配置。
|
|
||||||
- 该类可以包含 `@Bean` 注解的方法,返回要管理的 Bean。
|
|
||||||
|
|
||||||
### `@SpringBootTest` 注解
|
|
||||||
|
|
||||||
`@SpringBootTest` 注解是用于测试 Spring Boot 应用的一个重要注解,它提供了一种方便的方式来启动 Spring Boot 应用上下文,并对整个 Spring Boot 应用进行集成测试。这个注解本身也包含了多个注解,它使得我们能够在测试类中创建一个完整的 Spring 容器来进行集成测试。
|
|
||||||
|
|
||||||
具体来说,`@SpringBootTest` 是一个组合注解,它整合了以下几个主要的注解:
|
|
||||||
|
|
||||||
1. **`@ContextConfiguration`**:
|
|
||||||
- `@ContextConfiguration` 注解用于加载 Spring 配置文件或者配置类,在测试时会初始化 Spring 容器。`@SpringBootTest` 默认会加载 Spring Boot 应用的主配置类(即包含 `@SpringBootApplication` 注解的类),作为 Spring 容器的上下文。
|
|
||||||
- 它的作用是让测试类能够加载到 Spring 配置并创建一个完整的应用上下文。
|
|
||||||
2. **`@TestExecutionListeners`**:
|
|
||||||
- 该注解指定了测试执行时的监听器。在 Spring 测试框架中,`@TestExecutionListeners` 会提供某些扩展功能,如事务管理、环境配置等,但它的实际作用在大多数测试中不太明显,通常由 Spring Boot 自动配置。
|
|
||||||
3. **`@DirtiesContext`**:
|
|
||||||
- 这个注解会告诉 Spring 在测试执行之后清除(或重置)应用上下文,通常用于测试中的应用上下文需要被清理或重置,以避免测试间的相互影响。`@SpringBootTest` 会根据需要处理上下文的清理工作。
|
|
||||||
4. **`@BootstrapWith`**:
|
|
||||||
- 这个注解是用于引导测试的,它会指定 `SpringBootTestContextBootstrapper` 来启动 Spring Boot 测试上下文。这是一个 Spring Boot 测试框架中的内部机制,用于初始化应用上下文并准备测试。
|
|
||||||
|
|
||||||
### 测试页面
|
|
||||||
|
|
||||||
编写控制界面,返回`index.html`
|
|
||||||
|
|
||||||
```java
|
|
||||||
@RequestMapping
|
|
||||||
@Controller
|
|
||||||
public class HomeController {
|
|
||||||
|
|
||||||
@Operation(summary = "主页内容")
|
|
||||||
@GetMapping("index")
|
|
||||||
public String index() {
|
|
||||||
return "index";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
测试页面返回结果
|
|
||||||
|
|
||||||
```java
|
|
||||||
@WebMvcTest(HomeController.class)
|
|
||||||
class HomeControllerTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void index() throws Exception {
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get("/"))// 访问路径
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())// 判断状态是否成功
|
|
||||||
.andExpect(MockMvcResultMatchers.view().name("index"))// 判断视图名称是否是index
|
|
||||||
// 是否包含字段
|
|
||||||
.andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("欢迎。。。")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
访问index的页面
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Index 测试页面</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>欢迎。。。</h1>
|
|
||||||
<img alt="" th:src="@{/images/icon_3.png}">
|
|
||||||
<img alt="通常MVC项目静态资源放在 static/images 下" src="images/index/diannao.png">
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 访问控制
|
## 访问控制
|
||||||
|
|
||||||
请求地址时返回对应的网页文件
|
请求地址时返回对应的网页文件
|
||||||
|
@ -585,13 +501,17 @@ public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
`SessionInterceptor` 可以用于监控和管理 Session 数据。
|
`SessionInterceptor` 可以用于监控和管理 Session 数据。
|
||||||
|
|
||||||
> 在 Spring MVC 中,向 Session 共享数据主要有以下几种方式:
|
### 8. **总结**
|
||||||
>
|
|
||||||
> - **`HttpSession`**:通过 `HttpSession` 对象存储和读取 Session 数据。
|
在 Spring MVC 中,向 Session 共享数据主要有以下几种方式:
|
||||||
> - **`@SessionAttributes`**:通过 `@SessionAttributes` 注解将模型属性添加到 Session 中。
|
|
||||||
> - **`@ModelAttribute`**:结合 `@SessionAttributes` 使用,将模型数据持久化到 Session 中。
|
- **`HttpSession`**:通过 `HttpSession` 对象存储和读取 Session 数据。
|
||||||
> - **`@RequestParam` 和 `@PathVariable`**:将请求参数或路径变量存储到 Session 中。
|
- **`@SessionAttributes`**:通过 `@SessionAttributes` 注解将模型属性添加到 Session 中。
|
||||||
> - **Session 过期与清理**:可以通过配置控制会话超时,或手动清除 Session 数据。
|
- **`@ModelAttribute`**:结合 `@SessionAttributes` 使用,将模型数据持久化到 Session 中。
|
||||||
|
- **`@RequestParam` 和 `@PathVariable`**:将请求参数或路径变量存储到 Session 中。
|
||||||
|
- **Session 过期与清理**:可以通过配置控制会话超时,或手动清除 Session 数据。
|
||||||
|
|
||||||
|
Spring MVC 提供的 Session 管理机制非常灵活,能够满足各种需求。
|
||||||
|
|
||||||
## 向application域共享数据
|
## 向application域共享数据
|
||||||
|
|
||||||
|
@ -736,11 +656,14 @@ public class AppConfig {
|
||||||
|
|
||||||
在这种情况下,Spring 管理的 Bean 会在应用级别共享,类似于 `ServletContext` 中存储的数据。
|
在这种情况下,Spring 管理的 Bean 会在应用级别共享,类似于 `ServletContext` 中存储的数据。
|
||||||
|
|
||||||
> - `Application` 域(即 `ServletContext`)用于在整个应用程序范围内共享数据,适合存储全局共享的信息、配置和常量。
|
### 6. **总结**
|
||||||
> - 通过 `HttpServletRequest.getServletContext()` 或 `@Autowired` 注解可以访问 `ServletContext` 并向 `Application` 域中共享数据。
|
|
||||||
> - 数据存储在 `Application` 域中可以在整个应用程序生命周期内有效,适用于共享全局性的、无需频繁更新的数据。
|
- `Application` 域(即 `ServletContext`)用于在整个应用程序范围内共享数据,适合存储全局共享的信息、配置和常量。
|
||||||
> - 应谨慎存储敏感数据,并注意线程安全和数据的生命周期。
|
- 通过 `HttpServletRequest.getServletContext()` 或 `@Autowired` 注解可以访问 `ServletContext` 并向 `Application` 域中共享数据。
|
||||||
>
|
- 数据存储在 `Application` 域中可以在整个应用程序生命周期内有效,适用于共享全局性的、无需频繁更新的数据。
|
||||||
|
- 应谨慎存储敏感数据,并注意线程安全和数据的生命周期。
|
||||||
|
|
||||||
|
通过合理地使用 `Application` 域,你可以实现全局共享的数据管理,并且不需要担心会话或请求的生命周期问题。
|
||||||
|
|
||||||
## 重定向和转发使用
|
## 重定向和转发使用
|
||||||
|
|
||||||
|
@ -928,325 +851,12 @@ public class RedirectController {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 5. **总结**
|
||||||
|
|
||||||
- **重定向(Redirect)**:客户端浏览器会发起一次新的请求,地址栏 URL 会发生变化,适用于需要跨请求跳转或外部跳转的场景。
|
- **重定向(Redirect)**:客户端浏览器会发起一次新的请求,地址栏 URL 会发生变化,适用于需要跨请求跳转或外部跳转的场景。
|
||||||
- **转发(Forward)**:请求在服务器内部被转发,地址栏 URL 不变,适用于同一请求的内部跳转。
|
- **转发(Forward)**:请求在服务器内部被转发,地址栏 URL 不变,适用于同一请求的内部跳转。
|
||||||
|
|
||||||
## Spring 表单验证
|
通过合理使用转发和重定向,你可以灵活地控制请求流转和用户体验。
|
||||||
|
|
||||||
在 Spring MVC 中,表单验证是通过一系列的注解来完成的。
|
|
||||||
|
|
||||||
### **`@NotNull`**
|
|
||||||
|
|
||||||
- **作用**:确保字段值不为空。
|
|
||||||
|
|
||||||
- **用法**:用于字段、方法参数或返回值上,表示该字段不能为空。如果字段为空,将验证失败并返回相应的错误信息。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@NotNull(message = "用户名不能为空")
|
|
||||||
private String username;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@NotEmpty`**
|
|
||||||
|
|
||||||
- **作用**:确保字段不为空,并且不为一个空字符串。
|
|
||||||
|
|
||||||
- **用法**:用于字符串、集合等类型,验证字段不仅不能为空,而且不能为空字符串。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@NotEmpty(message = "密码不能为空")
|
|
||||||
private String password;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@NotBlank`**
|
|
||||||
|
|
||||||
- **作用**:确保字段不为空,并且不为一个空白字符串(即非空白字符)。
|
|
||||||
|
|
||||||
- **用法**:类似于 `@NotEmpty`,但除了不为空,还要求去除空白字符后不能为零长度。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@NotBlank(message = "电子邮件不能为空")
|
|
||||||
private String email;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Size(min, max)`**
|
|
||||||
|
|
||||||
- **作用**:验证字段的大小,适用于字符串、集合、数组等类型。
|
|
||||||
|
|
||||||
- **用法**:可以设置最小值和最大值来限制字段的长度或集合的大小。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Size(min = 6, max = 20, message = "密码长度必须在6到20之间")
|
|
||||||
private String password;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Email`**
|
|
||||||
|
|
||||||
- **作用**:验证字段是否符合有效的电子邮件格式。
|
|
||||||
|
|
||||||
- **用法**:用于验证字符串字段是否为有效的电子邮件地址格式。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Email(message = "请输入有效的电子邮件地址")
|
|
||||||
private String email;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Pattern(regexp)`**
|
|
||||||
|
|
||||||
- **作用**:根据正则表达式验证字段值。
|
|
||||||
|
|
||||||
- **用法**:可以根据自定义的正则表达式来验证字段的内容。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Pattern(regexp = "^\\d{10}$", message = "请输入有效的手机号码")
|
|
||||||
private String phoneNumber;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Min(value)` 和 `@Max(value)`**
|
|
||||||
|
|
||||||
- **作用**:确保数字类型字段的值在指定范围内。
|
|
||||||
|
|
||||||
- **用法**:`@Min` 用于验证值是否大于等于指定的最小值,`@Max` 用于验证值是否小于等于指定的最大值。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Min(value = 18, message = "年龄不能小于18岁")
|
|
||||||
@Max(value = 100, message = "年龄不能大于100岁")
|
|
||||||
private int age;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@DecimalMin(value)` 和 `@DecimalMax(value)`**
|
|
||||||
|
|
||||||
- **作用**:用于验证浮动值是否在指定范围内,类似于 `@Min` 和 `@Max`,但适用于 `BigDecimal` 或 `Double` 类型的数值。
|
|
||||||
|
|
||||||
- **用法**:`@DecimalMin` 验证值是否大于等于指定的最小值,`@DecimalMax` 验证值是否小于等于指定的最大值。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@DecimalMin(value = "0.0", inclusive = true, message = "价格不能小于0")
|
|
||||||
private BigDecimal price;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Future`**
|
|
||||||
|
|
||||||
- **作用**:验证日期字段的值是否为将来日期。
|
|
||||||
|
|
||||||
- **用法**:用于 `java.util.Date`、`java.time.LocalDate` 或 `java.time.LocalDateTime` 等日期类型的字段。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Future(message = "日期必须是未来的时间")
|
|
||||||
private LocalDate eventDate;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Past`**
|
|
||||||
|
|
||||||
- **作用**:验证日期字段的值是否为过去的日期。
|
|
||||||
|
|
||||||
- **用法**:类似于 `@Future`,但是验证日期必须是过去的时间。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Past(message = "出生日期必须是过去的时间")
|
|
||||||
private LocalDate birthDate;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@AssertTrue`**
|
|
||||||
|
|
||||||
- **作用**:验证字段值是否为 `true`。
|
|
||||||
|
|
||||||
- **用法**:适用于布尔类型字段,如果值不是 `true`,则验证失败。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@AssertTrue(message = "必须接受条款和条件")
|
|
||||||
private boolean acceptedTerms;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@AssertFalse`**
|
|
||||||
|
|
||||||
- **作用**:验证字段值是否为 `false`。
|
|
||||||
|
|
||||||
- **用法**:适用于布尔类型字段,如果值不是 `false`,则验证失败。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@AssertFalse(message = "不能接受条款")
|
|
||||||
private boolean declinedTerms;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Valid` 和 `@Validated`**
|
|
||||||
|
|
||||||
- **作用**:触发嵌套对象的验证。
|
|
||||||
|
|
||||||
- **用法**:当你有嵌套对象(如表单中的对象属性是另一个对象),使用 `@Valid` 或 `@Validated` 注解来递归验证该对象。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Valid
|
|
||||||
private Address address;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Digits(integer, fraction)`**
|
|
||||||
|
|
||||||
- **作用**:验证数字字段的有效性,确保字段值是一个有效的数字,并且整数部分和小数部分的位数符合指定要求。
|
|
||||||
|
|
||||||
- **用法**:`integer` 参数用于指定数字的整数部分的最大位数,`fraction` 参数用于指定小数部分的最大位数。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Digits(integer = 5, fraction = 2, message = "金额应为最大5位整数和2位小数")
|
|
||||||
private BigDecimal amount;
|
|
||||||
```
|
|
||||||
|
|
||||||
- 这个例子验证金额字段的最大值为 `99999.99`(即最多5位整数和2位小数)。
|
|
||||||
|
|
||||||
### **`@CreditCardNumber`**
|
|
||||||
|
|
||||||
- **作用**:验证信用卡号的有效性,确保其符合信用卡的常见格式,通常包括 Luhn 算法的验证。
|
|
||||||
|
|
||||||
- **用法**:该注解用于验证信用卡号的格式是否有效。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@CreditCardNumber(message = "请输入有效的信用卡号")
|
|
||||||
private String creditCardNumber;
|
|
||||||
```
|
|
||||||
|
|
||||||
- 该注解会根据常见的信用卡规则(如 VISA、MasterCard 等)验证输入的信用卡号是否合法。
|
|
||||||
|
|
||||||
### **`@Range(min, max)`**(不是 Spring 内置的,但通常来自 Hibernate Validator)
|
|
||||||
|
|
||||||
- **作用**:验证字段值是否在指定的范围内。常用于 `Integer`、`Long`、`Double` 等数值类型的字段。
|
|
||||||
|
|
||||||
- **用法**:指定字段的有效范围,当值不在范围内时会验证失败。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Range(min = 1, max = 100, message = "数字必须在1到100之间")
|
|
||||||
private int quantity;
|
|
||||||
```
|
|
||||||
|
|
||||||
- 该注解会验证 `quantity` 字段的值是否在 `1` 到 `100` 之间。
|
|
||||||
|
|
||||||
### **`@URL`**
|
|
||||||
|
|
||||||
- **作用**:验证字段是否为有效的 URL 格式。
|
|
||||||
|
|
||||||
- **用法**:用于字符串类型的字段,验证其是否符合有效的 URL 格式。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@URL(message = "请输入有效的网址")
|
|
||||||
private String website;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Valid` 与 `@Validated`**
|
|
||||||
|
|
||||||
- **作用**:用于嵌套对象的验证,确保嵌套对象的字段也进行验证。
|
|
||||||
|
|
||||||
- **用法**:这两个注解会触发嵌套对象的验证,通常用于嵌套的复杂表单数据结构。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Valid
|
|
||||||
private Address address;
|
|
||||||
```
|
|
||||||
|
|
||||||
- 如果 `Address` 类中有字段使用了验证注解,`@Valid` 会递归地验证 `Address` 对象的所有字段。
|
|
||||||
|
|
||||||
### **`@FutureOrPresent`**
|
|
||||||
|
|
||||||
- **作用**:验证日期或时间字段的值是否是当前日期(包括今天)或未来的日期。
|
|
||||||
|
|
||||||
- **用法**:该注解用于日期和时间字段,确保其为今天或将来的日期。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@FutureOrPresent(message = "事件日期必须是今天或将来")
|
|
||||||
private LocalDate eventDate;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@PastOrPresent`**
|
|
||||||
|
|
||||||
- **作用**:验证日期或时间字段的值是否是当前日期(包括今天)或过去的日期。
|
|
||||||
|
|
||||||
- **用法**:与 `@FutureOrPresent` 相反,确保字段是过去或今天的日期。
|
|
||||||
|
|
||||||
- 示
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PastOrPresent(message = "出生日期必须是过去的时间或今天")
|
|
||||||
private LocalDate birthDate;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@Null`**
|
|
||||||
|
|
||||||
- **作用**:验证字段是否为 `null`。如果字段不为空,则验证失败。
|
|
||||||
|
|
||||||
- **用法**:该注解可以用于字段或方法参数上,确保字段值必须为 `null`。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Null(message = "该字段必须为null")
|
|
||||||
private String nickname;
|
|
||||||
```
|
|
||||||
|
|
||||||
### **`@ScriptAssert(lang, script)`**
|
|
||||||
|
|
||||||
- **作用**:通过自定义脚本验证字段值。
|
|
||||||
|
|
||||||
- **用法**:允许使用自定义脚本(如 JavaScript)来执行复杂的验证逻辑。需要指定脚本语言和脚本内容。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@ScriptAssert(lang = "javascript", script = "_this.password == _this.confirmPassword", message = "密码和确认密码必须一致")
|
|
||||||
private String password;
|
|
||||||
private String confirmPassword;
|
|
||||||
```
|
|
||||||
|
|
||||||
- 这个注解可以用于检查两个字段值是否一致。
|
|
||||||
|
|
||||||
### **`@UniqueElements`**(Hibernate Validator 扩展)
|
|
||||||
|
|
||||||
- **作用**:确保集合中的元素是唯一的,常用于 List 或 Set 类型字段。
|
|
||||||
|
|
||||||
- **用法**:适用于集合类型字段,确保集合中的元素不重复。
|
|
||||||
|
|
||||||
- 示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
@UniqueElements(message = "列表中的元素必须唯一")
|
|
||||||
private List<String> tags;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Thymeleaf快速入门
|
## Thymeleaf快速入门
|
||||||
|
|
||||||
|
@ -1507,240 +1117,15 @@ Thymeleaf 是一种现代化的 Java 模板引擎,广泛用于生成 HTML、XM
|
||||||
|
|
||||||
- 设置 `input` 的 `placeholder` 为 `${placeholderText}` 的值。
|
- 设置 `input` 的 `placeholder` 为 `${placeholderText}` 的值。
|
||||||
|
|
||||||
### 23. **`th:errors`**
|
------
|
||||||
|
|
||||||
显示与 `username` 属性相关的错误信息。如果 `username` 为空或者不符合验证规则,这里就会显示出相应的错误消息。
|
### 总结
|
||||||
|
|
||||||
```html
|
Thymeleaf 提供了许多强大的指令来处理模板中的动态内容、条件渲染、迭代和属性绑定。常见的指令包括:
|
||||||
<div th:errors="*{email}"></div> <!-- 错误信息展示 -->
|
|
||||||
```
|
|
||||||
|
|
||||||
你还可以通过 `th:errors` 对错误消息进行自定义格式化。例如,使用 `*{field}` 可以获取字段的错误信息。
|
- `th:text`、`th:utext`:用于设置文本内容。
|
||||||
|
- `th:each`:用于循环遍历。
|
||||||
```html
|
- `th:if`、`th:unless`:用于条件判断。
|
||||||
<div th:errors="*{username}">Error</div>
|
- `th:attr`、`th:id`、`th:class`:用于设置 HTML 属性。
|
||||||
```
|
- `th:replace`、`th:include`:用于片段包含。
|
||||||
|
- `th:switch`、`th:case`:用于类似 `switch` 的条件语句。
|
||||||
如果验证失败,错误消息将显示在 `<div>` 中。如果没有错误,它会显示默认的 "Error" 文本。
|
|
||||||
|
|
||||||
## SpringSecurity
|
|
||||||
|
|
||||||
### 密码转换器(Password Encoder)
|
|
||||||
|
|
||||||
Spring Security 提供了多种密码转换器(Password Encoder),这些转换器用于对用户密码进行加密和验证。常见的密码转换器包括:
|
|
||||||
|
|
||||||
1. **BCryptPasswordEncoder**:
|
|
||||||
|
|
||||||
- 使用 **BCrypt** 算法对密码进行加密。
|
|
||||||
|
|
||||||
- 是最常用的密码加密方案,具有强大的加密性,并且支持自动加盐(salt),防止暴力破解攻击。
|
|
||||||
|
|
||||||
- 示例:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new BCryptPasswordEncoder();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **NoOpPasswordEncoder**:
|
|
||||||
|
|
||||||
- 不对密码进行加密,直接返回明文密码。
|
|
||||||
|
|
||||||
- 主要用于开发和测试环境,**不推荐在生产环境中使用**。
|
|
||||||
|
|
||||||
- 示例:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return NoOpPasswordEncoder.getInstance();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Pbkdf2PasswordEncoder**:
|
|
||||||
|
|
||||||
- 使用 **PBKDF2** 算法进行密码加密。
|
|
||||||
|
|
||||||
- 提供较强的安全性,并且支持对密码进行哈希。
|
|
||||||
|
|
||||||
- 示例:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new Pbkdf2PasswordEncoder();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Argon2PasswordEncoder**:
|
|
||||||
|
|
||||||
- 使用 **Argon2** 算法对密码进行加密。
|
|
||||||
|
|
||||||
- Argon2 是目前被认为最强的密码哈希算法,支持内存密集型计算,从而防止硬件加速破解。
|
|
||||||
|
|
||||||
- 示例:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new Argon2PasswordEncoder();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **SCryptPasswordEncoder**:
|
|
||||||
|
|
||||||
- 使用 **SCrypt** 算法进行密码加密。
|
|
||||||
|
|
||||||
- SCrypt 是另一种内存密集型的密码加密算法,与 Argon2 类似,旨在防止硬件加速破解。
|
|
||||||
|
|
||||||
- 示例:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new SCryptPasswordEncoder();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **MessageDigestPasswordEncoder** (已废弃):
|
|
||||||
|
|
||||||
- 基于 **MessageDigest** 算法进行加密(如 SHA-1、SHA-256 等)。
|
|
||||||
- 由于缺乏盐和密钥加密机制,已被其他更强的加密方式所替代。
|
|
||||||
|
|
||||||
> 选择密码转换器的建议:
|
|
||||||
>
|
|
||||||
> - 在现代应用中,推荐使用 **BCryptPasswordEncoder** 或 **Argon2PasswordEncoder**,这两种算法提供了强大的加密性。
|
|
||||||
> - **Pbkdf2PasswordEncoder** 和 **SCryptPasswordEncoder** 也可以作为备选方案,尤其是当你希望加密算法能够承受更多资源密集型攻击时。
|
|
||||||
> - **NoOpPasswordEncoder** 仅限于开发和测试环境。
|
|
||||||
|
|
||||||
### 访问主页
|
|
||||||
|
|
||||||
需要使用`http://localhost:8080/index`来访问主页,可以在配置中配置,访问根路径直接跳转
|
|
||||||
|
|
||||||
```java
|
|
||||||
@RequestMapping
|
|
||||||
@Controller
|
|
||||||
public class HomeController {
|
|
||||||
|
|
||||||
@Operation(summary = "主页内容")
|
|
||||||
@GetMapping("index")
|
|
||||||
public String index() {
|
|
||||||
return "index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "订单内容")
|
|
||||||
@GetMapping("order")
|
|
||||||
public String order() {
|
|
||||||
return "order";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "login")
|
|
||||||
@GetMapping("login")
|
|
||||||
public String login() {
|
|
||||||
return "login";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
在配置中
|
|
||||||
|
|
||||||
```java
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class WebConfiguration implements WebMvcConfigurer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
|
||||||
registry.addViewController("/")
|
|
||||||
// .setViewName("forward:/index") //两种方式写法
|
|
||||||
.setViewName("index");
|
|
||||||
registry.addViewController("/login");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 自定义登录
|
|
||||||
|
|
||||||
```java
|
|
||||||
package cn.bunny.springdemo.configuration;
|
|
||||||
|
|
||||||
import cn.bunny.springdemo.dao.entity.AdminUser;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class SecurityConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new SCryptPasswordEncoder(4, 8, 1, 8, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用内存方式
|
|
||||||
*
|
|
||||||
* @param encoder 密码加密器
|
|
||||||
* @return 基于内存的用户
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public UserDetailsService userDetailsService(PasswordEncoder encoder) {
|
|
||||||
ArrayList<UserDetails> userDetails = new ArrayList<>();
|
|
||||||
userDetails.add(new AdminUser("admin", encoder.encode("admin"), true));
|
|
||||||
userDetails.add(new AdminUser("bunny", encoder.encode("password"), true));
|
|
||||||
|
|
||||||
return new InMemoryUserDetailsManager(userDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 使用数据库方式
|
|
||||||
// *
|
|
||||||
// * @param userService 获取用户数据(如数据库)
|
|
||||||
// * @return 基于数据库的用户
|
|
||||||
// */
|
|
||||||
// @Bean
|
|
||||||
// public UserDetailsService userDetailsService(UserService userService) {
|
|
||||||
// return username -> {
|
|
||||||
// AdminUser adminUser = userService.getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getUsername, userService));
|
|
||||||
// if (adminUser != null) {
|
|
||||||
// return adminUser;
|
|
||||||
// }
|
|
||||||
// throw new UsernameNotFoundException("未找到 AdminUser");
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityFilterChain filterChain(HttpSecurity security) throws Exception {
|
|
||||||
return security
|
|
||||||
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
|
|
||||||
authorizationManagerRequestMatcherRegistry
|
|
||||||
.requestMatchers("/order").hasRole("USER")// 请求需要含有USER角色
|
|
||||||
.requestMatchers("/", "/index", "/login", "/images/**").permitAll()
|
|
||||||
)
|
|
||||||
/* 自定义登录页面 */
|
|
||||||
// .formLogin(AbstractAuthenticationFilterConfigurer::permitAll)// 默认的登录页会自动启用,无需额外配置
|
|
||||||
.formLogin(formLoginConfigurer -> formLoginConfigurer
|
|
||||||
.loginPage("/login")
|
|
||||||
// .loginProcessingUrl("/authenticate")
|
|
||||||
.usernameParameter("username")// 自定义用户名名称
|
|
||||||
.usernameParameter("password")// 自定义密码名称
|
|
||||||
.defaultSuccessUrl("/index")// 登录成功后默认跳转页面
|
|
||||||
// .defaultSuccessUrl("/index", true)// 登录成功后默认跳转页面,如果用户之前访问页面也需要强制跳转到 /index 可以传递第二个参数
|
|
||||||
)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -17,7 +17,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
<mybatis-plus.version>3.5.6</mybatis-plus.version>
|
<mybatis-plus.version>3.5.6</mybatis-plus.version>
|
||||||
<mysql.version>8.0.33</mysql.version>
|
<mysql.version>8.0.30</mysql.version>
|
||||||
<HikariCP.version>5.1.0</HikariCP.version>
|
<HikariCP.version>5.1.0</HikariCP.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- lombok -->
|
<!-- lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
|
|
@ -20,7 +20,7 @@ public class Knife4jConfig {
|
||||||
// 使用协议
|
// 使用协议
|
||||||
License license = new License().name("MIT").url("https://MUT.com");
|
License license = new License().name("MIT").url("https://MUT.com");
|
||||||
// 相关信息
|
// 相关信息
|
||||||
Info info = new Info().title("Spring MVC").description("Spring MVC 学习").version("v1.0.0").contact(contact).license(license).termsOfService("MIT");
|
Info info = new Info().title("家庭理财管理系统").description("家庭理财管理系统").version("v1.0.0").contact(contact).license(license).termsOfService("MIT");
|
||||||
|
|
||||||
return new OpenAPI().info(info).externalDocs(new ExternalDocumentation());
|
return new OpenAPI().info(info).externalDocs(new ExternalDocumentation());
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,6 @@ public class Knife4jConfig {
|
||||||
// 管理员相关分类接口
|
// 管理员相关分类接口
|
||||||
@Bean
|
@Bean
|
||||||
public GroupedOpenApi groupedOpenAdminApi() {
|
public GroupedOpenApi groupedOpenAdminApi() {
|
||||||
return GroupedOpenApi.builder().group("用户管理管理").pathsToMatch("/user/**").build();
|
return GroupedOpenApi.builder().group("后台管理").pathsToMatch("/user/**").build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package cn.bunny.mvc;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class MvcApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,92 +0,0 @@
|
||||||
11:10:36:949 INFO 11120 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Starting HomeControllerTest using Java 17.0.9 with PID 11120 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
11:10:36:951 INFO 11120 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : The following 1 profile is active: "dev"
|
|
||||||
11:10:37:324 INFO 11120 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
11:10:37:341 INFO 11120 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
11:10:37:500 INFO 11120 --- [spring-demo] [main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
|
||||||
11:10:37:500 INFO 11120 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
|
||||||
11:10:37:501 INFO 11120 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 1 ms
|
|
||||||
11:10:37:527 INFO 11120 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Started HomeControllerTest in 0.888 seconds (process running for 1.391)
|
|
||||||
11:10:58:580 INFO 15932 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Starting HomeControllerTest using Java 17.0.9 with PID 15932 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
11:10:58:584 INFO 15932 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : The following 1 profile is active: "dev"
|
|
||||||
11:10:58:965 INFO 15932 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
11:10:58:980 INFO 15932 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
11:10:59:140 INFO 15932 --- [spring-demo] [main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
|
||||||
11:10:59:140 INFO 15932 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
|
||||||
11:10:59:141 INFO 15932 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 1 ms
|
|
||||||
11:10:59:161 INFO 15932 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Started HomeControllerTest in 0.902 seconds (process running for 1.458)
|
|
||||||
11:12:10:789 INFO 1180 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Starting HomeControllerTest using Java 17.0.9 with PID 1180 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
11:12:10:792 INFO 1180 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : The following 1 profile is active: "dev"
|
|
||||||
11:12:11:166 INFO 1180 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
11:12:11:185 INFO 1180 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
11:12:11:337 INFO 1180 --- [spring-demo] [main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
|
||||||
11:12:11:337 INFO 1180 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
|
||||||
11:12:11:338 INFO 1180 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 1 ms
|
|
||||||
11:12:11:366 INFO 1180 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Started HomeControllerTest in 0.902 seconds (process running for 1.455)
|
|
||||||
11:13:43:498 INFO 12616 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Starting HomeControllerTest using Java 17.0.9 with PID 12616 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
11:13:43:501 INFO 12616 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : The following 1 profile is active: "dev"
|
|
||||||
11:13:43:877 INFO 12616 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
11:13:43:891 INFO 12616 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
11:13:44:041 INFO 12616 --- [spring-demo] [main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
|
|
||||||
11:13:44:041 INFO 12616 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
|
|
||||||
11:13:44:042 INFO 12616 --- [spring-demo] [main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 1 ms
|
|
||||||
11:13:44:062 INFO 12616 --- [spring-demo] [main] c.b.s.controller.HomeControllerTest : Started HomeControllerTest in 0.888 seconds (process running for 1.466)
|
|
||||||
12:56:08:799 INFO 10508 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 10508 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:56:08:802 INFO 10508 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:56:09:855 INFO 10508 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:56:09:868 INFO 10508 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:56:10:093 INFO 10508 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:56:10:240 INFO 10508 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.717 seconds (process running for 2.253)
|
|
||||||
12:56:30:906 INFO 21060 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 21060 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:56:30:909 INFO 21060 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:56:31:936 INFO 21060 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:56:31:950 INFO 21060 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:56:32:175 INFO 21060 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:56:32:317 INFO 21060 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.675 seconds (process running for 2.201)
|
|
||||||
12:56:49:178 INFO 19580 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 19580 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:56:49:181 INFO 19580 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:56:50:206 INFO 19580 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:56:50:220 INFO 19580 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:56:50:449 INFO 19580 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:56:50:598 INFO 19580 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.688 seconds (process running for 2.241)
|
|
||||||
12:57:19:701 INFO 12696 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 12696 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:57:19:704 INFO 12696 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:57:20:735 INFO 12696 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:57:20:750 INFO 12696 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:57:20:979 INFO 12696 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:57:21:127 INFO 12696 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.708 seconds (process running for 2.258)
|
|
||||||
12:57:45:076 INFO 9352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 9352 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:57:45:079 INFO 9352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:57:46:202 INFO 9352 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:57:46:219 INFO 9352 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:57:46:462 INFO 9352 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:57:46:630 INFO 9352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.858 seconds (process running for 2.69)
|
|
||||||
12:58:16:559 INFO 1652 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 1652 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:58:16:563 INFO 1652 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:58:17:571 INFO 1652 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:58:17:585 INFO 1652 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:58:17:813 INFO 1652 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:58:17:955 INFO 1652 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.689 seconds (process running for 2.236)
|
|
||||||
12:58:31:856 INFO 4352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 4352 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:58:31:860 INFO 4352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:58:42:935 INFO 4352 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:58:42:951 INFO 4352 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:58:43:193 INFO 4352 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:58:43:364 INFO 4352 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 11.813 seconds (process running for 12.431)
|
|
||||||
12:58:47:757 INFO 22540 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 22540 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:58:47:760 INFO 22540 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:58:53:578 INFO 22540 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:58:53:593 INFO 22540 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:58:53:835 INFO 22540 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:58:54:003 INFO 22540 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 6.548 seconds (process running for 7.169)
|
|
||||||
12:59:00:364 INFO 21332 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 21332 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
12:59:00:367 INFO 21332 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
12:59:01:498 INFO 21332 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
12:59:01:514 INFO 21332 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
12:59:01:752 INFO 21332 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
12:59:01:920 INFO 21332 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.851 seconds (process running for 2.456)
|
|
||||||
13:02:06:411 INFO 13172 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Starting SpringDemoApplicationTests using Java 17.0.9 with PID 13172 (started by 13199 in F:\学习\代码\Java\MultiThread\spring-demo)
|
|
||||||
13:02:06:416 INFO 13172 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : The following 1 profile is active: "dev"
|
|
||||||
13:02:07:458 INFO 13172 --- [spring-demo] [main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
|
|
||||||
13:02:07:471 INFO 13172 --- [spring-demo] [main] o.s.v.b.OptionalValidatorFactoryBean : Failed to set up a Bean Validation provider: jakarta.validation.NoProviderFoundException: Unable to create a Configuration, because no Jakarta Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
|
|
||||||
13:02:07:695 INFO 13172 --- [spring-demo] [main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
|
|
||||||
13:02:07:837 INFO 13172 --- [spring-demo] [main] c.b.s.SpringDemoApplicationTests : Started SpringDemoApplicationTests in 1.696 seconds (process running for 2.265)
|
|
|
@ -1,158 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>3.4.2</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>cn.bunny</groupId>
|
|
||||||
<artifactId>spring-demo</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<name>spring-demo</name>
|
|
||||||
<description>spring-demo</description>
|
|
||||||
<url/>
|
|
||||||
<licenses>
|
|
||||||
<license/>
|
|
||||||
</licenses>
|
|
||||||
<developers>
|
|
||||||
<developer/>
|
|
||||||
</developers>
|
|
||||||
<scm>
|
|
||||||
<connection/>
|
|
||||||
<developerConnection/>
|
|
||||||
<tag/>
|
|
||||||
<url/>
|
|
||||||
</scm>
|
|
||||||
<properties>
|
|
||||||
<java.version>17</java.version>
|
|
||||||
<fastjson2.version>2.0.47</fastjson2.version>
|
|
||||||
<version>${junit.version}</version>
|
|
||||||
<mybatis-plus.version>3.5.6</mybatis-plus.version>
|
|
||||||
<mysql.version>8.0.33</mysql.version>
|
|
||||||
<HikariCP.version>5.1.0</HikariCP.version>
|
|
||||||
</properties>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- spring-security -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security</groupId>
|
|
||||||
<artifactId>spring-security-test</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
|
||||||
<version>1.70</version> <!-- 请使用最新版本 -->
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcpg-jdk15on</artifactId>
|
|
||||||
<version>1.70</version> <!-- 请使用最新版本 -->
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- devtools -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-devtools</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<!-- 单元测试 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>${junit.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- lombok -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<!-- knife4j -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
|
||||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
|
||||||
<version>4.5.0</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- thymeleaf -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- fastjson2 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.fastjson2</groupId>
|
|
||||||
<artifactId>fastjson2</artifactId>
|
|
||||||
<version>${fastjson2.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- hutool -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>cn.hutool</groupId>
|
|
||||||
<artifactId>hutool-all</artifactId>
|
|
||||||
<version>5.8.27</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- mybatis-plus -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baomidou</groupId>
|
|
||||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
|
||||||
<version>${mybatis-plus.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- mysql -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
|
||||||
<version>${mysql.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- mysql连接池 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.zaxxer</groupId>
|
|
||||||
<artifactId>HikariCP</artifactId>
|
|
||||||
<version>${HikariCP.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<annotationProcessorPaths>
|
|
||||||
<path>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
</path>
|
|
||||||
</annotationProcessorPaths>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<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>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,11 +0,0 @@
|
||||||
package cn.bunny.springdemo;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
public class SpringDemoApplication {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(SpringDemoApplication.class, args);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package cn.bunny.springdemo.configuration;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.models.ExternalDocumentation;
|
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
|
||||||
import io.swagger.v3.oas.models.info.Contact;
|
|
||||||
import io.swagger.v3.oas.models.info.Info;
|
|
||||||
import io.swagger.v3.oas.models.info.License;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springdoc.core.models.GroupedOpenApi;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@Slf4j
|
|
||||||
public class Knife4jConfig {
|
|
||||||
@Bean
|
|
||||||
public OpenAPI openAPI() {
|
|
||||||
// 作者等信息
|
|
||||||
Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url("http://bunny-web.site");
|
|
||||||
// 使用协议
|
|
||||||
License license = new License().name("MIT").url("https://MUT.com");
|
|
||||||
// 相关信息
|
|
||||||
Info info = new Info().title("Spring ").description("Spring 学习").version("v1.0.0").contact(contact).license(license).termsOfService("MIT");
|
|
||||||
|
|
||||||
return new OpenAPI().info(info).externalDocs(new ExternalDocumentation());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 管理员相关分类接口
|
|
||||||
@Bean
|
|
||||||
public GroupedOpenApi groupedOpenAdminApi() {
|
|
||||||
return GroupedOpenApi.builder().group("基础请求").pathsToMatch("/api/**").build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
package cn.bunny.springdemo.configuration;
|
|
||||||
|
|
||||||
import cn.bunny.springdemo.dao.entity.AdminUser;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class SecurityConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new SCryptPasswordEncoder(4, 8, 1, 8, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用内存方式
|
|
||||||
*
|
|
||||||
* @param encoder 密码加密器
|
|
||||||
* @return 基于内存的用户
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public UserDetailsService userDetailsService(PasswordEncoder encoder) {
|
|
||||||
ArrayList<UserDetails> userDetails = new ArrayList<>();
|
|
||||||
userDetails.add(new AdminUser("admin", encoder.encode("admin"), true));
|
|
||||||
userDetails.add(new AdminUser("bunny", encoder.encode("password"), true));
|
|
||||||
|
|
||||||
return new InMemoryUserDetailsManager(userDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 使用数据库方式
|
|
||||||
// *
|
|
||||||
// * @param userService 获取用户数据(如数据库)
|
|
||||||
// * @return 基于数据库的用户
|
|
||||||
// */
|
|
||||||
// @Bean
|
|
||||||
// public UserDetailsService userDetailsService(UserService userService) {
|
|
||||||
// return username -> {
|
|
||||||
// AdminUser adminUser = userService.getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getUsername, userService));
|
|
||||||
// if (adminUser != null) {
|
|
||||||
// return adminUser;
|
|
||||||
// }
|
|
||||||
// throw new UsernameNotFoundException("未找到 AdminUser");
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityFilterChain filterChain(HttpSecurity security) throws Exception {
|
|
||||||
return security
|
|
||||||
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
|
|
||||||
authorizationManagerRequestMatcherRegistry
|
|
||||||
.requestMatchers("/order").hasRole("USER")// 请求需要含有USER角色
|
|
||||||
.requestMatchers("/", "/index", "/login", "/images/**").permitAll()
|
|
||||||
)
|
|
||||||
/* 自定义登录页面 */
|
|
||||||
// .formLogin(AbstractAuthenticationFilterConfigurer::permitAll)// 默认的登录页会自动启用,无需额外配置
|
|
||||||
.formLogin(formLoginConfigurer -> formLoginConfigurer
|
|
||||||
.loginPage("/login")
|
|
||||||
// .loginProcessingUrl("/authenticate")
|
|
||||||
.usernameParameter("username")// 自定义用户名名称
|
|
||||||
.usernameParameter("password")// 自定义密码名称
|
|
||||||
.defaultSuccessUrl("/index")// 登录成功后默认跳转页面
|
|
||||||
// .defaultSuccessUrl("/index", true)// 登录成功后默认跳转页面,如果用户之前访问页面也需要强制跳转到 /index 可以传递第二个参数
|
|
||||||
)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package cn.bunny.springdemo.configuration;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class WebConfiguration implements WebMvcConfigurer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
|
||||||
registry.addViewController("/")
|
|
||||||
// .setViewName("forward:/index") //两种方式写法
|
|
||||||
.setViewName("index");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package cn.bunny.springdemo.controller;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
@Controller
|
|
||||||
public class HomeController {
|
|
||||||
|
|
||||||
@Operation(summary = "主页内容")
|
|
||||||
@GetMapping("index")
|
|
||||||
public String index() {
|
|
||||||
return "index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "订单内容")
|
|
||||||
@GetMapping("order")
|
|
||||||
public String order() {
|
|
||||||
return "order";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "login")
|
|
||||||
@GetMapping("login")
|
|
||||||
public String login() {
|
|
||||||
return "login";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
package cn.bunny.springdemo.dao;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Schema(name = "BaseEntity", title = "基础信息字段", description = "基础信息字段")
|
|
||||||
public class BaseEntity implements Serializable {
|
|
||||||
|
|
||||||
@Schema(name = "id", title = "唯一标识")
|
|
||||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Schema(name = "createTime", title = "创建时间")
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
|
||||||
private LocalDateTime createTime;
|
|
||||||
|
|
||||||
@Schema(name = "updateTime", title = "更新时间")
|
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
|
||||||
private LocalDateTime updateTime;
|
|
||||||
|
|
||||||
@Schema(name = "createUser", title = "创建用户")
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
|
||||||
private Long createUser;
|
|
||||||
|
|
||||||
@Schema(name = "updateUser", title = "操作用户")
|
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING)
|
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
|
||||||
private Long updateUser;
|
|
||||||
|
|
||||||
@Schema(name = "isDeleted", title = "是否被删除")
|
|
||||||
@TableLogic
|
|
||||||
private Boolean isDeleted;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package cn.bunny.springdemo.dao;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
@Schema(name = "BaseUserEntity", title = "基础信息字段包含用户信息", description = "基础信息字段包含用户信息")
|
|
||||||
public class BaseUserEntity extends BaseEntity {
|
|
||||||
|
|
||||||
@Schema(name = "username", title = "用户名")
|
|
||||||
private String createUsername;
|
|
||||||
|
|
||||||
@Schema(name = "nickname", title = "昵称")
|
|
||||||
private String updateUsername;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package cn.bunny.springdemo.dao.dto;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Builder
|
|
||||||
@Schema(name = "BillDto对象", title = "账单信息查询内容", description = "账单信息查询内容")
|
|
||||||
public class BillDto {
|
|
||||||
|
|
||||||
@Schema(name = "userId", title = "绑定的用户id")
|
|
||||||
private Long userId;
|
|
||||||
|
|
||||||
@Schema(name = "amount", title = "金额")
|
|
||||||
private BigDecimal amount;
|
|
||||||
|
|
||||||
@Schema(name = "categoryIds", title = "类别分类")
|
|
||||||
private List<Long> categoryIds;
|
|
||||||
|
|
||||||
@Schema(name = "username", title = "类型:1 - 收入,-1 - 支出")
|
|
||||||
private Byte type;
|
|
||||||
|
|
||||||
@Schema(name = "description", title = "描述")
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
@Schema(name = "startDate", title = "开始交易日期")
|
|
||||||
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
|
||||||
private LocalDate startDate;
|
|
||||||
|
|
||||||
@Schema(name = "endDate", title = "结束交易日期")
|
|
||||||
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
|
||||||
private LocalDate endDate;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package cn.bunny.springdemo.dao.entity;
|
|
||||||
|
|
||||||
import cn.bunny.springdemo.dao.BaseEntity;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 管理员用户信息
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Bunny
|
|
||||||
* @since 2024-06-26
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@TableName("sys_user")
|
|
||||||
@Schema(name = "AdminUser对象", title = "用户信息", description = "用户信息")
|
|
||||||
public class AdminUser extends BaseEntity implements UserDetails {
|
|
||||||
|
|
||||||
@Schema(name = "username", title = "用户名")
|
|
||||||
private String username;
|
|
||||||
|
|
||||||
@Schema(name = "password", title = "密码")
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
@Schema(name = "status", title = "状态", description = "1:禁用 0:正常")
|
|
||||||
private Boolean status;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
|
||||||
return List.of(new SimpleGrantedAuthority("ROLE_USER"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package cn.bunny.springdemo.dao.entity;
|
|
||||||
|
|
||||||
import cn.bunny.springdemo.dao.BaseEntity;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 账单信息
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Bunny
|
|
||||||
* @since 2024-11-07
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@TableName("t_bill")
|
|
||||||
@Schema(name = "Bill对象", title = "账单信息", description = "账单信息")
|
|
||||||
public class Bill extends BaseEntity {
|
|
||||||
|
|
||||||
@Schema(name = "username", title = "类型:1 - 收入,-1 - 支出")
|
|
||||||
private Byte type;
|
|
||||||
|
|
||||||
@Schema(name = "userId", title = "绑定的用户id")
|
|
||||||
private Long userId;
|
|
||||||
|
|
||||||
@Schema(name = "amount", title = "金额")
|
|
||||||
private BigDecimal amount;
|
|
||||||
|
|
||||||
@Schema(name = "description", title = "描述")
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
@Schema(name = "transactionDate", title = "交易日期")
|
|
||||||
private LocalDateTime transactionDate;
|
|
||||||
|
|
||||||
@Schema(name = "categoryId", title = "类别id")
|
|
||||||
private Long categoryId;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package cn.bunny.springdemo.mapper;
|
|
||||||
|
|
||||||
import cn.bunny.springdemo.dao.entity.AdminUser;
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 用户信息 Mapper 接口
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Bunny
|
|
||||||
* @since 2024-09-26
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface UserMapper extends BaseMapper<AdminUser> {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package cn.bunny.springdemo.services;
|
|
||||||
|
|
||||||
import cn.bunny.springdemo.dao.entity.AdminUser;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* 用户信息 服务类
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Bunny
|
|
||||||
* @since 2024-09-26
|
|
||||||
*/
|
|
||||||
public interface UserService extends IService<AdminUser> {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package cn.bunny.springdemo.services.impl;
|
|
||||||
|
|
||||||
import cn.bunny.springdemo.dao.entity.AdminUser;
|
|
||||||
import cn.bunny.springdemo.mapper.UserMapper;
|
|
||||||
import cn.bunny.springdemo.services.UserService;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户信息 服务实现类
|
|
||||||
*
|
|
||||||
* @author Bunny
|
|
||||||
* @since 2024-09-26
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
@Transactional
|
|
||||||
public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implements UserService {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
server:
|
|
||||||
port: 8080
|
|
||||||
logging:
|
|
||||||
level:
|
|
||||||
cn.bunny.service.mapper: info
|
|
||||||
cn.bunny.service.controller: info
|
|
||||||
cn.bunny.service.service: info
|
|
||||||
root: info
|
|
||||||
pattern:
|
|
||||||
dateformat: HH:mm:ss:SSS
|
|
||||||
file:
|
|
||||||
path: "logs/${spring.application.name}"
|
|
||||||
|
|
||||||
#mybatis-plus:
|
|
||||||
# configuration:
|
|
||||||
# map-underscore-to-camel-case: true
|
|
||||||
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
|
|
||||||
|
|
||||||
bunny:
|
|
||||||
master:
|
|
||||||
host: 192.168.3.130
|
|
||||||
port: 3306
|
|
||||||
database: family_financial
|
|
||||||
username: root
|
|
||||||
password: "123456"
|
|
||||||
|
|
||||||
mongodb:
|
|
||||||
database: financial
|
|
||||||
host: 192.168.3.130
|
|
||||||
port: 27017
|
|
||||||
username: admin
|
|
||||||
password: "123456"
|
|
||||||
authentication-database: admin
|
|
||||||
additional-hosts: 192.168.3.130
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
spring:
|
|
||||||
application:
|
|
||||||
name: spring-demo
|
|
||||||
|
|
||||||
profiles:
|
|
||||||
active: dev
|
|
||||||
servlet:
|
|
||||||
multipart:
|
|
||||||
max-file-size: 6MB
|
|
||||||
|
|
||||||
datasource:
|
|
||||||
type: com.zaxxer.hikari.HikariDataSource
|
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
||||||
url: jdbc:mysql://${bunny.master.host}:${bunny.master.port}/${bunny.master.database}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
|
|
||||||
username: ${bunny.master.username}
|
|
||||||
password: ${bunny.master.password}
|
|
||||||
|
|
||||||
jackson:
|
|
||||||
date-format: yyyy-MM-dd HH:mm:ss
|
|
||||||
time-zone: GMT+8
|
|
|
@ -1,10 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>400</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>400</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,10 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>404</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>404</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,64 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-cmn-Hans">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>500 - 服务器错误</title>
|
|
||||||
<meta content="width=device-width, maximum-scale=1, initial-scale=1" name="viewport"/>
|
|
||||||
<style>
|
|
||||||
html, body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
color: #333;
|
|
||||||
margin: auto;
|
|
||||||
padding: 1em;
|
|
||||||
display: table;
|
|
||||||
user-select: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font: lighter 20px "微软雅黑";
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #3498db;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin-top: 0;
|
|
||||||
font-size: 3.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
display: table-cell;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
color: #fff;
|
|
||||||
padding: .75em 1em;
|
|
||||||
background: #3498db;
|
|
||||||
border-radius: 1.5em;
|
|
||||||
display: inline-block;
|
|
||||||
transition: opacity .3s, transform .3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:hover {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:active {
|
|
||||||
opacity: .7;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<h1>:'(</h1>
|
|
||||||
<p>服务器开小差啦!管理员正在修理中...</p>
|
|
||||||
<p>还请阁下静候站点恢复~</p>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 326 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.7 KiB |
|
@ -1,12 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Index 测试页面</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>欢迎。。。</h1>
|
|
||||||
<img alt="" th:src="@{/images/icon_3.png}">
|
|
||||||
<img alt="通常MVC项目静态资源放在 static/images 下" src="images/index/diannao.png">
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,255 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>边框流动效果的login页面 www.bootstrapmb.com</title>
|
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
|
||||||
<meta content="ie=edge" http-equiv="X-UA-Compatible"/>
|
|
||||||
<style media="screen">
|
|
||||||
* {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
box-sizing: border-box
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: sans-serif;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: 100vh;
|
|
||||||
background: #0c0116
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
|
||||||
position: relative;
|
|
||||||
padding: 60px 15px;
|
|
||||||
width: 270px;
|
|
||||||
height: 350px;
|
|
||||||
background: #0c0116;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: 0 0 10px 0 #747772;
|
|
||||||
border-radius: 5px
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-inner {
|
|
||||||
position: absolute;
|
|
||||||
height: 98%;
|
|
||||||
width: 98%;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
background: #0c0116;
|
|
||||||
transform: translate(-50%, -50%)
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
padding: 25px
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-inner h2 {
|
|
||||||
font-size: 25px;
|
|
||||||
color: #d7a3d7;
|
|
||||||
text-align: center;
|
|
||||||
padding-top: 35px
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
display: block;
|
|
||||||
padding: 12px 15px;
|
|
||||||
width: 100%;
|
|
||||||
left: 50%;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin-top: 20px;
|
|
||||||
border: 1.5px solid #6d5779;
|
|
||||||
outline: 0;
|
|
||||||
background: #19052c;
|
|
||||||
color: white
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
margin-top: 40px;
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px;
|
|
||||||
outline: 0;
|
|
||||||
background: #800080;
|
|
||||||
border: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
border-radius: 10px;
|
|
||||||
transition: .4s
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:hover {
|
|
||||||
background: #c907c9
|
|
||||||
}
|
|
||||||
|
|
||||||
.form span {
|
|
||||||
position: absolute;
|
|
||||||
height: 50%;
|
|
||||||
width: 50%
|
|
||||||
}
|
|
||||||
|
|
||||||
.form span:nth-child(1) {
|
|
||||||
background: #ffda05;
|
|
||||||
top: 0;
|
|
||||||
left: -48%;
|
|
||||||
animation: 5s span1 infinite linear;
|
|
||||||
animation-delay: 1s
|
|
||||||
}
|
|
||||||
|
|
||||||
.form span:nth-child(2) {
|
|
||||||
background: #00a800;
|
|
||||||
bottom: 0;
|
|
||||||
right: -48%;
|
|
||||||
animation: 5s span2 infinite linear
|
|
||||||
}
|
|
||||||
|
|
||||||
.form span:nth-child(3) {
|
|
||||||
background: #800080;
|
|
||||||
right: -48%;
|
|
||||||
top: 0;
|
|
||||||
animation: 5s span3 infinite linear
|
|
||||||
}
|
|
||||||
|
|
||||||
.form span:nth-child(4) {
|
|
||||||
background: #f00;
|
|
||||||
bottom: 0;
|
|
||||||
right: -48%;
|
|
||||||
animation: 5s span4 infinite linear;
|
|
||||||
animation-delay: 1s
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes span1 {
|
|
||||||
0% {
|
|
||||||
top: -48%;
|
|
||||||
left: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
25% {
|
|
||||||
top: -48%;
|
|
||||||
left: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
top: 98%;
|
|
||||||
left: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
75% {
|
|
||||||
top: 98%;
|
|
||||||
left: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
top: -48%;
|
|
||||||
left: -48%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes span2 {
|
|
||||||
0% {
|
|
||||||
bottom: -48%;
|
|
||||||
right: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
25% {
|
|
||||||
bottom: -48%;
|
|
||||||
right: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
bottom: 98%;
|
|
||||||
right: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
75% {
|
|
||||||
bottom: 98%;
|
|
||||||
right: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
bottom: -48%;
|
|
||||||
right: -48%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes span3 {
|
|
||||||
0% {
|
|
||||||
top: -48%;
|
|
||||||
left: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
25% {
|
|
||||||
top: -48%;
|
|
||||||
left: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
top: 98%;
|
|
||||||
left: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
75% {
|
|
||||||
top: 98%;
|
|
||||||
left: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
top: -48%;
|
|
||||||
left: -48%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes span4 {
|
|
||||||
0% {
|
|
||||||
bottom: -48%;
|
|
||||||
right: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
25% {
|
|
||||||
bottom: -48%;
|
|
||||||
right: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
bottom: 98%;
|
|
||||||
right: 98%
|
|
||||||
}
|
|
||||||
|
|
||||||
75% {
|
|
||||||
bottom: 98%;
|
|
||||||
right: -48%
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
bottom: -48%;
|
|
||||||
right: -48%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="form" method="post" th:action="@{/login}">
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
<div class="form-inner">
|
|
||||||
<h2>登录界面</h2>
|
|
||||||
<div class="content">
|
|
||||||
<label>
|
|
||||||
<input class="input" name="username" placeholder="用户名" type="text" value="admin"/>
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<input class="input" name="password" placeholder="密码" type="password" value="admin"/>
|
|
||||||
</label>
|
|
||||||
<button class="btn">登录</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,10 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>订单内容</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>订单内容</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,20 +0,0 @@
|
||||||
package cn.bunny.springdemo;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class SpringDemoApplicationTests {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
PasswordEncoder passwordEncoder;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
String s = passwordEncoder.encode("admin123");
|
|
||||||
System.out.println(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package cn.bunny.springdemo.controller;
|
|
||||||
|
|
||||||
import org.hamcrest.Matchers;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
|
||||||
|
|
||||||
@WebMvcTest(HomeController.class)
|
|
||||||
class HomeControllerTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void index() throws Exception {
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get("/"))// 访问路径
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())// 判断状态是否成功
|
|
||||||
.andExpect(MockMvcResultMatchers.view().name("index"))// 判断视图名称是否是index
|
|
||||||
.andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("欢迎。。。")));// 是否包含字段
|
|
||||||
}
|
|
||||||
}
|
|