SpringBoot和SpringDataJpa實現登錄註冊功能

前言

今天想簡單使用Spring Data Jpa做一個RESTful的接口

實現的功能

  1. 教師註冊
  2. 教師登錄

項目結構

項目架構

依賴包

 <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進行接口測試

教師註冊

手機號不合法

手機號不合法

密碼不合法

密碼不合法

用戶已經存在

用戶已經存在

註冊成功

註冊成功

教師登錄

賬戶不存在或密碼錯誤

手機號錯誤

登錄成功

登錄成功

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章