spring boot3 三、 spring alibaba cloud 整合 fastjson2、 接口统一响应注解 、mybatis plus、satoken 登录认证、knife4j文档 示例

在这里插入图片描述

jianmu-springboot3-springalibabacloud 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>

    <groupId>org.jm</groupId>
    <artifactId>jianmu-springboot3-springalibabacloud</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>jm-gateway</module>
        <module>jm-apis</module>
        <module>jm-apis-common</module>
        <module>jm-dubbo-apis</module>
    </modules>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2-extension-spring6</artifactId>
            <version>2.0.24</version>
        </dependency>

        <!--排除全局spring-boot-starter-logging相关依赖-->
        <!--        日志-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>*</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--添加log4j2依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>


    </dependencies>

    <dependencyManagement>
        <dependencies>
            <!--           数据库相关 start-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.5.3.1</version>
            </dependency>
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>8.0.32</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
                <version>3.5.2</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.16</version>
            </dependency>
            <!--           数据库相关 end-->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.12.0</version>
            </dependency>
            <!--        sa-token-->
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-spring-boot3-starter</artifactId>
                <version>1.34.0</version>
            </dependency>
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-reactor-spring-boot3-starter</artifactId>
                <version>1.34.0</version>
            </dependency>
            <!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
            <dependency>
                <groupId>cn.dev33</groupId>
                <artifactId>sa-token-dao-redis-jackson</artifactId>
                <version>1.34.0</version>
            </dependency>
            <!--           redis 连接池-->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>2.11.1</version>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>3.0.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2022.0.0.0-RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--            spring cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2022.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

jm-apis-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">
    <parent>
        <artifactId>jianmu-springboot3-springalibabacloud</artifactId>
        <groupId>org.jm</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>jm-apis-common</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>jm-apis-common-conf</module>
        <module>jm-apis-common-tool</module>
        <module>jm-apis-common-bean</module>
    </modules>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>

        <!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--        sa-token-->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot3-starter</artifactId>
        </dependency>
        <!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-dao-redis-jackson</artifactId>
        </dependency>

        <!--        knife4j-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
            <version>4.0.0</version>
        </dependency>


        <!--           数据库相关 start-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.32</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <!--           数据库相关 end-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

</project>

jm-apis-common jm-apis-common-conf

在这里插入图片描述

com.jm.common.conf

CommonsFastJsonConfig.java fastjson2配置类

package com.jm.common.conf.api;

import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring6.http.converter.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;

/**
 * 使用 阿里巴巴 fastjson2 进行json格式处理
 *
 * @author kong
 */
@Configuration
public class FastJsonConf implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig config = new FastJsonConfig();
        config.setDateFormat("yyyy-MM-dd HH:mm:ss");
        config.setReaderFeatures(JSONReader.Feature.FieldBased, JSONReader.Feature.SupportArrayToBean);
        config.setWriterFeatures(JSONWriter.Feature.WriteMapNullValue, JSONWriter.Feature.PrettyFormat);
        converter.setFastJsonConfig(config);
        converter.setDefaultCharset(StandardCharsets.UTF_8);
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
        converters.add(0, converter);
    }

}

RedisConf.java 整合redis 的fastjson2

package com.jm.common.conf;

import com.alibaba.fastjson2.support.spring6.data.redis.GenericFastJsonRedisSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

@Configuration
public class RedisConf {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
        //设置默认的Serialize,包含 keySerializer & valueSerializer
        redisTemplate.setDefaultSerializer(fastJsonRedisSerializer);

        //redisTemplate.setKeySerializer(fastJsonRedisSerializer);//单独设置keySerializer
        //redisTemplate.setValueSerializer(fastJsonRedisSerializer);//单独设置valueSerializer
        return redisTemplate;
    }
}

整合Mybatis plus

在这里插入图片描述

package com.jm.common.conf.mybatis;

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;

/**
 * @author kong
 */
@Configuration
@MapperScan("com.jm.mapper*")
public class MybatisPlusConf {

    /**
     * 分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    /**
     * 增强sql注入的Bean
     */
    @Bean
    public SqlInjectorPlus sqlInjectorPlus() {
        return new SqlInjectorPlus();
    }

}
package com.jm.common.conf.mybatis;

import org.apache.ibatis.type.LocalDateTimeTypeHandler;
import org.springframework.stereotype.Component;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;

