开始尝试从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;}}

初步完成这样

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/40682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

找不到msvcp120.dll无法继续执行的原因分析及解决方法

在计算机使用中&#xff0c;经常会遇到msvcp120.dll文件丢失的情况&#xff0c;很多人对这个文件不是很熟悉&#xff0c;今天就来给大家讲解一下msvcp120.dll文件的丢失以及这个文件的重要性&#xff0c;让大家更好地了解计算机&#xff0c;同时也可以帮助我们更好地掌握这个文…

揭秘品牌成功秘诀:品牌营销策略的核心要素大公开

品牌营销作为企业战略中至关重要的一环&#xff0c;其核心是建立和传播品牌的独特魅力&#xff0c;使其在消费者心目中占据重要位置。 一个成功的品牌营销策略能够提升品牌的知名度和影响力&#xff0c;带来持续的销售和忠诚客户群体。 在当今竞争激烈的市场环境中&#xff0…

树状数组基础知识

lowbit: lowbit(x)x&(-x) 树状数组&#xff1a; 树状数组的功能&#xff1a; 数组 在O(1)的时间复杂度实现单点加&#xff1a; 在O(lng n)的时间复杂度实现查询前缀和&#xff1a; 树状数组的定义&#xff1a; 查询前x项的和操作&#xff1a; ll query(int x){ll s0;f…

户用分布式光伏项目开发模式

随着全球对可再生能源的重视和技术的不断进步&#xff0c;分布式光伏发电作为一种清洁、高效、可再生的能源形式&#xff0c;正逐渐成为新能源发展的重要方向。户用分布式光伏项目&#xff0c;作为分布式光伏发电的重要组成部分&#xff0c;其开发模式对于推动光伏产业的普及与…

二分查找及其变种

一、概念 二分查找算法&#xff08;Binary Search Algorithm&#xff09;是一种在有序数组中查找特定元素的高效搜索方法。 其基本思想是将目标值与数组中间的元素进行比较&#xff0c;如果目标值等于中间元素&#xff0c;则查找成功&#xff1b;如果目标值小于中间元素&…

第十五章 Qt的QGraphics View绘图框架详解

目录 一、视图、场景、图形项 1、Graphics View 绘图架构 1.1、图形项 GraphicsItem 1.2、场景 QGraphicsScene 1.3、视图 QGraphicsView 2、图形项、场景、视图的坐标系 3、Graphics View 基础练习 二、使用自定义视图处理鼠标事件 1、添加自定义视图类 2、使用自定…

ScaleCache: A Scalable Page Cache for Multiple Solid-State Drives——论文泛读

EuroSys 2024 Paper 论文阅读笔记整理 问题 高性能存储设备&#xff0c;如具有GB/s级I/O带宽的NVMe SSD&#xff0c;已被广泛应用于企业服务器中。对于处理大量数据&#xff0c;在RAID配置中使用多个SSD很有吸引力&#xff0c;这可以提高I/O性能、可靠性和容量。尽管多个SSD为…

全面教程:在Ubuntu上快速部署ZeroTier,实现Windows与VSCode的局域网无缝访问

文章目录 1 背景介绍2 Windows上的操作3 Ubuntu上的操作4 连接 1 背景介绍 在现代工作环境中&#xff0c;远程访问公司内网的Ubuntu主机对于开发者来说是一项基本需求。然而&#xff0c;由于内网的限制&#xff0c;传统的远程控制软件如向日葵和todesk往往无法满足这一需求。作…

华硕电脑格式化后电脑会怎样?数据怎么恢复

在数字化时代&#xff0c;电脑已经成为我们日常生活和工作中不可或缺的设备。然而&#xff0c;在使用电脑的过程中&#xff0c;有时我们会遇到需要格式化硬盘的情况。对于华硕电脑用户而言&#xff0c;了解格式化后的影响以及如何恢复磁盘数据至关重要。本文将详细探讨华硕电脑…

《昇思25天学习打卡营第9天|保存与加载》

文章目录 今日所学&#xff1a;一、构建与准备二、保存和加载模型权重三、保存和加载MindIR总结 今日所学&#xff1a; 在上一章节主要学习了如何调整超参数以进行网络模型训练。在这一过程中&#xff0c;我们通常会想要保存一些中间或最终的结果&#xff0c;以便进行后续的模…

