feat: Spring实战学习
|
@ -9,6 +9,7 @@
|
||||||
<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,6 +6,7 @@
|
||||||
<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 @@
|
||||||
# `SpringMVC`笔记
|
# `Spring`笔记
|
||||||
|
|
||||||
- 公共AI网站:https://chatgptplus.cn/
|
- 公共AI网站:https://chatgptplus.cn/
|
||||||
- vue3官网:https://cn.vuejs.org/
|
- vue3官网:https://cn.vuejs.org/
|
||||||
|
@ -147,6 +147,90 @@ 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>
|
||||||
|
```
|
||||||
|
|
||||||
## 访问控制
|
## 访问控制
|
||||||
|
|
||||||
请求地址时返回对应的网页文件
|
请求地址时返回对应的网页文件
|
||||||
|
@ -501,17 +585,13 @@ public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
`SessionInterceptor` 可以用于监控和管理 Session 数据。
|
`SessionInterceptor` 可以用于监控和管理 Session 数据。
|
||||||
|
|
||||||
### 8. **总结**
|
> 在 Spring MVC 中,向 Session 共享数据主要有以下几种方式:
|
||||||
|
>
|
||||||
在 Spring MVC 中,向 Session 共享数据主要有以下几种方式:
|
> - **`HttpSession`**:通过 `HttpSession` 对象存储和读取 Session 数据。
|
||||||
|
> - **`@SessionAttributes`**:通过 `@SessionAttributes` 注解将模型属性添加到 Session 中。
|
||||||
- **`HttpSession`**:通过 `HttpSession` 对象存储和读取 Session 数据。
|
> - **`@ModelAttribute`**:结合 `@SessionAttributes` 使用,将模型数据持久化到 Session 中。
|
||||||
- **`@SessionAttributes`**:通过 `@SessionAttributes` 注解将模型属性添加到 Session 中。
|
> - **`@RequestParam` 和 `@PathVariable`**:将请求参数或路径变量存储到 Session 中。
|
||||||
- **`@ModelAttribute`**:结合 `@SessionAttributes` 使用,将模型数据持久化到 Session 中。
|
> - **Session 过期与清理**:可以通过配置控制会话超时,或手动清除 Session 数据。
|
||||||
- **`@RequestParam` 和 `@PathVariable`**:将请求参数或路径变量存储到 Session 中。
|
|
||||||
- **Session 过期与清理**:可以通过配置控制会话超时,或手动清除 Session 数据。
|
|
||||||
|
|
||||||
Spring MVC 提供的 Session 管理机制非常灵活,能够满足各种需求。
|
|
||||||
|
|
||||||
## 向application域共享数据
|
## 向application域共享数据
|
||||||
|
|
||||||
|
@ -656,14 +736,11 @@ public class AppConfig {
|
||||||
|
|
||||||
在这种情况下,Spring 管理的 Bean 会在应用级别共享,类似于 `ServletContext` 中存储的数据。
|
在这种情况下,Spring 管理的 Bean 会在应用级别共享,类似于 `ServletContext` 中存储的数据。
|
||||||
|
|
||||||
### 6. **总结**
|
> - `Application` 域(即 `ServletContext`)用于在整个应用程序范围内共享数据,适合存储全局共享的信息、配置和常量。
|
||||||
|
> - 通过 `HttpServletRequest.getServletContext()` 或 `@Autowired` 注解可以访问 `ServletContext` 并向 `Application` 域中共享数据。
|
||||||
- `Application` 域(即 `ServletContext`)用于在整个应用程序范围内共享数据,适合存储全局共享的信息、配置和常量。
|
> - 数据存储在 `Application` 域中可以在整个应用程序生命周期内有效,适用于共享全局性的、无需频繁更新的数据。
|
||||||
- 通过 `HttpServletRequest.getServletContext()` 或 `@Autowired` 注解可以访问 `ServletContext` 并向 `Application` 域中共享数据。
|
> - 应谨慎存储敏感数据,并注意线程安全和数据的生命周期。
|
||||||
- 数据存储在 `Application` 域中可以在整个应用程序生命周期内有效,适用于共享全局性的、无需频繁更新的数据。
|
>
|
||||||
- 应谨慎存储敏感数据,并注意线程安全和数据的生命周期。
|
|
||||||
|
|
||||||
通过合理地使用 `Application` 域,你可以实现全局共享的数据管理,并且不需要担心会话或请求的生命周期问题。
|
|
||||||
|
|
||||||
## 重定向和转发使用
|
## 重定向和转发使用
|
||||||
|
|
||||||
|
@ -851,12 +928,325 @@ 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快速入门
|
||||||
|
|
||||||
|
@ -1117,15 +1507,18 @@ Thymeleaf 是一种现代化的 Java 模板引擎,广泛用于生成 HTML、XM
|
||||||
|
|
||||||
- 设置 `input` 的 `placeholder` 为 `${placeholderText}` 的值。
|
- 设置 `input` 的 `placeholder` 为 `${placeholderText}` 的值。
|
||||||
|
|
||||||
------
|
### 23. **`th:errors`**
|
||||||
|
|
||||||
### 总结
|
显示与 `username` 属性相关的错误信息。如果 `username` 为空或者不符合验证规则,这里就会显示出相应的错误消息。
|
||||||
|
|
||||||
Thymeleaf 提供了许多强大的指令来处理模板中的动态内容、条件渲染、迭代和属性绑定。常见的指令包括:
|
```html
|
||||||
|
<div th:errors="*{email}"></div> <!-- 错误信息展示 -->
|
||||||
|
```
|
||||||
|
|
||||||
- `th:text`、`th:utext`:用于设置文本内容。
|
你还可以通过 `th:errors` 对错误消息进行自定义格式化。例如,使用 `*{field}` 可以获取字段的错误信息。
|
||||||
- `th:each`:用于循环遍历。
|
|
||||||
- `th:if`、`th:unless`:用于条件判断。
|
```html
|
||||||
- `th:attr`、`th:id`、`th:class`:用于设置 HTML 属性。
|
<div th:errors="*{username}">Error</div>
|
||||||
- `th:replace`、`th:include`:用于片段包含。
|
```
|
||||||
- `th:switch`、`th:case`:用于类似 `switch` 的条件语句。
|
|
||||||
|
如果验证失败,错误消息将显示在 `<div>` 中。如果没有错误,它会显示默认的 "Error" 文本。
|
|
@ -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("家庭理财管理系统").description("家庭理财管理系统").version("v1.0.0").contact(contact).license(license).termsOfService("MIT");
|
Info info = new Info().title("Spring MVC").description("Spring MVC 学习").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,32 @@
|
||||||
|
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)
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?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>
|
||||||
|
</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>
|
||||||
|
<!-- 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>
|
||||||
|
|
||||||
|
</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>
|
|
@ -0,0 +1,11 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
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
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>400</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>400</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>404</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>404</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,64 @@
|
||||||
|
<!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>
|
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 326 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,12 @@
|
||||||
|
<!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,10 +1,10 @@
|
||||||
package cn.bunny.mvc;
|
package cn.bunny.springdemo;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class MvcApplicationTests {
|
class SpringDemoApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {
|
void contextLoads() {
|
|
@ -0,0 +1,24 @@
|
||||||
|
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("欢迎。。。")));// 是否包含字段
|
||||||
|
}
|
||||||
|
}
|