优化任务6

This commit is contained in:
many2many 2024-05-12 16:58:58 +08:00
parent 7d60d2293d
commit ea5ddff70f
6 changed files with 202 additions and 97 deletions

View File

@ -102,18 +102,6 @@ public class ResultUtil {
}
```
#### 5. 自定义API接口版本号
在application.yml配置文件中添加如下配置
```yaml
app:
version: v1
default:
head-icon: https://assets.paopao.info/public/avatar/default/joshua.png
```
### 技术/工具需求:
- [列出完成任务所需的技术栈、工具、软件版本等。]

View File

@ -1,35 +1,29 @@
## 任务名称: 实现注册接口
#### 目标:
### 目标:
- 掌握Restful API设计
- 掌握RestController类的使用
- 掌握JPA Entity类的使用
- 掌握JPA Repository接口的使用
#### 预备知识:
### 预备知识:
- Restful API设计
- JPA
#### 操作步骤:
##### 1. 创建RestController类AuthController
```java
package com.lk.paopao.controller;
### 操作步骤:
@RestController
@RequestMapping("${app.version}/auth")
public class AuthController {
@Autowired
AuthService authService;
@PostMapping("/register")
public DataResult<User> register(@RequestBody RegisterRequest req) {
User saved = authService.register(req);
return ResultUtil.ok(saved);
}
}
#### 1. 撰写注册接口的API文档
使用模板[API接口说明模板](../API接口说明模板.md),根据演示站点的实际请求和回应填写API接口说明模板。
#### 2. 自定义配置
在配置文件中设置接口的版本号用户的缺省头像地址。在application.yml配置文件中添加如下配置
```yaml
app:
version: v1
default:
head-icon: https://assets.paopao.info/public/avatar/default/joshua.png
```
##### 2. 创建请求类RegisterRequest
#### 3. 创建请求类RegisterRequest
根据注册api接口说明文档,前端通过post方式在请求体中携带用户帐号和密码信息创建请求类RegisterRequest来获取用户帐号和密码信息。
```java
package com.lk.paopao.dto.rest.request;
@ -41,11 +35,20 @@ public class RegisterRequest {
}
```
##### 3. 创建实体类User
#### 4. 创建实体类User
基于需求分析获得用户实体类User。
```java
package com.lk.paopao.domain;
package com.lk.paopao.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Comment;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Getter
@Setter
@ -64,22 +67,18 @@ public class User {
private Long id;
@Comment("昵称")
@ColumnDefault("")
@Column(name = "nickname", nullable = false, length = 32)
@Column(name = "nickname", length = 32)
private String nickname;
@Comment("用户名")
@ColumnDefault("")
@Column(name = "username", nullable = false, length = 32)
private String username;
@Comment("手机号")
@ColumnDefault("")
@Column(name = "phone", length = 16)
private String phone;
@Comment("密码")
@ColumnDefault("")
@Column(name = "password", nullable = false, length = 32)
private String password;
@ -88,12 +87,11 @@ public class User {
private Byte status = 1;
@Comment("用户头像")
@ColumnDefault("")
@Column(name = "avatar", nullable = false)
private String avatar;
@Comment("是否管理员")
@Column(name = "is_admin")
@Column(name = "is_admin",nullable = false)
private Boolean isAdmin = false;
@Comment("创建时间")
@ -107,9 +105,8 @@ public class User {
private Long modifiedOn;
@Comment("删除时间")
@ColumnDefault("0")
@Column(name = "deleted_on", nullable = false)
private Long deletedOn = 0L;
@Column(name = "deleted_on")
private Long deletedOn;
@Comment("是否删除 0 为未删除、1 为已删除")
@Column(name = "is_del")
@ -118,26 +115,95 @@ public class User {
}
```
##### 4. 创建接口UserRepository
**代码中使用的注解:**
- **`@Getter`** 和 **`@Setter`**: Lombok库提供的注解自动生成类的getter和setter方法减少样板代码。
- **`@Comment`**: Hibernate的注解为实体类或其属性添加注释说明通常用于ORM映射时的描述。
- **`@Entity`**: 表示这个类是一个JPA实体映射到数据库中的一个表。
- **`@Table`**: 指定实体类映射到的数据库表的名称,以及表的索引和唯一性约束。
- `name`: 映射到的表的名称。
- `indexes`: 定义表的索引,提高查询效率。
- `uniqueConstraints`: 定义表的唯一性约束,确保列的组合在表中是唯一的。
- **`@EntityListeners(AuditingEntityListener.class)`**: 指定实体类要使用的实体监听器,`AuditingEntityListener`用于自动维护实体的创建时间和修改时间。
- **`@Id`**: 标记实体类中的属性作为数据库表的主键。
- **`@GeneratedValue(strategy = GenerationType.IDENTITY)`**: 指定主键的生成策略,`IDENTITY`表示使用数据库的自增ID。
- **`@Column`**: 用于映射实体类属性到数据库表的列。
- `name`: 映射到的列的名称。
- `nullable`: 指定列是否可以为null。
- `length`: 指定列的最大长度。
- **`@CreatedDate`** 和 **`@LastModifiedDate`**: Spring Data JPA提供的注解用于自动维护实体的创建时间和最后修改时间。
**关于实体类中的自动生成时间**
> 阅读[JPA审计](../guides/JPA审计.md)
**在项目的启动类中,添加@EnableJpaAuditing注解, 启用JPA审计功能。**
```java
package com.lk.paopao;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication
@EnableJpaAuditing
public class PaopaoApplication {
public static void main(String[] args) {
SpringApplication.run(PaopaoApplication.class, args);
}
}
```
#### 5. 创建JPA接口 UserRepository
为用户实体类User创建JPA接口UserRepository。 并提供一个根据用户帐号查询用户的方法。
```java
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
```
##### 5. 创建AuthService
**代码解释:**
- `JpaRepository<User, Long>`: UserRepository继承自JpaRepository接口需要指定实体类和主键类型。
- `Optional<User> findByUsername(String username)`: 这是一个JPA查询方法用于根据用户名查询用户这是使用了基于命名的查询jpa的命名查询会根据方法名自动生成SQL语句。
- `Optional`: 这是一个Java8提供的新类型用于表示可能为空的值。
#### 6. 创建AuthService
AuthService类用于实现用户注册、登录等认证相关功能。
```java
package com.lk.paopao.service;
import com.lk.paopao.dto.rest.request.RegisterRequest;
import com.lk.paopao.entity.User;
import com.lk.paopao.exception.ResourceExistedException;
import com.lk.paopao.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class AuthService {
// 注入用户实体的数据库接口
@Autowired
PasswordEncoder encoder; // 自动注入密码编码器
@Autowired
UserRepository userRepository; // 自动注入用户仓库
UserRepository userRepository;
// 从配置文件中读取默认头像地址
@Value("${app.default.head-icon}")
private String DEFAULT_HEAD_ICON; // 从配置文件中读取默认头像地址
private String DEFAULT_HEAD_ICON;
/**
* 用户注册。
@ -145,21 +211,70 @@ public class AuthService {
* @return 注册后的用户信息
*/
public User register(RegisterRequest reg) {
// 检查用户是否已存在
userRepository.findByUsername(reg.getUsername()).ifPresent((u)-> {throw new ResourceNotFoundException("","");});
// 检查用户是否已存在,如果存在则抛出异常
userRepository.findByUsername(reg.getUsername()).orElseThrow(() -> new ResourceExistedException("User","useranme="+reg.getUsername()));
// 创建用户对象并设置信息
User user = new User();
user.setPassword(encoder.encode(reg.getPassword())); // 编码密码
user.setAvatar(DEFAULT_HEAD_ICON); // 设置默认头像
user.setNickname(reg.getUsername()); // 设置昵称为用户名
user.setUsername(reg.getUsername()); // 设置用户名
return userRepository.save(user); // 保存用户到数据库
// 设置密码,暂时使用明文密码
user.setPassword(reg.getPassword());
// 设置昵称为用户名
user.setUsername(reg.getUsername());
// 设置昵称为用户名
user.setNickname(reg.getUsername());
// 设置默认头像
user.setAvatar(DEFAULT_HEAD_ICON);
// 在数据库中创建用户
return userRepository.save(user);
}
}
```
**代码中使用的注解:**
- **`@Service`**: 用于标识一个服务类,用于定义业务逻辑。
- **`@Transactional`**: 用于标识一个事务方法,用于确保方法中的所有数据库操作在一个事务中执行,要么都成功,要么都失败。
- **`@Autowired`**: 用于自动装配依赖。
- **`@Value`**: 用于从配置文件中读取属性值。
##### 6. 测试
#### 7. 创建RestController类AuthController
```java
package com.lk.paopao.controller;
import com.lk.paopao.dto.rest.request.RegisterRequest;
import com.lk.paopao.dto.rest.response.DataResult;
import com.lk.paopao.dto.rest.response.ResultUtil;
import com.lk.paopao.entity.User;
import com.lk.paopao.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("${app.version}/auth")
public class AuthController {
@Autowired
AuthService authService;
/**
* 处理用户注册请求。
* @param req 包含用户注册信息的请求体。
* @return 返回注册结果,包括注册成功的用户信息。
*/
@PostMapping("/register")
public DataResult<User> register(@RequestBody RegisterRequest req) {
User saved = authService.register(req);
return ResultUtil.ok(saved);
}
}
```
**代码中使用的注解:**
- **`@RestController`**: 用于标识一个RESTful控制器用于处理RESTful请求。
- **`@RequestMapping`**: 用于映射请求路径。
- **`@PostMapping`**: 用于映射POST请求。**`@PostMapping("/register")`**: 映射POST请求到/register路径。
- **`@Autowired`**: 用于自动装配依赖。
- **`@RequestBody`**: 用于从请求体中获取请求参数。
#### 8. 测试
http://localhost:8080/api-docs