/**
 * @author kong
 * 实体日期类型 localdatetime兼容
 */
@Component
public class MybatisLocalDateTimeTypeHandler extends LocalDateTimeTypeHandler {

    @Override
    public LocalDateTime getResult(ResultSet rs, String columnName) throws SQLException {
        Object object = rs.getObject(columnName);
        if (object == null) {
            return null;
        }
        if (object instanceof Timestamp) {
            //可以根据自己的需要进行转化
            return ((Timestamp) object).toLocalDateTime();
        }

        return super.getResult(rs, columnName);
    }
}
package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @author kong
 * addTime 和 updateTime 添加和修改时间填充
 */
@Component
public class MyBatisPlusAutoFill implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        Object addTime = this.getFieldValByName("addTime", metaObject);
        if (addTime == null) {
            this.setFieldValByName("addTime", LocalDateTime.now(), metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }
}

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;

import java.util.List;

/**
 * @author kong
 * 配置sql 增强
 */
public class SqlInjectorPlus extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        //继承原来的通用方法
        List<AbstractMethod> methods = super.getMethodList(mapperClass, tableInfo);
//        methods.add(new EnhanceBatchInsert());
//        methods.add(new EnhanceBatchDelete());
//        methods.add(new EnhanceBatchUpdate());
//        methods.add(new EnhanceUpdate());
//        methods.add(new EnhanceDelete());
        return methods;
    }
}

全局异常处理

package com.jm.common.conf;

import cn.dev33.satoken.exception.NotLoginException;
import com.jm.common.conf.api.Result;
import com.jm.common.conf.api.ResultCode;
import com.jm.common.conf.exception.ErrorException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author kong
 */
@Slf4j
@RestController
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 参数验证全局处理
     */
    @ExceptionHandler(value = BindException.class)
    public Result<?> methodArgumentNotValidException(BindException e) {
        ObjectError error = e.getBindingResult().getAllErrors().get(0);
        log.error("error!", e);
        if (log.isDebugEnabled()) {
            e.fillInStackTrace();
        }
        return Result.fail(error.getDefaultMessage());

    }

    /**
     * 全局手动抛出异常捕捉处理
     */
    @ExceptionHandler(value = ErrorException.class)
    public Result<?> errorHandler(ErrorException e) {
        log.error("error!", e);
        if (log.isDebugEnabled()) {
            e.fillInStackTrace();
        }
        return Result.fail(e.getMessage().replaceAll("com.jianmu.exception.ErrorException: ", ""));
    }


    /**
     * 未登录 或token失效
     */
    @ExceptionHandler(value = NotLoginException.class)
    public Result<?> errorHandler(NotLoginException e) {
        log.error("error!", e);
        if (log.isDebugEnabled()) {
            e.fillInStackTrace();
        }
        return new Result<>().setCode(ResultCode.UNAUTHORIZED.getCode())
                .setInfo(e.getMessage().replaceAll("com.jm.exception.NotLoginException: ", "")).setData(false);
    }

    /**
     * 全局异常捕捉处理
     */
    @ExceptionHandler(value = Exception.class)
    public Result<?> errorHandler(Exception e) {
        log.error("", e);
        if (log.isDebugEnabled()) {
            e.fillInStackTrace();
        }
        if (e.getMessage().contains("io.undertow.server.RequestTooBigException")) {
            return Result.fail("上传失败,请上传0~5M的图片");
        }
        return Result.fail("服务器出差了,请联系管理员!");
    }


    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) throws BindException {
        webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), false));
        webDataBinder.close();
    }
}

undertow 自定义缓冲

package com.jm.common.conf;

import io.undertow.server.DefaultByteBufferPool;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

/**
 * @author kong
 */
@Component
public class UndertowConf implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {

    /**
     * 设置缓冲池
     */
    @Override
    public void customize(UndertowServletWebServerFactory factory) {
        factory.addDeploymentInfoCustomizers(deploymentInfo -> {
            WebSocketDeploymentInfo info = new WebSocketDeploymentInfo();
            info.setBuffers(new DefaultByteBufferPool(false, 1024));
            deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", info);
        });
    }
}

接口统一响应注解

package com.jm.common.conf.api;

import java.lang.annotation.*;

