当前位置: 首页 > news >正文

开始尝试从0写一个项目--后端(一)

创建文件的目录结构

利用这个界面创建

序号

名称

说明

1

SEMS

maven父工程,统一管理依赖版本,聚合其他子模块

2

sems-common

子模块,存放公共类,例如:工具类、常量类、异常类等

3

sems-pojo

子模块,存放实体类、VO、DTO等

4

sems-server

子模块,后端服务,存放配置文件、Controller、Service、Mapper等

配置pom文件

文件路径:SEMS\pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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>2.7.3</version></parent><groupId>com.ljc</groupId><artifactId>SEMS</artifactId><packaging>pom</packaging><version>0.0.1-SNAPSHOT</version><modules><module>sems-common</module><module>sems-pojo</module><module>sems-server</module></modules><!--它定义了一系列项目依赖的版本号--><properties><mybatis.spring>2.2.0</mybatis.spring><lombok>1.18.20</lombok><fastjson>1.2.76</fastjson><commons.lang>2.6</commons.lang><druid>1.2.1</druid><pagehelper>1.3.0</pagehelper><aliyun.sdk.oss>3.10.2</aliyun.sdk.oss><knife4j>3.0.2</knife4j><aspectj>1.9.4</aspectj><jjwt>0.9.1</jjwt><jaxb-api>2.3.1</jaxb-api><poi>3.16</poi></properties><dependencyManagement><dependencies><!--mybatis的依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.spring}</version></dependency><!--Lombok 是一个 Java 库,用于自动化生成如 getter、setter、toString 等方法--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok}</version></dependency><!--一个 Java 语言编写的高性能功能完善的 JSON 库--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson}</version></dependency><!--一个包含大量静态方法的库,用于处理 Java 核心 API 中没有的常用功能--><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>${commons.lang}</version></dependency><!--阿里巴巴开源的数据库连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid}</version></dependency><!--MyBatis 分页插件--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pagehelper}</version></dependency><!--Swagger 的增强 UI 实现,用于 API 文档生成--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>${knife4j}</version></dependency><!--AspectJ 是一个面向切面的编程(AOP)框架--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>${aspectj}</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>${aspectj}</version></dependency><!--Java JWT(JSON Web Tokens)库,用于生成和解析 JWT 令牌--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>${jjwt}</version></dependency><!--阿里云对象存储服务(OSS)的 Java SDK--><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>${aliyun.sdk.oss}</version></dependency><!--用于将 Java 类映射到 XML 表示--><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>${jaxb-api}</version></dependency><!-- poi --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>${poi}</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>${poi}</version></dependency></dependencies></dependencyManagement>
</project>

SEMS\sems-server\pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.ljc</groupId><artifactId>SEMS</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>sems-server</artifactId><dependencies><dependency><groupId>com.ljc</groupId><artifactId>sems-common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.ljc</groupId><artifactId>sems-pojo</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><scope>compile</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId></dependency><!-- poi --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

SEMS\sems-pojo\pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.ljc</groupId><artifactId>SEMS</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>sems-pojo</artifactId><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.2</version></dependency><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId></dependency></dependencies>
</project>

SEMS\sems-common\pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.ljc</groupId><artifactId>SEMS</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>sems-common</artifactId><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency><!--支持配置属性类,yml文件中可以提示配置项--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId></dependency><!--微信支付--><dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-apache-httpclient</artifactId><version>0.4.9</version></dependency></dependencies>
</project>

配置好后需要点击这个编译一下,显示成功才可继续后面的

配置git环境上传到仓库,反之代码丢失

在各自对应的结构下构建相应的目录结构

名称

说明

constant

存放相关常量类

context

存放上下文类

enumeration

项目的枚举类存储

exception

存放自定义异常类

json

处理json转换的类

properties

存放SpringBoot相关的配置属性类

result

返回结果类的封装

utils

常用工具类

名称

说明

Entity

实体,通常和数据库中的表对应

DTO

数据传输对象,通常用于程序中各层之间传递数据

VO

视图对象,为前端展示数据提供的对象

POJO

普通Java对象,只有属性和对应的getter和setter

名称

说明

config

存放配置类

controller

存放controller类

interceptor

存放拦截器类

mapper

存放mapper接口

service

存放service类

SemsApplication

启动类

配置application.yml文件

sems-server/src/main/resources/application.yml

