sujiajie 3 weeks ago
parent
commit
44ba08b89e

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 218 - 0
pom.xml

@@ -0,0 +1,218 @@
+<?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>
+    <groupId>com.example.demo</groupId>
+    <artifactId>travel</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>travel</name>
+    <description>travel</description>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <mybatisplus.version>3.4.1</mybatisplus.version>
+        <hutool.version>5.7.15</hutool.version>
+        <druid.version>1.1.21</druid.version>
+        <swagger.version>2.8.0</swagger.version>
+        <fastjson.version>1.2.80</fastjson.version>
+        <commons-lang3.version>3.3.2</commons-lang3.version>
+        <commons.io.version>2.11.0</commons.io.version>
+        <jedis.version>3.8.0</jedis.version>
+        <qcloud.cos.version>5.6.69</qcloud.cos.version>
+        <spring-boot-admin.version>2.6.10</spring-boot-admin.version>
+        <mysql.connector.version>8.0.29</mysql.connector.version>
+    </properties>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>2.5.12</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+    <dependencies>
+        <dependency>
+            <groupId>de.codecentric</groupId>
+            <artifactId>spring-boot-admin-starter-client</artifactId>
+            <version>${spring-boot-admin.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+            <version>${jedis.version}</version>
+        </dependency>
+        <!-- Spring Boot Data JPA -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.connector.version}</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+        <!--         redis -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <!--   生成二维码   -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.3.3</version>
+        </dependency>
+        <!--   io常用工具类   -->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons.io.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons-lang3.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>${hutool.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>2.1.3</version>
+        </dependency>
+        <!-- Jackson -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
+        <!-- Spring Boot Test -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!--          <dependency>  -->
+        <!--              <groupId>org.hibernate.validator</groupId>  -->
+        <!--              <artifactId>hibernate-validator</artifactId>  -->
+        <!--              <version>6.1.5.Final</version>  -->
+        <!--          </dependency>  -->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.9</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+        <!--         &lt;!&ndash; kafka &ndash;&gt; -->
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+        </dependency>
+        <!--          redisson分布式锁  -->
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson</artifactId>
+            <version>3.14.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatisplus.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.baomidou</groupId>
+                    <artifactId>mybatis-plus-generator</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- ModelMapper -->
+        <dependency>
+            <groupId>org.modelmapper</groupId>
+            <artifactId>modelmapper</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 14 - 0
src/main/java/com/example/demo/TravelApplication.java

@@ -0,0 +1,14 @@
+package com.example.demo;
+
+import cn.hutool.crypto.digest.BCrypt;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class TravelApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(TravelApplication.class, args);
+    }
+
+}

+ 18 - 0
src/main/java/com/example/demo/common/enums/BaseExceptionEnum.java

@@ -0,0 +1,18 @@
+package com.example.demo.common.enums;
+
+/**
+ * 抽象接口
+ *
+ */
+public interface BaseExceptionEnum {
+
+    /**
+     * 获取异常编码
+     */
+    Integer getCode();
+
+    /**
+     * 获取异常信息
+     */
+    String getMessage();
+}

+ 32 - 0
src/main/java/com/example/demo/common/utils/Md5Util.java

