【Springboot3+vue3】从零到一搭建Springboot3+vue3前后端分离项目之后端环境搭建

【Springboot3+vue3】从零到一搭建Springboot3+vue3前后端分离项目,整合knef4j和mybaits实现基础用户信息管理

  • 后端环境搭建
    • 1.1 环境准备
    • 1.2 数据库表准备
    • 1.3 SpringBoot3项目创建
    • 1.4 MySql环境整合,使用druid连接池
    • 1.5 整合mybatis-plus
      • 1.5.1 引入mybaties-plus
      • 1.5.2 配置代码生成器
      • 1.5.3 配置分页插件
    • 1.6 整合swagger3(knife4j)
      • 1.6.1 整合
      • 1.6.2 使用
    • 1.7 数据交互处理
      • 1.7.1响应数据封装(公共返回数据类)
      • 1.7.2 分页查询返回数据封装
    • 1.8 全局异常处理
    • 1.9 整合JWT,生成token
    • 1.10 封装ThreadLocal工具类
    • 1.11 MD5封装
    • 1.12 登陆验证拦截
    • 1.13 新增,登录和查询当前用户
      • 1.13.1 新增用户
      • 1.13.2 用户登录
      • 1.13.3 获取当前用户信息
      • 1.13.4 查询所有用户信息
    • 1.14 删除和修改用户信息
      • 1.14.1 删除用户信息
      • 1.14.2 修改用户信息

跟着黑马敲了黑马点评和苍穹外卖,但是感觉黑马教程封装的太好了。于是想自己从零到一搭建一个前后端分离的简单项目。
主要参考的博客为:

从零搭建SpringBoot3+Vue3前后端分离项目基座,中小项目可用_springboot+vue3-CSDN博客

记录一下自己的实现过程。

最终实现效果如下:

在这里插入图片描述

后端环境搭建

1.1 环境准备

-spring-boot3 最低支持jdk17,所以需要准备jdk17的环境

-Idea版本 2024.1.4

-Mysql8

1.2 数据库表准备

可以随便使用一个数据库可视化软件,然后创建数据库data_demo,并运行以下查询,创建用户表

我用的是Navicat Premium

在这里插入图片描述

在这里插入图片描述

建好后,选中数据库,右键选择新建查询

运行如下命令,创建数据库表

CREATE TABLE user(id INT NOT NULL AUTO_INCREMENT COMMENT '主键',login_name VARCHAR(255) NOT NULL COMMENT '登录名(账号)',password VARCHAR(255) NOT NULL COMMENT '密码',name varchar(50) NOT NULL COMMENT '姓名',sex char(1) NOT NULL COMMENT '性别',phone VARCHAR(20) COMMENT '联系电话',PRIMARY KEY(id))COMMENT '用户信息表';

1.3 SpringBoot3项目创建

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

之后等待项目构建完成。构建完成的pom.xml文件如下,注意我在这里修改了spring的version,修改为3.3.3 ,因为在后面集成knef4j的时候发现3.4.0版本的spring无法显示接口。

参考博客如下:

尚硅谷新SSM教程中关于Knife4j 接口文档无法显示接口的问题_knife4j 识别不到controller-CSDN博客

即,正确的启动控制台没问题,但是不显示接口信息,后面将spring的版本降为3.3.3,成功解决

<?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 https://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>3.3.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.myProject</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>demo</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

1.4 MySql环境整合,使用druid连接池

在pom.xml中添加jdbc依赖,防止项目启动时找不到Bean报错

        <!--添加JDBC依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency>

添加druid依赖

        <!--添加Druid依赖--><!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-3-starter --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.20</version></dependency>

项目使用yml格式配置文件,修改resources下的application.properties为application.yml,删除文件原本内容,并将application.yml文件内容加上如下

配置项目端口号
server:port: 9999

application.yml中配置数据源和druid连接池 ,注意将database的name修改为自己数据库的名称,以及mysql的username和password

# ???????
database:name: data_demospring:datasource: #????url: jdbc:mysql://localhost:3306/${database.name}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: root