server:port: 8080spring:profiles:active: devmain:allow-circular-references: truedatasource:druid:driver-class-name: ${ljc.datasource.driver-class-name}url: jdbc:mysql://${ljc.datasource.host}:${ljc.datasource.port}/${ljc.datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: ${ljc.datasource.username}password: ${ljc.datasource.password}mybatis:#mapper配置文件mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.ljc.entityconfiguration:#开启驼峰命名map-underscore-to-camel-case: truelogging:level:com:sky:mapper: debugservice: infocontroller: infoljc:jwt:# 设置jwt签名加密时使用的秘钥admin-secret-key: kussm# 设置jwt过期时间admin-ttl: 7200000# 设置前端传递过来的令牌名称admin-token-name: token

sems-server/src/main/resources/application-dev.yml

ljc:datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: semsusername: rootpassword: 8888

编写一些基础代码

1. 全局异常处理器,处理项目中抛出的业务异常

GlobalExceptionHandler(全局异常处理器)

sems-server\src\main\java\com\ljc\handler\GlobalExceptionHandler.java

package com.ljc.handler;import com.ljc.exception.BaseException;
import com.ljc.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 全局异常处理器,处理项目中抛出的业务异常*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {/*** 捕获业务异常* @param ex* @return*/@ExceptionHandlerpublic Result exceptionHandler(BaseException ex){log.error("异常信息:{}", ex.getMessage());return Result.error(ex.getMessage());}}

同时创建相关代码

BaseException(业务异常)

sems-common\src\main\java\com\ljc\exception\BaseException.java

package com.ljc.exception;/*** 业务异常*/
public class BaseException extends RuntimeException {public BaseException() {}public BaseException(String msg) {super(msg);}}

Result(后端统一返回结果)

sems-common\src\main\java\com\ljc\result\Result.java

package com.ljc.result;import lombok.Data;import java.io.Serializable;/*** 后端统一返回结果* @param <T>*/
@Data
public class Result<T> implements Serializable {private Integer code; //编码:1成功,0和其它数字为失败private String msg; //错误信息private T data; //数据public static <T> Result<T> success() {Result<T> result = new Result<T>();result.code = 1;return result;}public static <T> Result<T> success(T object) {Result<T> result = new Result<T>();result.data = object;result.code = 1;return result;}public static <T> Result<T> error(String msg) {Result result = new Result();result.msg = msg;result.code = 0;return result;}}

2. 配置类,注册web层相关组件JWT

注册自定义拦截器jwt

通过knife4j生成接口文档

设置静态资源映射

WebMvcConfiguration(配置类,注册web层相关组件)

sems-server\src\main\java\com\ljc\config\WebMvcConfiguration.java

package com.ljc.config;import com.ljc.interceptor.JwtTokenAdminInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;/*** 配置类,注册web层相关组件*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {@Autowiredprivate JwtTokenAdminInterceptor jwtTokenAdminInterceptor;/*** 注册自定义拦截器** @param registry*/protected void addInterceptors(InterceptorRegistry registry) {log.info("开始注册自定义拦截器...");registry.addInterceptor(jwtTokenAdminInterceptor).addPathPatterns("/admin/**").excludePathPatterns("/admin/student/login");}/*** 通过knife4j生成接口文档* @return*/@Beanpublic Docket docket() {ApiInfo apiInfo = new ApiInfoBuilder().title("体育器材项目接口文档").version("1.0").description("体育器材项目接口文档").build();Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage("com.ljc.controller")).paths(PathSelectors.any()).build();return docket;}/*** 设置静态资源映射* @param registry*/protected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}

3. 相关联的jwt令牌校验的拦截器

JwtTokenAdminInterceptor

sems-server\src\main\java\com\ljc\interceptor\JwtTokenAdminInterceptor.java

package com.ljc.interceptor;import com.ljc.constant.JwtClaimsConstant;
import com.ljc.properties.JwtProperties;
import com.ljc.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** jwt令牌校验的拦截器*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法,直接放行return true;}//1、从请求头中获取令牌String token = request.getHeader(jwtProperties.getAdminTokenName());//2、校验令牌try {log.info("jwt校验:{}", token);Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("当前员工id:", empId);//3、通过,放行return true;} catch (Exception ex) {//4、不通过,响应401状态码response.setStatus(401);return false;}}
}

4. 常量类(后面用)

JwtClaimsConstant

sems-common/src/main/java/com/ljc/constant/JwtClaimsConstant.java

package com.ljc.constant;public class JwtClaimsConstant {public static final String EMP_ID = "empId";public static final String USER_ID = "userId";public static final String PHONE = "phone";public static final String USERNAME = "username";public static final String NAME = "name";}

MessageConstant

sems-common/src/main/java/com/ljc/constant/MessageConstant.java

