前言
今天想簡單使用Spring Data Jpa做一個RESTful的接口
實現的功能
- 教師註冊
- 教師登錄
項目結構
依賴包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
JPA配置
server:
port: 8888
servlet:
context-path: /api
spring:
jackson:
time-zone: GMT+8
jpa:
generate-ddl: true
database: mysql
show-sql: true
open-in-view: true
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: create
datasource:
url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai
username: root
password: ABCabc_123456
driver-class-name: com.mysql.cj.jdbc.Driver
實體 Entity
Teacher.java
@Entity
@Table(name = "tbl_teacher")
@Getter
@Setter
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "mobile",length = 11,unique = true,nullable = false)
private String mobile;
@Column(name = "password",length = 64)
private String password;
@Column(name = "nickname",length = 30)
private String nickname;
@Column(name = "birth")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
@Column(name = "gender",length = 1,columnDefinition = "tinyint default 0")
private Integer gender;
@Column(name = "create_time",columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP",insertable = false,updatable = false)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Generated ( GenerationTime.INSERT )
private Timestamp createTime;
@Column(name = "update_time",columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP",insertable = false)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Generated ( GenerationTime.ALWAYS )
private Timestamp updateTime;
}
數據訪問對象 DAO
TeacherDao.java
@Repository
public interface TeacherDao extends JpaRepository<Teacher,Integer>, JpaSpecificationExecutor<Teacher> {
// 用戶登錄
Optional<Teacher> findTeacherByMobile(String mobile);
}
數據傳輸對象 DTO
RegisterDto.java
@Getter
@Setter
public class RegisterDto {
@JsonProperty(value = "id")
private Integer id;
@JsonProperty(value = "mobile")
private String mobile;
@JsonProperty(value = "password")
private String password;
@JsonProperty(value = "nickname")
private String nickname;
// 默認用戶不存在
@JsonProperty(value = "ifExist")
private Boolean ifExist = false;
// 默認爲合法
@JsonProperty(value = "ifIllegal")
private Boolean ifIllegal = true;
}
LoginDto.java
@Getter
@Setter
public class LoginDto {
@JsonProperty(value = "id")
private Integer id;
@JsonProperty(value = "mobile")
private String mobile;
@JsonProperty(value = "password")
private String password;
// 默認用戶存在
@JsonProperty(value = "ifExist")
private Boolean ifExist = true;
// 如果手機號和密碼正確,默認爲合法
@JsonProperty(value = "ifIllegal")
private Boolean ifIllegal = true;
}
業務邏輯 Service
TeacherService.java
public interface TeacherService {
// 教師註冊
RegisterDto register(RegisterDto dto);
// 教師登錄
LoginDto login(LoginDto dto);
}
TeacherServiceImpl.java
@Service
public class TeacherServiceImpl implements TeacherService {
final TeacherDao teacherDao;
@Autowired
public TeacherServiceImpl(TeacherDao teacherDao) {
this.teacherDao = teacherDao;
}
@Override
public RegisterDto register(RegisterDto dto) {
// 判斷手機號和密碼是否合法
if ( !(PatternUtil.isMobile ( dto.getMobile () ) && PatternUtil.isPassword ( dto.getPassword () )) ) {
dto.setIfIllegal ( false );
return dto;
}
// sha256加密
dto.setPassword ( DigestUtils.sha256Hex (dto.getPassword ()) );
ModelMapper modelMapper = new ModelMapper ();
// 根據手機號查詢用戶
Optional<Teacher> one = teacherDao.findTeacherByMobile ( dto.getMobile () );
// 如果查詢結果不爲空,則已經註冊
if (one.isPresent ()) {
RegisterDto ret = modelMapper.map ( one.get (), RegisterDto.class );
ret.setIfExist ( true );
return ret;
}
// 如果結果爲空,那麼創建新的實體
// 根據dto映射實體類
Teacher teacher = modelMapper.map ( dto, Teacher.class );
// 默認insert DML不會返回實體,需要進行一次select返回實體
return modelMapper.map ( teacherDao.save ( teacher ), RegisterDto.class );
}
@Override
public LoginDto login(LoginDto dto) {
if ( !(PatternUtil.isMobile ( dto.getMobile () ) && PatternUtil.isPassword ( dto.getPassword () )) ) {
dto.setIfIllegal ( false );
dto.setIfExist ( false );
return dto;
}
ModelMapper modelMapper = new ModelMapper ();
// 根據手機號查詢用戶
Optional<Teacher> one = teacherDao.findTeacherByMobile ( dto.getMobile () );
// 如果查詢結果爲空,則不存在該手機號
if (one.isEmpty ()) {
LoginDto ret = modelMapper.map ( one.orElseGet ( Teacher::new ), LoginDto.class );
ret.setIfExist ( false );
return ret;
}
// 如果查詢結果不爲空,但是密碼和查詢結果不同,則密碼錯誤
else {
// 數據庫中加密後的密碼與dto中加密後的密碼是否相同
if (!one.get ().getPassword ().equals ( DigestUtils.sha256Hex (dto.getPassword ()) )) {
LoginDto ret = modelMapper.map ( one.orElseGet ( Teacher::new ), LoginDto.class );
ret.setIfExist ( false );
return ret;
}
}
// 如果手機號密碼都正確,返回
return modelMapper.map ( one.orElseGet ( Teacher::new ), LoginDto.class );
}
}
控制層Controller
TeacherController.java
@RestController
@RequestMapping("teacher")
public class TeacherController {
final TeacherService teacherService;
@Autowired
public TeacherController(TeacherService teacherService) {
this.teacherService = teacherService;
}
@PostMapping("register")
public ResponseEntity<RegisterDto> teacherRegister(@RequestBody RegisterDto dto) {
RegisterDto register = teacherService.register ( dto );
if (register.getIfExist ()) return new ResponseEntity<> ( register, HttpStatus.OK );
// 返回狀態碼201,表示註冊了一個新的資源
return new ResponseEntity<> ( register, HttpStatus.CREATED );
}
@PostMapping("login")
public ResponseEntity<LoginDto> teacherLogin(@RequestBody LoginDto dto) {
return new ResponseEntity<> ( teacherService.login ( dto ), HttpStatus.OK );
}
}
工具類Util
PatternUtil.java
public class PatternUtil {
// 手機號正則
public static boolean isMobile(String mobile) {
String regex = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3])|(17[5-8])|(18[0-9])|166|198|199|(147))\\d{8}$";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(mobile);
return m.matches();
}
// 密碼正則: 大寫字母+小寫字母+數字+下劃線
public static boolean isPassword(String password) {
String regex = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[_]).{8,}$";
Pattern p = Pattern.compile ( regex, Pattern.CASE_INSENSITIVE );
Matcher m = p.matcher ( password );
return m.matches ();
}
}
接口測試
使用postman進行接口測試