@@ -0,0 +1,32 @@
+package com.example.demo.common.utils;
+
+import java.security.MessageDigest;
+
+public class Md5Util {
+    /**
+     * 获取String字符串的MD5
+     *
+     * @param s
+     * @return
+     */
+    public static String MD5(String s) {
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            byte[] bytes = md.digest(s.getBytes("utf-8"));
+            return toHex(bytes);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static String toHex(byte[] bytes) {
+
+        final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
+        StringBuilder ret = new StringBuilder(bytes.length * 2);
+        for (int i = 0; i < bytes.length; i++) {
+            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
+            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
+        }
+        return ret.toString();
+    }
+}

+ 112 - 0
src/main/java/com/example/demo/common/utils/TokenUtils.java

@@ -0,0 +1,112 @@
+package com.example.demo.common.utils;
+
+import com.example.demo.common.exception.ApiException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
+import java.security.Key;
+import java.util.Date;
+
+/**
+ * 生成Token工具类
+ */
+public class TokenUtils {
+
+    /**
+     * 签名秘钥
+     */
+    public static final String SECRET = "cjyfutu1688";
+
+    /**
+     * 生成token
+     * @param id 一般传入userName
+     * @return
+     */
+    public static String createJwtToken(String id){
+        String issuer = "www.futureading.com";
+        String subject = "65532781@qq.com";
+        long ttlMillis = System.currentTimeMillis();
+        return createJwtToken(id, issuer, subject, ttlMillis);
+    }
+
+    /**
+     * 生成Token
+     *
+     * @param id
+     *            编号
+     * @param issuer
+     *            该JWT的签发者,是否使用是可选的
+     * @param subject
+     *            该JWT所面向的用户,是否使用是可选的;
+     * @param ttlMillis
+     *            签发时间
+     * @return token String
+     */
+    public static String createJwtToken(String id, String issuer, String subject, long ttlMillis) {
+
+        // 签名算法 ,将对token进行签名
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+
+        // 生成签发时间
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        // 通过秘钥签名JWT
+        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
+        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
+
+        // Let's set the JWT Claims
+        JwtBuilder builder = Jwts.builder().setId(id)
+                .setIssuedAt(now)
+                .setSubject(subject)
+                .setIssuer(issuer)
+                .signWith(signatureAlgorithm, signingKey);
+
+        // if it has been specified, let's add the expiration
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            builder.setExpiration(exp);
+        }
+
+        // Builds the JWT and serializes it to a compact, URL-safe string
+        return builder.compact();
+
+    }
+
+    // Sample method to validate and read the JWT
+    public static Claims parseJWT(String jwt) {
+        // This line will throw an exception if it is not a signed JWS (as expected)
+        Claims claims = Jwts.parser()
+                .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET))
+                .parseClaimsJws(jwt).getBody();
+        return claims;
+    }
+
+    public static Long getUserId(String token){
+        Claims claims = null;
+        try {
+            claims = TokenUtils.parseJWT(token);
+        } catch (Exception e) {
+            throw new ApiException(101,"token错误,请重新登录");
+        }
+
+        if(null==claims) {
+            throw new ApiException("token错误,请重新登录");
+        }
+        String id = claims.getId();
+        Long userId=Long.valueOf(id);
+
+        return userId;
+
+
+    }
+
+    public static void main(String[] args) {
+        System.out.println(TokenUtils.createJwtToken("admin"));
+    }
+}

+ 38 - 0
src/main/java/com/example/demo/user/config/RedissionConfig.java

@@ -0,0 +1,38 @@
+package com.example.demo.user.config;
+
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class RedissionConfig {
+    @Value("${spring.redis.host}")
+    private String host;
+    @Value("${spring.redis.port}")
+    private Integer port;
+    @Value("${spring.redis.database}")
+    private Integer database;
+    @Value("${spring.redis.password}")
+    private String password;
+
+    @Bean
+    public RedissonClient getRedisson(){
+        Config config = new Config();
+        config.useSingleServer().setAddress("redis://" + host + ":" + port)
+                .setDatabase(database);
+        if (StringUtils.isNotEmpty(password)){
+            config.useSingleServer().setAddress("redis://" + host + ":" + port).setDatabase(database)
+                    .setPassword(password);
+        }else{
+            config.useSingleServer().setAddress("redis://" + host + ":" + port).setDatabase(database);
+        }
+        //设置全局默认看门狗机制续期时间,如果在使用时不设置,则使用全局的,如果全局不设置,则使用默认的30000,单位毫秒
+        config.setLockWatchdogTimeout(2000);
+        return Redisson.create(config);
+    }
+
+}

+ 31 - 0
src/main/java/com/example/demo/user/controller/UserController.java

@@ -0,0 +1,31 @@
+package com.example.demo.user.controller;
+
+import com.example.demo.user.dto.LoginDto;
+import com.example.demo.user.dto.UserDto;
+import com.example.demo.user.service.UserService;
+import com.example.demo.user.service.impl.UserServiceImpl;
+import com.example.demo.user.vo.ResultVo;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = "用户管理")
+@RestController
+@RequestMapping("/user")
+public class UserController {
+    @Autowired
+    private UserServiceImpl userService;
+
+    @RequestMapping("/register")
+    public ResultVo register(@RequestBody UserDto dto){
+        return userService.register(dto);
+    }
+
+    @RequestMapping("/login")
+    public ResultVo login(@RequestBody LoginDto dto){
+        return userService.login(dto);
+    }
+
+}

+ 20 - 0
src/main/java/com/example/demo/user/dao/UserMapper.java

@@ -0,0 +1,20 @@
+package com.example.demo.user.dao;
+
+import com.example.demo.user.domain.User;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 徐乐
+* @description 针对表【user(用户基础信息表)】的数据库操作Mapper
+* @createDate 2025-06-04 17:31:35
+* @Entity com.example.demo.user.domain.User
+*/
+@Mapper
+public interface UserMapper extends BaseMapper<User> {
+
+}
+
+
+
+