package com.ljc.constant;/*** 信息提示常量类*/
public class MessageConstant {public static final String PASSWORD_ERROR = "密码错误";public static final String ACCOUNT_NOT_FOUND = "账号不存在";public static final String ACCOUNT_LOCKED = "账号被锁定";public static final String UNKNOWN_ERROR = "未知错误";public static final String USER_NOT_LOGIN = "用户未登录";public static final String CATEGORY_BE_RELATED_BY_SETMEAL = "当前分类关联了套餐,不能删除";public static final String CATEGORY_BE_RELATED_BY_DISH = "当前分类关联了菜品,不能删除";public static final String SHOPPING_CART_IS_NULL = "购物车数据为空,不能下单";public static final String ADDRESS_BOOK_IS_NULL = "用户地址为空,不能下单";public static final String LOGIN_FAILED = "登录失败";public static final String UPLOAD_FAILED = "文件上传失败";public static final String SETMEAL_ENABLE_FAILED = "套餐内包含未启售菜品,无法启售";public static final String PASSWORD_EDIT_FAILED = "密码修改失败";public static final String DISH_ON_SALE = "起售中的菜品不能删除";public static final String SETMEAL_ON_SALE = "起售中的套餐不能删除";public static final String DISH_BE_RELATED_BY_SETMEAL = "当前菜品关联了套餐,不能删除";public static final String ORDER_STATUS_ERROR = "订单状态错误";public static final String ORDER_NOT_FOUND = "订单不存在";}

StatusConstant

sems-common/src/main/java/com/ljc/constant/StatusConstant.java

package com.ljc.constant;/*** 状态常量,启用或者禁用*/
public class StatusConstant {//启用public static final Integer ENABLE = 1;//禁用public static final Integer DISABLE = 0;
}

5. 异常类

AccountLockedException

sems-common/src/main/java/com/ljc/exception/AccountLockedException.java

package com.ljc.exception;/*** 账号被锁定异常*/
public class AccountLockedException extends BaseException {public AccountLockedException() {}public AccountLockedException(String msg) {super(msg);}}

AccountNotFoundException

sems-common/src/main/java/com/ljc/exception/AccountNotFoundException.java

package com.ljc.exception;/*** 账号不存在异常*/
public class AccountNotFoundException extends BaseException {public AccountNotFoundException() {}public AccountNotFoundException(String msg) {super(msg);}}

PasswordErrorException

sems-common/src/main/java/com/ljc/exception/PasswordErrorException.java

package com.ljc.exception;/*** 密码错误异常*/
public class PasswordErrorException extends BaseException {public PasswordErrorException() {}public PasswordErrorException(String msg) {super(msg);}}

6. 配置类

JwtProperties

sems-common/src/main/java/com/ljc/properties/JwtProperties.java

package com.ljc.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "ljc.jwt")
@Data
public class JwtProperties {/*** 管理端员工生成jwt令牌相关配置*/private String adminSecretKey;private long adminTtl;private String adminTokenName;/*** 用户端微信用户生成jwt令牌相关配置*/private String userSecretKey;private long userTtl;private String userTokenName;}

7. 实用工具

JwtUtil(生成jwt)

sems-common/src/main/java/com/ljc/utils/JwtUtil.java