Swift Core Data 分阶段迁移

文章目录 前言什么是分阶段迁移&#xff1f;提供一些背景信息创建迁移管理器设置使用 Core Data 栈。总结 前言 在这之前&#xff0c;我发布了一篇文章&#xff0c;在其中解释了如何使用映射模型和自定义迁移策略执行复杂的 Core Data 迁移。虽然这种方法性能良好且运行良好&a…

【Linux进阶】文件和目录的默认权限与隐藏权限

1.文件默认权限&#xff1a;umask OK&#xff0c;那么现在我们知道如何建立或是改变一个目录或文件的属性了&#xff0c;不过&#xff0c;你知道当你建立一个新的文件或目录时&#xff0c;它的默认权限会是什么吗&#xff1f; 呵呵&#xff0c;那就与umask这个玩意儿有关了&…

Vue85-Vuex的求和案例

一、需求 二、开发 2-1、index.js中vuex的代码 注意&#xff1a; 书写格式&#xff1a;actions中的函数名用小写&#xff01;mutations中的函数名&#xff0c;用大写。 注意&#xff1a; 2-2、组件count.vue中的代码 2-3、代码优化 三、actions中的context参数 此写法的后…

Python基于PyQt5和卷积神经网络分类模型(ResNet50分类算法)实现生活垃圾分类系统GUI界面项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 在当今社会&#xff0c;随着人们对环境保护意识的增强以及科技的快速发展&#xff0c;智能化的垃圾分类…

EasyBoss ERP移动端上线数据分析模块,随时查Shopee/TikTok本土店数据

前段时间&#xff0c;EasyBoss ERP出了个超酷炫的数字大屏功能&#xff0c;广受好评。 但是也有老板说&#xff0c;电脑端看数据不够方便啊&#xff0c;你们EasyBoss有本事上个手机就能看数据的功能啊&#xff01; 说干就干&#xff0c;直接满足你们的需求&#xff01; 于是在…

day02-统计数据

numpy统计学 1.求平均值[数组名.mean()/np.mean(数组名)] m1 np.arange(20).reshape((4,5))m1.mean() #9.5若想要求某一维的平均值&#xff0c;设置axis参数&#xff0c;多维数组元素指定&#xff1a; axis 0&#xff0c;将从上往下计算。axis 1&#xff0c;将从左往右计算…

44 mysql batch insert 的实现

前言 我们这里 来探讨一下 insert into $fields values ($values1), ($values2), ($values3); 的相关实现, 然后 大致来看一下 为什么 他能这么快 按照 我的思考, 应该里里面有 批量插入才对, 但是 调试结果 发现令我有一些意外 呵呵 果然 只有调试才是唯一的真理 相比于 …

Linux的Socket开发概述

套接字&#xff08;socket&#xff09;是 Linux 下的一种进程间通信机制&#xff08;socket IPC&#xff09;&#xff0c;在前面的内容中已经给大家提到过&#xff0c;使用 socket IPC 可以使得在不同主机上的应用程序之间进行通信&#xff08;网络通信&#xff09;&#xff0c…

MATLAB和Python发那科ABB库卡史陶比尔工业机器人模拟示教框架

&#x1f3af;要点 &#x1f3af;模拟工业机器人 | &#x1f3af;可视化机器人DH 参数&#xff0c;机器人三维视图 | &#x1f3af;绘制观察运动时关节坐标位置、速度和加速度 | &#x1f3af;绘制每个关节处的扭矩和力 | &#x1f3af;图形界面示教机器人 | &#x1f3af;工业…

Qt入门小项目 | WPS tab页面(无边框窗口综合应用)

文章目录 一、手写代码实现WPS tab页面 一、手写代码实现WPS tab页面 实现类似WPS tab效果&#xff0c;具体包含&#xff1a; 自定义标题栏&#xff1a;最大、最小、关闭在QTabWidget的tab上增加控件在QTabWidget的tab上右键菜单可拖拽移动可拉伸窗口双击标题栏在最大与正常间…