/**
 * @author lime
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface ApiResult {
}

package com.jm.common.conf.api;

/**
 * 封装api的错误码
 *
 * @author lime
 */
public interface IErrorCode {
    /**
     * 获取状态码
     *
     * @return 状态码
     */
    int getCode();

    /**
     * 获取消息
     *
     * @return 消息
     */
    String getInfo();

    /**
     * 获取接口URI
     */
    String getApi();
}

package com.jm.common.conf.api;

import jakarta.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;


/**
 * @author kong
 * ApiResult 自定义拦截注解 接口返回统一结果
 */
@RestControllerAdvice
@Slf4j
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, @Nonnull Class<? extends HttpMessageConverter<?>> converterType) {
        if (returnType.getMethod() != null) {
            return returnType.getMethod().isAnnotationPresent(ApiResult.class);
        }
        return false;
    }

    @Override
    public Object beforeBodyWrite(Object body, @Nonnull MethodParameter parameter, @Nonnull MediaType type, @Nonnull Class<? extends HttpMessageConverter<?>> converterType,
                                  @Nonnull ServerHttpRequest request, @Nonnull ServerHttpResponse response) {
        return this.body(body);
    }

    private Result<?> body(Object body) {
        if (body instanceof Boolean) {
            return (Boolean) body ? Result.ok() : Result.fail();
        } else if (body instanceof String) {
            return Result.ok(String.valueOf(body));
        }
        return Result.ok(body);
    }
}

package com.jm.common.conf.api;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * @author lime
 * 统一接口结果
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Result<T> implements Serializable {
    private int code;
    private String info;
    private T data;

    public static Result<String> ok() {
        return new Result<>(ResultCode.OK.getCode(), ResultCode.OK.getInfo(), null);
    }

    public static <T> Result<T> ok(T data) {
        return new Result<>(ResultCode.OK.getCode(), ResultCode.OK.getInfo(), data);
    }

    public static Result<String> fail() {
        return new Result<>(ResultCode.FAIL.getCode(), ResultCode.FAIL.getInfo(), null);
    }

    public static Result<String> fail(String info) {
        return new Result<>(ResultCode.FAIL.getCode(), info, null);
    }



    @Override
    public String toString() {
        return "{\"code\": " + this.getCode() + ", \"info\": \"" + this.getInfo() + "\", \"data\": \"" + this.getData() + "\"}";
    }


}

package com.jm.common.conf.api;

/**
 * 枚举了一些常用API操作码
 *
 * @author kong
 */
public enum ResultCode implements IErrorCode {
    OK(1, "操作成功"),
    FAIL(0, "操作失败"),
    UNAUTHORIZED(-1000, "token已失效");


    /**
     * 状态码
     */
    private final int code;
    /**
     * 消息
     */
    private final String info;
    private String api;

    ResultCode(int code, String info) {
        this.code = code;
        this.info = info;
    }

    ResultCode(int code, String info, String api) {
        this.code = code;
        this.info = info;
        this.api = api;
    }

    @Override
    public int getCode() {
        return code;
    }

    @Override
    public String getInfo() {
        return info;
    }

    @Override
    public String getApi() {
        return api;
    }
}

package com.jm.common.conf.exception;

/**
 * @author kong
 * 自定义错误异常
 */
public class ErrorException extends RuntimeException {
    public ErrorException(String message) {
        super(message);
    }

    public ErrorException(String message, Throwable cause) {
        super(message, cause);
    }
}

package com.jm.common.conf.constant;

/**
 * @author kong
 * 统一的接口前缀
 */
public class SysApiConstant {

    private SysApiConstant(){}

    /**
     * 通用开放接口
     */
    public static final String OPEN_API = "api/open/";
}


jm-user-api 登录接口

在这里插入图片描述

jm-datasource.yaml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/db_jm_example?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useUnicode=true&rewriteBatchedStatements=true
    type: com.alibaba.druid.pool.DruidDataSource

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
package com.jm.model;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.time.LocalDateTime;

/**
 * @author kong
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@TableName("s_sys_user")
public class SysUser extends Model<SysUser> {
    private Long id;
    private String username;
    private String password;
    private Boolean deleted;
    private LocalDateTime addTime;
    private LocalDateTime updateTime;
}

package com.jm.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jm.model.SysUser;

/**
 * @author kong
 */
public interface SysUserMapper extends BaseMapper<SysUser> {
}