package com.ljc.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;public class JwtUtil {/*** 生成jwt* 使用Hs256算法, 私匙使用固定秘钥** @param secretKey jwt秘钥* @param ttlMillis jwt过期时间(毫秒)* @param claims    设置的信息* @return*/public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 生成JWT的时间long expMillis = System.currentTimeMillis() + ttlMillis;Date exp = new Date(expMillis);// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);return builder.compact();}/*** Token解密** @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个* @param token     加密后的token* @return*/public static Claims parseJWT(String secretKey, String token) {// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}}

8. 阶段效果展示

现在就可以开始运行代码了

SemsApplication

sems-server/src/main/java/com/ljc/SemsApplication.java

package com.ljc;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
public class SemsApplication {public static void main(String[] args) {SpringApplication.run(SemsApplication.class, args);log.info("server started");}
}

打开浏览器输入:http://localhost:8080/doc.html

可以看到通过knife4j生成的初步接口文档,后面慢慢完善接口

学生管理--登录

接口设计

请求路径:/admin/student/login

请求方式:POST

设计数据库

student表为学生表,用于存储学生信息。具体表结构如下:

字段名

数据类型

说明

备注

id

bigint

主键

自增

name

varchar(32)

姓名

username

varchar(32)

用户名

唯一

password

varchar(64)

密码

phone

varchar(11)

手机号

sex

varchar(2)

性别

id_number

varchar(18)

身份证号

status

int

账号状态

1正常 0锁定

create_time

datetime

创建时间

update_time

datetime

最后修改时间

create_user

bigint

创建人id

update_user

bigint

最后修改人id

sql语句

DROP TABLE IF EXISTS student;
CREATE TABLE `employee` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '姓名',`username` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '用户名',`password` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '密码',`phone` varchar(11) COLLATE utf8_bin NOT NULL COMMENT '手机号',`sex` varchar(2) COLLATE utf8_bin NOT NULL COMMENT '性别',`id_number` varchar(18) COLLATE utf8_bin NOT NULL COMMENT '身份证号',`status` int NOT NULL DEFAULT '1' COMMENT '状态 0:禁用,1:启用',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL COMMENT '更新时间',`create_user` bigint DEFAULT NULL COMMENT '创建人',`update_user` bigint DEFAULT NULL COMMENT '修改人',PRIMARY KEY (`id`),UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='员工信息';INSERT INTO student VALUES (1,'管理员','admin','123456','13812312312','1','110101199001010047',1,'2022-02-15 15:51:20','2022-02-17 09:16:20',10,1);

设计接收和回传数据的DTO和VO结构以及和数据库对应的entity实体类

Student

sems-pojo/src/main/java/com/ljc/entity/Student.java

package com.ljc.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.time.LocalDateTime;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String username;private String name;private String password;private String phone;private String sex;private String idNumber;private Integer status;//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime updateTime;private Long createUser;private Long updateUser;}

StudentLoginDTO

sems-pojo/src/main/java/com/ljc/dto/StudentLoginDTO.java

package com.ljc.dto;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.io.Serializable;@Data
@ApiModel(description = "学生登录时传递的数据模型")
public class StudentLoginDTO implements Serializable {@ApiModelProperty("用户名")private String username;@ApiModelProperty("密码")private String password;
}

StudentLoginVO

sems-pojo/src/main/java/com/ljc/vo/StudentLoginVO.java

package com.ljc.vo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "学生登录返回的数据格式")
public class StudentLoginVO implements Serializable {@ApiModelProperty("主键值")private Long id;@ApiModelProperty("用户名")private String userName;@ApiModelProperty("姓名")private String name;@ApiModelProperty("jwt令牌")private String token;}

设计真正业务的代码

controller层-StudentController

sems-server/src/main/java/com/ljc/controller/student/StudentController.java