View File

@ -17,10 +17,14 @@ public class AuthController {
@Autowired
AuthService authService;
/**
* 处理用户注册请求
* @param req 包含用户注册信息的请求体
* @return 返回注册结果包括注册成功的用户信息
*/
@PostMapping("/register")
public DataResult<User> register(@RequestBody RegisterRequest req) {
User saved = authService.register(req);
return ResultUtil.ok(saved);
}
}

View File

@ -3,7 +3,6 @@ package com.lk.paopao.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Comment;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
@ -38,7 +37,6 @@ public class User {
private String phone;
@Comment("密码")
@ColumnDefault("")
@Column(name = "password", nullable = false, length = 32)
private String password;
@ -51,7 +49,7 @@ public class User {
private String avatar;
@Comment("是否管理员")
@Column(name = "is_admin")
@Column(name = "is_admin",nullable = false)
private Boolean isAdmin = false;
@Comment("创建时间")
@ -65,9 +63,8 @@ public class User {
private Long modifiedOn;
@Comment("删除时间")
@ColumnDefault("0")
@Column(name = "deleted_on")
private Long deletedOn = 0L;
private Long deletedOn;
@Comment("是否删除 0 为未删除、1 为已删除")
@Column(name = "is_del")

View File

@ -3,6 +3,7 @@ package com.lk.paopao.service;
import com.lk.paopao.dto.rest.request.RegisterRequest;
import com.lk.paopao.entity.User;
import com.lk.paopao.exception.ResourceExistedException;
import com.lk.paopao.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -12,13 +13,12 @@ import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class AuthService {
// @Autowired
// PasswordEncoder encoder; // 自动注入密码编码器
// 注入用户实体的数据库接口
@Autowired
UserRepository userRepository; // 自动注入用户仓库
UserRepository userRepository;
// 从配置文件中读取默认头像地址
@Value("${app.default.head-icon}")
private String DEFAULT_HEAD_ICON; // 从配置文件中读取默认头像地址
private String DEFAULT_HEAD_ICON;
/**
* 用户注册
@ -26,17 +26,19 @@ public class AuthService {
* @return 注册后的用户信息
*/
public User register(RegisterRequest reg) {
// 检查用户是否已存在
if(userRepository.findByUsername(reg.getUsername()).isPresent()){
return null;
}
// 检查用户名是否已存在,如果存在则抛出异常
userRepository.findByUsername(reg.getUsername()).orElseThrow(() -> new ResourceExistedException("User","useranme="+reg.getUsername()));
// 创建用户对象并设置信息
User user = new User();
// user.setPassword(encoder.encode(reg.getPassword())); // 编码密码
user.setAvatar(DEFAULT_HEAD_ICON); // 设置默认头像
user.setNickname(reg.getUsername()); // 设置昵称为用户名
user.setUsername(reg.getUsername()); // 设置用户名
// 设置密码,暂时使用明文密码
user.setPassword(reg.getPassword());
return userRepository.save(user); // 保存用户到数据库
// 设置昵称为用户名
user.setUsername(reg.getUsername());
// 设置昵称为用户名
user.setNickname(reg.getUsername());
// 设置默认头像
user.setAvatar(DEFAULT_HEAD_ICON);
// 在数据库中创建用户
return userRepository.save(user);
}
}

View File

@ -4,11 +4,10 @@ springdoc:
spring:
datasource:
url: jdbc:h2:file:./paopao.h2
url: jdbc:h2:file:./paopao.h2 # 使用文件存储
driverClassName: org.h2.Driver
username: root
password: root
# initialization-mode: always
h2:
console: # 开启console访问 默认false
enabled: true
@ -22,11 +21,11 @@ spring:
defer-datasource-initialization: true
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create-drop # update create-drop
ddl-auto: create-drop
# 可选值create-drop,create,update,none. create-drop每次启动项目都会删除表然后重新创建表适合开发环境create每次启动项目都会创建表适合开发环境update每次启动项目都会更新表适合开发环境none不执行任何操作适合生产环境。
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.H2Dialect
app:
version: v1