启动项目, 查看日志,端口和druid 初始化, 整合成功

在这里插入图片描述

1.5 整合mybatis-plus

1.5.1 引入mybaties-plus

官网地址: https://baomidou.com/

  1. pom.xml中添加如下依赖
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version>
</dependency>
  1. application.yml中加入如下配置
# mybatis ??????
mybatis-plus:configuration:#????????map-underscore-to-camel-case: truemapper-locations: classpath:mapper/*.xmltype-aliases-package: com.example.demo

启动项目,出现mybatis-plus日志

在这里插入图片描述

1.5.2 配置代码生成器

  1. pom.xml中添加如下依赖
<!-- mybatis-plus 代码生成器-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.5</version>
</dependency><!-- mybatis-plus代码生成器模板引擎 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>

2.新建utils包,并在下边创建MybatisPlusGenerator.java代码生成器配置类

在这里插入图片描述

package com.example.demo.utils;import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;import java.io.File;
import java.sql.Types;
import java.util.Collections;public class MybatisPlusGenerator {static final String url = "jdbc:mysql://127.0.0.1:3306/data_demo?serverTimezone=UTC";    // 数据库地址static final String username = "root";  // 数据库用户名static final String password = "123456";  // 数据库密码static final String authorName = "HuaXiang"; // 作者名static final String parentPackageNameResource = "com/example/demo";  // mapper.xml路径static final String parentPackageNameJava = "com.example.demo";  // java 文件父包名// 要生成代码对应的数据表名static final String tableName = "user";public static void main(String[] args) {FastAutoGenerator.create(url, username, password)// 1.全局配置.globalConfig(builder -> {builder.author(authorName)                // 设置作者.enableSpringdoc()               // 开启 swagger 模式// 获取当前工程路径并定位到项目java目录下.outputDir(System.getProperty("user.dir") + "/src/main/java");            // 指定输出目录})// 2.数据源配置.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {int typeCode = metaInfo.getJdbcType().TYPE_CODE;if (typeCode == Types.SMALLINT) {// 自定义类型转换return DbColumnType.INTEGER;}return typeRegistry.getColumnType(metaInfo);}))// 3.包名策略配置.packageConfig(builder -> {builder.parent(parentPackageNameJava) // 设置父包名.entity("entity").mapper("mapper").service("service").serviceImpl("service.impl").controller("controller")//.moduleName("system") // 设置父包模块名.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/"  + "/mapper")); // 设置mapperXml生成路径})// 策略配置.strategyConfig(builder -> {builder.addInclude(tableName) // 设置需要生成的表名// 覆盖已生成文件.entityBuilder().enableFileOverride().mapperBuilder().enableFileOverride().serviceBuilder().enableFileOverride().formatServiceFileName("%sService");//.addTablePrefix("t_", "c_"); // 设置过滤表前缀})// 配置模板.templateConfig(builder -> {//builder.controller("");         // 不生成controller}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}
}
  • 修改数据库相关信息
  • 修改authorName
  • 修改parentPackageNameResource, parentPackageNameJava
  • 修改tableName, 要生成代码的数据表名称,多个表使用,分割
  • .enableSpringdoc() 可以选择,生成swagger3文档注释
    修改完成后运行main函数,生成相应代码,mapper.xml在resource下与java同路径下

运行后目录如下:

在这里插入图片描述

1.5.3 配置分页插件

新建config包,并在下边配置类MybatiesPlusConfig.java

在这里插入图片描述