+ 128 - 0
src/main/java/com/example/demo/user/domain/User.java

@@ -0,0 +1,128 @@
+package com.example.demo.user.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 用户基础信息表
+ * @TableName user
+ */
+@TableName(value ="user")
+@Data
+public class User {
+    /**
+     * 用户唯一ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 登录用户名
+     */
+    private String username;
+
+    /**
+     * 盐值
+     */
+    private String salt;
+
+    /**
+     * 加密后的密码
+     */
+    private String password;
+
+    /**
+     * 用户手机号
+     */
+    private String phone;
+
+    /**
+     * 用户邮箱
+     */
+    private String email;
+
+    /**
+     * 头像地址
+     */
+    private String avatar;
+
+    /**
+     * 注册时间
+     */
+    private Date createTime;
+
+    /**
+     * 信息更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 状态:1-正常 2-冻结 3-注销
+     */
+    private Integer status;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        User other = (User) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
+            && (this.getSalt() == null ? other.getSalt() == null : this.getSalt().equals(other.getSalt()))
+            && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
+            && (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
+            && (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
+            && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
+        result = prime * result + ((getSalt() == null) ? 0 : getSalt().hashCode());
+        result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
+        result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
+        result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
+        result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", username=").append(username);
+        sb.append(", salt=").append(salt);
+        sb.append(", password=").append(password);
+        sb.append(", phone=").append(phone);
+        sb.append(", email=").append(email);
+        sb.append(", avatar=").append(avatar);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", status=").append(status);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 9 - 0
src/main/java/com/example/demo/user/dto/LoginDto.java

@@ -0,0 +1,9 @@
+package com.example.demo.user.dto;
+
+import lombok.Data;
+
+@Data
+public class LoginDto {
+    private String phone;
+    private String password;
+}

+ 31 - 0
src/main/java/com/example/demo/user/dto/UserDto.java

@@ -0,0 +1,31 @@
+package com.example.demo.user.dto;
+
+import lombok.Data;
+
+@Data
+public class UserDto {
+    /**
+     * 登录用户名
+     */
+    private String username;
+
+    /**
+     * 加密后的密码
+     */
+    private String password;
+
+    /**
+     * 用户手机号
+     */
+    private String phone;
+
+    /**
+     * 用户邮箱
+     */
+    private String email;
+
+    /**
+     * 头像地址
+     */
+    private String avatar;
+}

+ 19 - 0
src/main/java/com/example/demo/user/service/UserService.java

@@ -0,0 +1,19 @@
+package com.example.demo.user.service;
+
+import com.example.demo.user.domain.User;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.user.dto.LoginDto;
+import com.example.demo.user.dto.UserDto;
+import com.example.demo.user.vo.ResultVo;
+
+/**
+* @author 徐乐
+* @description 针对表【user(用户基础信息表)】的数据库操作Service
+* @createDate 2025-06-04 17:31:35
+*/
+public interface UserService extends IService<User> {
+
+    ResultVo register(UserDto dto);
+
+    ResultVo login(LoginDto dto);
+}

+ 109 - 0
src/main/java/com/example/demo/user/service/impl/UserServiceImpl.java

@@ -0,0 +1,109 @@
+package com.example.demo.user.service.impl;
+
+import cn.hutool.core.util.IdUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.Md5Util;
+import com.example.demo.common.utils.TokenUtils;
+import com.example.demo.user.domain.User;
+import com.example.demo.user.dto.LoginDto;
+import com.example.demo.user.dto.UserDto;
+import com.example.demo.user.service.UserService;
+import com.example.demo.user.dao.UserMapper;
+import com.example.demo.user.vo.ResultVo;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+* @author 徐乐
+* @description 针对表【user(用户基础信息表)】的数据库操作Service实现
+* @createDate 2025-06-04 17:31:35
+*/
+@Slf4j
+@Service
+public class UserServiceImpl extends ServiceImpl<UserMapper, User>
+    implements UserService{
+
+    @Autowired
+    private UserMapper userMapper;
+    @Autowired
+    private RedissonClient redissonClient;
+    @Autowired
+    private RedisTemplate<String,String> redisTemplate;
+    @Override
+    public ResultVo register(UserDto dto) {
+        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
+        userQueryWrapper.eq("phone", dto.getPhone());
+        log.info("加锁");
+        RLock lock = redissonClient.getLock(dto.getPhone());
+        try {
+            log.info("获取锁");
+            boolean lockSuccess = lock.tryLock(3, TimeUnit.SECONDS);
+            if (!lockSuccess) {
+                throw new RuntimeException("操作频繁,请稍后再试");
+            }
+            User user = userMapper.selectOne(userQueryWrapper);
+            if (user != null) {
+                return ResultVo.error("用户已存在");
+            }
+            log.info("注册");
+            User u = new User();
+            u.setId(IdUtil.getSnowflake().nextId());
+            u.setUsername(dto.getUsername());
+            //生成盐值
+            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+            u.setSalt(uuid);
+            //获取密码
+            String password = dto.getPassword();
+            //加密
+            String md5Password = Md5Util.MD5(uuid + password);
+            u.setPassword(md5Password);
+            u.setEmail(dto.getEmail());
+            u.setPhone(dto.getPhone());
+            u.setAvatar(dto.getAvatar());
+            userMapper.insert(u);
+            return ResultVo.success("注册成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("注册过程中出现异常,请稍后再试");
+        } finally {
+            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
+                log.info("释放锁");
+                lock.unlock();
+            }
+        }
+    }
+
+    @Override
+    public ResultVo login(LoginDto dto) {
+        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
+        userQueryWrapper.eq("phone",dto.getPhone());
+        User user = userMapper.selectOne(userQueryWrapper);
+        if (user==null){
+            return ResultVo.error("用户不存在");
+        }
+        //获取盐值
+        String salt = user.getSalt();
+        //获取密码
+        String password = dto.getPassword();
+        //加密
+        String encryptedPassword = Md5Util.MD5(salt + password);
+        if (encryptedPassword.equals(user.getPassword())){
+            String token = TokenUtils.createJwtToken(user.getId().toString());
+            redisTemplate.opsForValue().set("userToken:",token);
+            return ResultVo.success("登录成功");
+        }
+        return ResultVo.error("用户名或密码有误");
+    }
+}
+
+
+
+

+ 46 - 0
src/main/java/com/example/demo/user/vo/ResultVo.java

@@ -0,0 +1,46 @@
+package com.example.demo.user.vo;
+
+import lombok.Data;
+
+@Data
+public class ResultVo<T> {
+    private Integer code;
+    private String msg;
+    private T obj;
+    public ResultVo(Integer code,String msg){
+        this.code = code;
+        this.msg = msg;
+    }
+    public ResultVo(){}
+    public static ResultVo success(Object object) {
+        ResultVo resultVO = new ResultVo(200,"成功");
+        resultVO.setObj(object);
+        return resultVO;
+    }
+    public static ResultVo success() {
+        return success(null);
+    }
+    public static ResultVo error(Integer code,String msg){
+        ResultVo resultVO = new ResultVo();
+        resultVO.setCode(code);
+        resultVO.setMsg(msg);
+        return resultVO;
+    }
+    public static ResultVo error(String msg){
+        ResultVo resultVO = new ResultVo();
+        resultVO.setMsg(msg);
+        return resultVO;
+    }
+    public static ResultVo error(){
+        ResultVo resultVO = new ResultVo();
+        resultVO.setCode(0);
+        resultVO.setMsg("失败");
+        return resultVO;
+    }
+    public static ResultVo error(Integer code,String msg,Object object){
+        ResultVo resultVO = new ResultVo();
+        resultVO.setCode(0);
+        resultVO.setMsg(msg);
+        return resultVO;
+    }
+}

+ 23 - 0
src/main/resources/application.yml

@@ -0,0 +1,23 @@
+server:
+  port: 8080
+
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://43.143.204.137:3306/travel_db?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
+    username: root
+    password: H2407!
+  redis:
+    host: 127.0.0.1
+    port: 6379
+    database: 0
+    password:
+  jpa:
+    open-in-view: false
+
+mybatis-plus:
+  type-aliases-package: com.example.domain
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  mapper-locations: classpath:mapper/*.xml

+ 24 - 0
src/main/resources/com/example/demo/user/mapper/UserMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.demo.user.dao.UserMapper">
+
+    <resultMap id="BaseResultMap" type="com.example.demo.user.domain.User">
+            <id property="id" column="id" />
+            <result property="username" column="username" />
+            <result property="salt" column="salt" />
+            <result property="password" column="password" />
+            <result property="phone" column="phone" />
+            <result property="email" column="email" />
+            <result property="avatar" column="avatar" />
+            <result property="createTime" column="create_time" />
+            <result property="updateTime" column="update_time" />
+            <result property="status" column="status" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,username,salt,password,phone,email,avatar,
+        create_time,update_time,status
+    </sql>
+</mapper>

+ 13 - 0
src/test/java/com/example/demo/TravelApplicationTests.java

@@ -0,0 +1,13 @@
+package com.example.demo;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TravelApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}