package com.jm.service.i;

import com.baomidou.mybatisplus.extension.service.IService;
import com.jm.model.SysUser;

/**
 * @author kong
 */
public interface SysUserService extends IService<SysUser> {
}

package com.jm.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jm.mapper.SysUserMapper;
import com.jm.model.SysUser;
import com.jm.service.i.SysUserService;
import org.springframework.stereotype.Service;

/**
 * @author kong
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
}

package com.jm.api;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jm.common.conf.api.ApiResult;
import com.jm.common.conf.constant.SysApiConstant;
import com.jm.common.conf.exception.ErrorException;
import com.jm.model.SysUser;
import com.jm.service.i.SysUserService;
import com.jm.service.i.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

/**
 * @author kong
 */
@Tag(name = "开放的登录接口")
@RestController
@RequestMapping(SysApiConstant.OPEN_API)
public class LoginApi {
    private final SysUserService sysUserService;
    private final UserService userService;

    @Autowired
    public LoginApi(SysUserService sysUserService, UserService userService) {
        this.sysUserService = sysUserService;
        this.userService = userService;
    }

    @Operation(summary = "登录")
    @Parameters({@Parameter(name = "username", description = "账号", required = true, in = ParameterIn.QUERY),
            @Parameter(name = "password", description = "密码", required = true, in = ParameterIn.QUERY)})
    @PostMapping("/login/sys")
    @ApiResult
    public String login(String username, String password) {
        this.userService.init();

        SysUser sysUser = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username).last("limit 1"));
        if (new BCryptPasswordEncoder().matches(password, sysUser.getPassword())) {
//            登录
            StpUtil.login(UUID.randomUUID());
            return StpUtil.getTokenValue();
        }
        throw new ErrorException("登录失败");
    }

    public static void main(String[] args) {
        System.out.println(new BCryptPasswordEncoder().encode("123456"));
    }
}

/*
Navicat MySQL Data Transfer

Source Server         : local
Source Server Version : 50737
Source Host           : localhost:3306
Source Database       : db_jm_example

Target Server Type    : MYSQL
Target Server Version : 50737
File Encoding         : 65001

Date: 2023-02-28 11:45:52
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for s_sys_user
-- ----------------------------
DROP TABLE IF EXISTS `s_sys_user`;
CREATE TABLE `s_sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT '',
  `password` varchar(200) DEFAULT '',
  `deleted` tinyint(1) DEFAULT '0',
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of s_sys_user
-- ----------------------------
INSERT INTO `s_sys_user` VALUES ('1', 'kong', '$2a$10$GLfuL5Bqxdl7LEQWTPbl4epfBcPb8A21pK1SE4lP7aK0jMcQmuhtW', '0', null, null);

在这里插入图片描述

注意事项

springboo3 fastjson2 引入的包 为fastjson2-extension-spring6

knife4j-openapi3-jakarta-spring-boot-starter 4.0.0 存在bug

在这里插入图片描述

需要手动加上服务前端 /user/api/open/login/sys

sa-token 的包名为sa-token-spring-boot3-starter

完整代码请看项目git地址

https://gitee.com/sunuping/jianmu-example-jdk17.git

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Spring Boot整合Fastjson需要进行以下步骤: 1.添加Fastjson依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> ``` 2.配置FastjsonHttpMessageConverter 在Spring Boot中我们可以使用`@Configuration`和`@Bean`注解来配置`FastjsonHttpMessageConverter`,并将其添加到`HttpMessageConverters`中。 ```java @Configuration public class FastjsonConfig { @Bean public HttpMessageConverters fastjsonHttpMessageConverter() { //定义一个converters转换消息的对象 FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); //添加fastjson的配置信息,比如:是否要格式化返回的json数据 FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); //在converter中添加配置信息 fastConverter.setFastJsonConfig(fastJsonConfig); HttpMessageConverter<?> converter = fastConverter; return new HttpMessageConverters(converter); } } ``` 3.测试 在Controller中使用`@RestController`注解,并返回一个Object对象。Fastjson会自动将其转换为JSON格式。 ```java @RestController public class UserController { @GetMapping("/user") public Object getUser() { User user = new User(); user.setId(1L); user.setUsername("test"); user.setPassword("123456"); return user; } } ``` 访问http://localhost:8080/user,可以看到返回的JSON格式数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等一场春雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值