package com.example.demo.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MybatisPlusConfig {/*** 添加分页插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加//interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbTypereturn interceptor;}
}

在启动类配置扫描mapper路径@MapperScan(“com.example.demo.mapper”)

在这里插入图片描述

1.6 整合swagger3(knife4j)

1.6.1 整合

  1. pom.xml引入knife4j的依赖
        <!-- API 文档 knife4j --><!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.5.0</version></dependency>
  1. application.yml中添加配置
# springdoc-openapi 配置
springdoc:swagger-ui:path: /swagger-ui.htmltags-sorter: alphaoperations-sorter: alphaapi-docs:path: /v3/api-docsgroup-configs:- group: 'default'paths-to-match: '/**'packages-to-scan: com.example.demo.controller# knife4j 配置
knife4j:# 是否启用增强enable: true# 开启生产环境屏蔽production: false# 是否认证登录basic:# basic是否开启,默认为falseenable: trueusername: rootpassword: 123456setting:language: zh_cnenable-version: trueenable-swagger-models: true
  1. 测试。配置完成后,访问路径:http://localhost:9999/doc.html ,用户名密码为配置文件中的用户名和密码,如图

在这里插入图片描述

1.6.2 使用

实体类使用@Schema注解,在mybatis-plus选择的话会自动生成

在这里插入图片描述

Controller层使用

/*** <p>* 用户信息表 前端控制器* </p>* @since 2024-12-06*/
@Tag(name = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;/*** 用户列表分页* @param pageSize 每页显示的条数* @param currentPage  要查询的页* @param name  用户姓名* @return  Result<PageResultBean<List<User>>>*/@GetMapping("/pageList")@Operation(summary = "用户列表分页查询")@Parameters({@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token"),@Parameter(name = "pageSize", required = true, description = "每页显示的条数"),@Parameter(name = "currentPage", required = true, description = "要查询的页"),@Parameter(name = "name", description = "用户姓名", required = false)})public Result<PageResultBean<User>> pageList(@RequestParam int pageSize, @RequestParam int currentPage, @Nullable @RequestParam String name) {IPage<User> page = userService.pageList(pageSize, currentPage, name);if (page == null) {return Result.error("查询失败");}//PageResultBean<User> pageResultBean = new PageResultBean<User>(page.getTotal(), page.getRecords());return Result.success(PageResultBean.getInstance(page.getTotal(), page.getRecords()));}
}

在这里插入图片描述

1.7 数据交互处理

1.7.1响应数据封装(公共返回数据类)

封装返回数据封装类,放到common包下:

在这里插入图片描述

package com.example.demo.common;import io.swagger.v3.oas.annotations.media.Schema;public class Result<T> {@Schema(description = "业务状态码 1:成功  0: 失败")private int code;        // 业务状态码 0:成功  1: 失败@Schema(description = "提示信息")private String message;  // 提示信息@Schema(description = "返回数据")private T data;          // 响应数据public Result(int code, String message, T data) {this.code = code;this.message = message;this.data = data;}// 操作成功返回响应结果(带响应数据)public static <E> Result<E> success(E data) {return new Result<>(1, "操作成功", data);}public static <E> Result<E> success() {return new Result<>(1, "操作成功", null);}public static <E> Result<E> error(String message) {return new Result<>(0, message, null);}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return "Result{" +"code=" + code +", message='" + message + '\'' +", data=" + data +'}';}
}

1.7.2 分页查询返回数据封装

封装分页查询的数据,放到common包下

在这里插入图片描述

package com.example.demo.common;import io.swagger.v3.oas.annotations.media.Schema;public class Result<T> {@Schema(description = "业务状态码 0:成功  1: 失败")private int code;        // 业务状态码 0:成功  1: 失败@Schema(description = "提示信息")private String message;  // 提示信息@Schema(description = "返回数据")private T data;          // 响应数据public Result(int code, String message, T data) {this.code = code;this.message = message;this.data = data;}// 操作成功返回响应结果(带响应数据)public static <E> Result<E> success(E data) {return new Result<>(0, "操作成功", data);}public static <E> Result<E> success() {return new Result<>(0, "操作成功", null);}public static <E> Result<E> error(String message) {return new Result<>(1, message, null);}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return "Result{" +"code=" + code +", message='" + message + '\'' +", data=" + data +'}';}
}

1.8 全局异常处理

创建exception包,在包下放全局异常处理类GlobalExceptionHandler.java,

在这里插入图片描述

使用springboot @RestControllerAdvice注解配置

package com.example.demo.exception;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.example.demo.common.Result;// 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);@ExceptionHandler(Exception.class)public Result<String> handlerException(Exception e) {logger.warn(e.getMessage());return Result.error(StringUtils.hasLength(e.getMessage()) ? e.getMessage() : "操作失败");}
}

1.9 整合JWT,生成token

  1. pom.xml 中引入依赖
 <!-- jwt --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency>
  1. 封装工具类JwtUtil,放到utils包下
package com.example.demo.utils;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;import java.util.Date;
import java.util.Map;public class JwtUtil {private static final String KEY = "Demo";   // 密钥// 接收数据,生成token并返回public static String getToken(Map<String, Object> claims) {return JWT.create().withClaim("claims", claims).withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60))       // 失效时间1小时.sign(Algorithm.HMAC256(KEY));}// 接收token,验证并返回数据public static Map<String, Object> parseToken(String token) {return JWT.require(Algorithm.HMAC256(KEY)).build().verify(token).getClaim("claims").asMap();}
}

1.10 封装ThreadLocal工具类

因为前后端分离,使用ThreadLocal线程变量存储用户登录信息,替代session

package com.example.demo.utils;public class ThreadLocalUtil {// 提供ThreadLocal 对象private static final ThreadLocal<Object> THREAD_LOCAL = new ThreadLocal<>();// 获取存储值public static <T> T get() {return (T) THREAD_LOCAL.get();}// 存储值public static void set(Object value) {THREAD_LOCAL.set(value);}// 清除THREAD_LOCAL 防止内存泄漏public static void remove() {THREAD_LOCAL.remove();}
}

1.11 MD5封装

package com.example.demo.utils;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class Md5Util {/*** 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合*/protected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};protected static MessageDigest messagedigest = null;static {try {messagedigest = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException nsaex) {System.err.println(Md5Util.class.getName() + "初始化失败,MessageDigest不支持MD5Util。");nsaex.printStackTrace();}}/*** 生成字符串的md5校验值** @param s* @return*/public static String getMD5String(String s) {return getMD5String(s.getBytes());}/*** 判断字符串的md5校验码是否与一个已知的md5码相匹配** @param password  要校验的字符串* @param md5PwdStr 已知的md5校验码* @return*/public static boolean checkPassword(String password, String md5PwdStr) {String s = getMD5String(password);return s.equals(md5PwdStr);}public static String getMD5String(byte[] bytes) {messagedigest.update(bytes);return bufferToHex(messagedigest.digest());}private static String bufferToHex(byte bytes[]) {return bufferToHex(bytes, 0, bytes.length);}private static String bufferToHex(byte bytes[], int m, int n) {StringBuffer stringbuffer = new StringBuffer(2 * n);int k = m + n;for (int l = m; l < k; l++) {appendHexPair(bytes[l], stringbuffer);}return stringbuffer.toString();}private static void appendHexPair(byte bt, StringBuffer stringbuffer) {char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>>// 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换stringbuffer.append(c0);stringbuffer.append(c1);}// 测试public static void main(String[] args) {System.out.println(Md5Util.getMD5String("admin"));}}

1.12 登陆验证拦截

  1. 创建包interceptors,在包下配置登录拦截器
package com.example.demo.interceptors;import com.example.demo.utils.JwtUtil;
import com.example.demo.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 获取tokenString token = request.getHeader("Authorization");// 验证tokentry {Map<String, Object> claims = JwtUtil.parseToken(token);// 存储业务信息到线程变量ThreadLocalUtil.set(claims);// 放行拦截return true;} catch (Exception e) {// 登录信息异常或未登录,http响应状态码为401response.setStatus(401);// 拦截请求return false;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清除ThreadLocal业务数据ThreadLocalUtil.remove();}
}
  1. 在config包下创建WebConfig配置类,注册登录拦截器
package com.example.demo.config;import com.example.demo.interceptors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.ArrayList;
import java.util.List;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 配置放行资源// 无需拦截的接口集合List<String> ignorePath = new ArrayList<>();// knife4j(swagger)ignorePath.add("/swagger-resources/**");ignorePath.add("/doc.html");ignorePath.add("/v3/**");ignorePath.add("/webjars/**");ignorePath.add("/static/**");ignorePath.add("/templates/**");ignorePath.add("/error");// 登录页面ignorePath.add("/user/login");ignorePath.add("/user/add");registry.addInterceptor(loginInterceptor).excludePathPatterns(ignorePath);}
}

1.13 新增,登录和查询当前用户

1.13.1 新增用户

逻辑为:

  1. 参数验证。对传入的user进行基本的非空校验,校验用户姓名,登录名以及密码是否为空或者null。为空则返回错误提示信息
  2. 用户名重复校验。通过userService中的findByLoginName去数据库中查询是否存在相同loginName的用户
  3. 密码非空判断,假如密码为空,设置为默认的123456
  4. 密码加密处理。使用1.11 中的MD5对数据库中的密码进行加密
  5. 保存用户信息到数据库,调用userService中的add方法。

在UserController.java中加入如下方法

    /*** 添加用户* @param User* @return Result<String>*/@PostMapping("/add")@Operation(summary = "添加用户")@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token")public Result<String> addUser(@RequestBody User user) {return userService.add(user);}

在UserService.java中加入如下方法

    Result<String> add(User user);

UserServiceImpl.java中

package com.example.demo.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.utils.Md5Util;
import org.springframework.stereotype.Service;/*** <p>* 用户信息表 服务实现类* </p>** @author HuaXiang* @since 2024-12-06*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {private final UserMapper userMapper;public UserServiceImpl(UserMapper userMapper) {this.userMapper = userMapper;}public IPage<User> pageList(int pageSize, int currentPage, String name) {// 创建Page对象,传入当前页码和每页显示的记录数Page<User> page = new Page<>(currentPage, pageSize);// 可以在这里添加条件构造器来添加更复杂的查询条件,比如根据用户名模糊查询等// 以下是示例,如果name不为空进行模糊查询,实际根据需求调整if (name!= null &&!name.isEmpty()) {// 假设User实体类中有对应的username字段用于查询,此处只是示例,需根据实际调整LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.like(User::getName, name);return baseMapper.selectPage(page, queryWrapper);}// 如果没有额外条件,直接进行简单分页查询return baseMapper.selectPage(page, null);}@Overridepublic User findByLoginName(String loginName) {return userMapper.findByLoginName(loginName);}@Overridepublic Result<String> add(User user) {// 登录名校验if (user.getLoginName() == null || "".equals(user.getLoginName())) {return Result.error("登录名不能为空");}// 登录名重复校验if (findByLoginName(user.getLoginName()) != null) {return Result.error("登录名已存在,请重新输入");}if (user.getName() == null || "".equals(user.getName())) {return Result.error("姓名不能为空");}if (user.getPassword() == null || "".equals(user.getPassword())) {user.setPassword(Md5Util.getMD5String("123456"));}else{user.setPassword(Md5Util.getMD5String(user.getPassword()));}if (userMapper.insert(user) > 0) {return Result.success("添加成功");}return Result.error("添加失败");}
}

UserMapper.java中

package com.example.demo.mapper;import com.example.demo.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;/*** <p>* 用户信息表 Mapper 接口* </p>** @author HuaXiang* @since 2024-12-06*/
@Mapper
public interface UserMapper extends BaseMapper<User> {@Select("SELECT * FROM user WHERE login_name = #{loginName}")User findByLoginName(String loginName);}

使用swagger测试新增用户功能,在浏览器中输入http://localhost:9999/doc.html

请求参数如下:

{"loginName": "user1","password": "user1","name": "user1","sex": "男","phone": "15612341234"
}

在这里插入图片描述

数据库中查看,已经成功插入用户user1,密码也为user1

在这里插入图片描述

1.13.2 用户登录

  1. 接口定义:POST请求,路径为/login,
  2. 参数校验:对User对象判断,判断对象或则和loginName,password是否为空,为空则直接返回错误信息
  3. 用户名存在性校验调用userService.findByLoginName方法
  4. 密码正确性校验及登陆成功处理。
/*** 用户登录* @param user* @return*/@PostMapping("/login")@Operation(summary = "用户登录")@Parameters({@Parameter(name = "loginName", description = "登录名", required = true, schema = @Schema(type = "sting")),@Parameter(name = "password", description = "密码", required = true, schema = @Schema(type = "sting"))})public Result<String> login(@RequestBody User user) {if (user == null || "".equals(user.getLoginName()) || user.getLoginName() == null || "".equals(user.getPassword()) || user.getPassword() == null) {return Result.error("用户名密码不能为空");}// 检验用户名是否存在User eruser = userService.findByLoginName(user.getLoginName());if (eruser == null) {return Result.error("用户名不存在");}// 检验用户密码是否正确if (Md5Util.getMD5String(user.getPassword()).equals(eruser.getPassword())) {Map<String, Object> claims = new HashMap<>();claims.put("id", eruser.getId());claims.put("name", eruser.getName());claims.put("loginName", eruser.getLoginName());String token = JwtUtil.getToken(claims);return Result.success(token);}return Result.error("密码错误");}

测试

用刚刚新创建的用户测试用户登录功能。

在这里插入图片描述

1.13.3 获取当前用户信息

UserController.java

/*** 获取当前登录用户信息* @return  User*/@GetMapping("/currentUser")@Operation(summary = "获取当前登录用户信息")@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token")public Result<User> getCurrentUser() {Map<String, Object> userSession = ThreadLocalUtil.get();int id = (int) userSession.get("id");User user = userService.getUserById(id);if (user != null) {return Result.success(user);}return Result.error("用户状态异常");}

UserService.java

    User getUserById(int id);

UserServiceImpl.java

    @Overridepublic User getUserById(int id) {return userMapper.getUserById(id);}

UserMapper.java

    @Select("SELECT * FROM user WHERE id = #{id}")User getUserById(int id);

测试,复制1.13.2中用户登录成功返回的token值作为请求头

在这里插入图片描述

1.13.4 查询所有用户信息

UserController.javas

/*** 查询所有用户信息* @return List<User>*/
@GetMapping("/userList")
@Operation(summary = "查询所有用户信息")
@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token")
public Result<List<User>> userList() {List<User> userList = userService.getUserList();if (userList == null) {return Result.error("查询失败");}return Result.success(userList);
}

UserService.java

List<User> getUserList();

UserServiceImpl.java

/*** 查询所有用户信息* @return List<User>*/
@Override
public List<User> getUserList() {return userMapper.selectList(null);
}

1.14 删除和修改用户信息

1.14.1 删除用户信息

UserController.java

    /*** 删除用户*/@DeleteMapping("/delete/{id}")@Operation(summary = "删除用户信息")@Parameters({@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token"),@Parameter(name = "id", required = true, description = "用户id")})public Result<String> delete(@PathVariable int id) {boolean result = userService.deleteById(id); // 调用service层的方法根据loginname删除用户信息,这里假设UserService中有removeById方法if (result) {return Result.success("用户删除成功");} else {return Result.error("用户删除失败");}}

UserService.java

    boolean deleteById(int id);

UserServiceImpl.java

    @Overridepublic boolean deleteById(int id) {return userMapper.deleteById(id) > 0;}

测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.14.2 修改用户信息

UserController.java

    @PutMapping("/update")@Operation(summary = "修改用户信息")@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token")public Result<String> updateUser(@RequestBody User user) {Map<String, Object> userSession = ThreadLocalUtil.get();int id = (int) userSession.get("id");user.setId(id);user.setPassword(Md5Util.getMD5String(user.getPassword()));if (userService.update(user) > 0) {return Result.success("修改成功");}else {return Result.error("修改失败");}}

UserService.java

    int update(User user);

UserServiceImpl.java

    @Overridepublic int update(User user) {return userMapper.updateById(user);}

测试,先在请求头部中加上Authorization。(1.13.2中用户登录的返回的data)

在这里插入图片描述

请求参数如下:(将性别修改为女)

{"loginName": "user1","password": "user1","name": "user1","sex": "女","phone": "15612341234"
}

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

【大数据技术基础】 课程 第3章 Hadoop的安装和使用 大数据基础编程、实验和案例教程(第2版)

第3章 Hadoop的安装和使用 3.1 Hadoop简介 Hadoop是Apache软件基金会旗下的一个开源分布式计算平台&#xff0c;为用户提供了系统底层细节透明的分布式基础架构。Hadoop是基于Java语言开发的&#xff0c;具有很好的跨平台特性&#xff0c;并且可以部署在廉价的计算机集群中。H…

【Elasticsearch】ES+MySQL实现迷糊搜索

1. 技术选型 使用 Elasticsearch (ES) 结合 MySQL 进行数据存储和查询&#xff0c;而不是直接从 MySQL 中进行查询&#xff0c;主要是为了弥补传统关系型数据库&#xff08;如 MySQL&#xff09;在处理大规模、高并发和复杂搜索查询时的性能瓶颈。具体来说&#xff0c;ES 与 My…

Tomcat 的使用(图文教学)

Tomcat 的使用&#xff08;图文教学&#xff09; 前言一、什么是Tomcat&#xff1f;二、Tomcat 服务器和 Servlet 版本的对应关系三、Tomcat 的使用 1、安装2、目录介绍3、如何启动4、Tomcat 的停止5、如何修改 Tomcat 的端口号6、如何部暑 web 工程到 Tomcat 中 6.1 方式一6.…

Altium Designer学习笔记 31 PCB布线优化_GND处理

基于Altium Designer 23学习版&#xff0c;四层板智能小车PCB 更多AD学习笔记&#xff1a;Altium Designer学习笔记 1-5 工程创建_元件库创建Altium Designer学习笔记 6-10 异性元件库创建_原理图绘制Altium Designer学习笔记 11-15 原理图的封装 编译 检查 _PCB封装库的创建Al…

前端知识1html

VScode一些快捷键 Ctrl/——注释 !——生成html框架元素 *n——生成n个标签 直接书写html的名字回车生成对应的标签 常见标签 span&#xff1a; <span style"color: red;">hello</span> <span>demo</span> span实现&#xff1a; 标题…

Java项目实战II基于微信小程序的私家车位共享系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着城市化进程的加速&…

在google cloud虚拟机上配置anaconda虚拟环境简单教程

下载anaconda安装包 wget https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-x86_64.sh 安装 bash Anaconda3-2022.10-Linux-x86_64.sh 进入base环境 eval "$(/home/xmxhuihui/anaconda3/bin/conda shell.bash hook)" source ~/.bashrc 安装虚拟环境…

天天 AI-241207:今日热点- Windsurf:在工程能力上进一步进化的Cursor

2AGI.NET | 探索 AI 无限潜力&#xff0c;2AGI 为您带来最前沿资讯。 Windsurf&#xff1a;在工程能力上进一步进化的Cursor 介绍了一个新的AI代码编辑器Windsurf&#xff0c;它被认为是Cursor的进化版&#xff0c;具有更强的工程能力。文章强调了Windsurf在自动化编码和系统…

数据结构---单链表

目录 一、概念 二、分类 1. 单向或者双向 2. 带头或者不带头 3. 循环或者非循环 三、接口实现 1.定义结构 2、申请节点 3、尾插 4、头插 5、尾删 6、头删 7.查找&#xff0c;也可以充当修改 8、在pos之前插入x 9、在pos之后插入x ​编辑 10、删除pos位置 …

CSU课内课程资料【github仓库】

里面是我当时的PPT&#xff0c;作业答案&#xff0c;实验&#xff0c;还有一些笔记啥的&#xff0c;里面有的是他人的笔记和报告&#xff0c;等之后闲下来的话&#xff0c;我会删掉这部分&#xff0c;起码人家的笔记也是有隐私权的。关于实验&#xff0c;大多也是很普通&#x…

深算院崖山发布核心平替战略 加速金融数智化跃迁

2024年11月14日&#xff0c;由深圳计算科学研究院&#xff08;简称&#xff1a;深算院&#xff09;主办、深圳崖山科技有限公司&#xff08;简称&#xff1a;崖山科技&#xff09;和赛迪网承办的“2024国产数据库创新生态大会”在深圳成功举办。会上&#xff0c;崖山数据库重磅…

【Web】2023安洵杯第六届网络安全挑战赛 WP

目录 Whats my name easy_unserialize signal Swagger docs 赛题链接&#xff1a;GitHub - D0g3-Lab/i-SOON_CTF_2023: 2023 第六届安洵杯 题目环境/源码 Whats my name 第一段正则用于匹配以 include 结尾的字符串&#xff0c;并且在 include 之前&#xff0c;可以有任…

从零开始的vscode配置及安装rust教程

配置vscode的rust环境 下载安装vscodemac 环境 1. 下载安装rust2. 配置 mac vscode环境3. 创建一个测试项目 windows 环境 1. 安装c运行环境2. 安装配置rustup3. 配置windows vscode环境4. 创建一个测试项目 下载安装vscode 1.官网应用程序下载 vscode&#xff1a;https://…

小程序 - 美食列表

小程序交互练习 - 美食列表小程序开发笔记 目录 美食列表 功能描述 准备工作 创建项目 配置页面 配置导航栏 启动本地服务器 页面初始数据 设置获取美食数据 设置onload函数 设置项目配置 页面渲染 页面样式 处理电话格式 创建处理电话格式脚本 页面引入脚本 …

ip所属地址是什么意思?怎么改ip地址归属地

在数字化时代&#xff0c;IP地址作为网络设备的唯一标识符&#xff0c;不仅关乎设备间的通信&#xff0c;还涉及到用户的网络身份与位置信息。IP所属地址&#xff0c;即IP地址的归属地&#xff0c;通常反映了设备连接互联网时的地理位置。本文将深入解析IP所属地址的含义&#…

【opencv入门教程】12. 矩阵初始化

文章选自&#xff1a; 一、 数据类型 建立矩阵必须要指定矩阵存储的数据类型&#xff0c;图像处理中常用的几种数据类型如下&#xff1a;包括数据位深度8位、32位&#xff0c;数据类型U:uchar、F:float型以及通道数C1&#xff1a;单通道、C3&#xff1a;三通道、C4&#xff…

Hadoop生态圈框架部署 伪集群版(七)- Hive部署

文章目录 前言一、Hive部署&#xff08;手动部署&#xff09;1. 下载Hive2. 解压Hive安装包2.1 解压2.2 重命名2.3 解决冲突2.3.1 解决guava冲突2.3.2 解决SLF4J冲突 3. 配置Hive3.1 配置Hive环境变量3.2 修改 hive-site.xml 配置文件3.3 配置MySQL驱动包 4. 初始化MySQL上的存…

Hadoop生态圈框架部署 伪集群版(五)- HBase伪分布式部署

文章目录 前言一、Hbase伪分布式部署&#xff08;手动部署&#xff09;1. 下载Hbase2. 上传安装包3. 解压HBase安装包4. 配置HBase配置文件4.1 修改hbase-env.sh配置文件4.2 修改hbase-site.xml配置文件4.3 修改regionservers配置文件4.4 删除hbase中slf4j-reload4j-1.7.33.jar…

家政项目小程序+ssm

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序家政项目小程序的开发全过程。通过分析微信小程序家政项目小程序管理的不足&#xff0c;创建了一个计算机管理微信小程序家政项目小程序的方案。文章…

qt QNetworkAccessManager详解

1、概述 QNetworkAccessManager是QtNetwork模块中的一个核心类&#xff0c;它允许应用程序发送网络请求并接收响应。该类是网络通信的基石&#xff0c;提供了一种方便的方式来处理常见的网络协议&#xff0c;如HTTP、HTTPS等。QNetworkAccessManager对象持有其发送的请求的通用…