package com.ljc.controller.student;import com.ljc.constant.JwtClaimsConstant;
import com.ljc.dto.StudentLoginDTO;
import com.ljc.entity.Student;
import com.ljc.properties.JwtProperties;
import com.ljc.result.Result;
import com.ljc.service.StudentService;
import com.ljc.utils.JwtUtil;
import com.ljc.vo.StudentLoginVO;import lombok.extern.slf4j.Slf4j;
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;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/admin/student")
@Slf4j
public class StudentController {@Autowiredprivate StudentService studentService;@Autowiredprivate JwtProperties jwtProperties;/*** 登录** @param studentLoginDTO* @return*/@PostMapping("/login")public Result<StudentLoginVO> login(@RequestBody StudentLoginDTO studentLoginDTO) {log.info("学生登录:{}", studentLoginDTO);Student student = studentService.login(studentLoginDTO);//登录成功后,生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.EMP_ID, student.getId());String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);StudentLoginVO studentLoginVO = StudentLoginVO.builder().id(student.getId()).userName(student.getUsername()).name(student.getName()).token(token).build();return Result.success(studentLoginVO);}/*** 退出** @return*/@PostMapping("/logout")public Result<String> logout() {return Result.success();}
}

service层-StudentService

sems-server/src/main/java/com/ljc/service/StudentService.java

package com.ljc.service;import com.ljc.dto.StudentLoginDTO;
import com.ljc.entity.Student;public interface StudentService {/*** 学生登录* @param studentLoginDTO* @return*/Student login(StudentLoginDTO studentLoginDTO);}

service层-StudentServiceImpl

sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java

package com.ljc.service.impl;import com.ljc.constant.MessageConstant;
import com.ljc.constant.StatusConstant;
import com.ljc.dto.StudentLoginDTO;
import com.ljc.entity.Student;
import com.ljc.exception.AccountLockedException;
import com.ljc.exception.AccountNotFoundException;
import com.ljc.exception.PasswordErrorException;
import com.ljc.mapper.StudentMapper;
import com.ljc.service.StudentService;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper studentMapper;/*** 学生登录** @param studentLoginDTO* @return*/public Student login(StudentLoginDTO studentLoginDTO) {String username = studentLoginDTO.getUsername();String password = studentLoginDTO.getPassword();//1、根据用户名查询数据库中的数据Student student = studentMapper.getByUsername(username);//2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)if (student == null) {//账号不存在throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);}//密码比对// TODO 后期需要进行md5加密,然后再进行比对if (!password.equals(student.getPassword())) {//密码错误throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);}if (student.getStatus() == StatusConstant.DISABLE) {//账号被锁定throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);}//3、返回实体对象return student;}}

mapper层-StudentMapper

sems-server/src/main/java/com/ljc/mapper/StudentMapper.java

package com.ljc.mapper;import com.ljc.entity.Student;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface StudentMapper {/*** 根据用户名查询学生* @param username* @return*/@Select("select * from student where username = #{username}")Student getByUsername(String username);}

阶段结果展示

通过swagger测试

注意:我在运行中出现的一些问题:

基本就没什么问题了。

这样登录功能就搞定了!!!!!

目前为止整体结构

完善登录功能

学生表中的密码是明文存储,安全性太低

使用MD5加密方式对明文密码加密

”123456“进行MD5加密后结果为:

e10adc3949ba59abbe56e057f20f883e

进入数据库,修改密码为这个

修改代码

完整代码:

sems-server/src/main/java/com/ljc/service/impl/StudentServiceImpl.java

package com.ljc.service.impl;import com.ljc.constant.MessageConstant;
import com.ljc.constant.StatusConstant;
import com.ljc.dto.StudentLoginDTO;
import com.ljc.entity.Student;
import com.ljc.exception.AccountLockedException;
import com.ljc.exception.AccountNotFoundException;
import com.ljc.exception.PasswordErrorException;
import com.ljc.mapper.StudentMapper;
import com.ljc.service.StudentService;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;@Service
public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper studentMapper;/*** 学生登录** @param studentLoginDTO* @return*/public Student login(StudentLoginDTO studentLoginDTO) {String username = studentLoginDTO.getUsername();String password = studentLoginDTO.getPassword();//1、根据用户名查询数据库中的数据Student student = studentMapper.getByUsername(username);//2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)if (student == null) {//账号不存在throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);}//密码比对// 进行md5加密,然后再进行比对password = DigestUtils.md5DigestAsHex(password.getBytes());if (!password.equals(student.getPassword())) {//密码错误throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);}if (student.getStatus() == StatusConstant.DISABLE) {//账号被锁定throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);}//3、返回实体对象return student;}}

初步完成这样

相关文章:

  • 6.8应用进程跨网络通信
  • Airflow: 大数据调度工具详解
  • 0/1背包问题总结
  • 【Python机器学习】处理文本数据——将文本数据表示为词袋
  • 顶级5款有用的免费IntelliJ插件,提升你作为Java开发者的旅程
  • Redis 的过期策略
  • Node.js的下载、安装和配置
  • 房屋租赁管理小程序的设计
  • 【GD32F303红枫派使用手册】第三十节 CAN -CAN通信实验
  • 完全理解C语言函数
  • Linux 查看修改系统时间| date -s
  • 昇思25天学习打卡营第6天|关于函数与神经网络梯度相关技术探讨
  • 算法基础-----【动态规划】
  • 基于上一篇博客,用阻塞队列实现异步下单
  • mac中文件夹怎么显示.git隐藏文件
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • Docker 笔记(2):Dockerfile
  • js继承的实现方法
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • ng6--错误信息小结(持续更新)
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Vue.js源码(2):初探List Rendering
  • 从PHP迁移至Golang - 基础篇
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 收藏好这篇,别再只说“数据劫持”了
  • 移动端 h5开发相关内容总结(三)
  • 应用生命周期终极 DevOps 工具包
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • Spring Batch JSON 支持
  • 阿里云服务器如何修改远程端口?
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • # Maven错误Error executing Maven
  • #git 撤消对文件的更改
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (1)STL算法之遍历容器
  • (26)4.7 字符函数和字符串函数
  • (7)STL算法之交换赋值
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (转) Face-Resources
  • (转)树状数组
  • .NET MVC第五章、模型绑定获取表单数据
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 设计模式初探
  • .NET 依赖注入和配置系统
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .NET建议使用的大小写命名原则
  • .NET设计模式(11):组合模式(Composite Pattern)
  • ?
  • @entity 不限字节长度的类型_一文读懂Redis常见对象类型的底层数据结构