【SpringBoot系列】SpringBoot新项目配置

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
img

  • 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术点,如集合,jvm,并发编程 redis,kafka,Spring,微服务,Netty 等
    • 常用开发工具系列:罗列常用的开发工具,如 IDEA,Mac,Alfred,electerm,Git,typora,apifox 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

1.启动配置文件

application.yml

spring:
  profiles:
    active: local

application-local.yml

server:
  servlet:
    context-path: /bfp-o2o

#Spring 相关配置
spring:
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  datasource:
    dynamic:
      #设置默认的数据源或者数据源组,默认值即为master
      primary: master
      strict: false
      datasource:
        master:
          driver-class-name: com.mysql.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource
          url: jdbc:mysql://10.239.183.66:3306/o2o?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false
          #          url: jdbc:mysql://10.201.1.222:3306/o2o?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false
          username: root
          password: cw68_sit@crv
o2o:
  jd:
    file:
      remotePath: /home/ftpuser/jd/
      remoteFileName: jd-back.csv
      localPath: ./data/jd/
      localFileName: jd-back.csv
  mt:
    file:
      remotePath: /home/ftpuser/meituan/
      remoteFileName: mt.csv
      localPath: ./data/meituan/
      localFileName: mt.csv
  eleme:
    file:
      remotePath: /home/ftpuser/eleme/
      remoteFileName: eleme.csv
      localPath: ./data/eleme/
      localFileName: eleme.csv
  shop_ids_url: https://o2o-api.crv.com.cn/open_api/v1/dc-shop
  suguo_url: https://wei-test.vipxiaoqu.com/wty-test
  sftp:
    name: ftpuser
    passwd: ftpP#ssw0rd
    ipAddr: 10.201.1.223
    port: 22

#mybatis-plus配置
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    call-setters-on-nulls: true
    auto-mapping-behavior: full
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  global-config:
    banner: false
    # 逻辑删除配置
    db-config:
      id-type: AUTO
      logic-delete-field: delFlag
      logic-delete-value: 1
      logic-not-delete-value: 0
      table-underline: true

bootstrap.yml

spring:
  application:
    name: o2o-service
  cloud:
    nacos:
      config:
        file-extension: yaml

启动参数

-Dspring.cloud.nacos.discovery.serverAddr=10.239.165.190:80 -Dspring.cloud.nacos.discovery.namespace=bfp-sit -Dspring.cloud.nacos.config.serverAddr=10.239.165.190:80 -Dspring.cloud.nacos.config.namespace=bfp-sit

2…gitignore 文件

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/

3.logback.xml 日志文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <!--定义日志文件的存储地址 -->
    <property name="APPDIR" value="o2o-api"/>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>log/${APPDIR}.out</File>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 添加.gz 历史日志会启用压缩 大大缩小日志文件所占空间 -->
            <fileNamePattern>log/daily/${APPDIR}.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory><!--  保留7天日志 -->
        </rollingPolicy>
    </appender>

    <!--myibatis log configure -->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
    <logger name="com.wanjia.o2o" level="INFO"/>

    <!-- 日志输出级别 -->
    <root level="info">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>

4.Swagger2Config

package org.jeecg.config;

import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.shiro.vo.DefContants;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Author scott
 */
@Slf4j
@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
@ConditionalOnProperty(name = "swagger.enable", havingValue = "true")
public class Swagger2Config implements WebMvcConfigurer {

    /**
     * 显示swagger-ui.html文档展示页,还必须注入swagger资源:
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }


    Predicate<RequestHandler> selector1 = RequestHandlerSelectors.basePackage("org.jeecg.modules");
    Predicate<RequestHandler> selector2 = RequestHandlerSelectors.basePackage("com.eastroc");

    /**
     * swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等
     *
     * @return Docket
     */
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo()).groupName("预约系统")
                .select()
                //此包路径下的类,才生成接口文档
//                .apis(RequestHandlerSelectors.basePackage("org.jeecg.modules"))
                //加了ApiOperation注解的类,才生成接口文档
                .apis(Predicates.or(selector1, selector2))
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(Collections.singletonList(securityScheme()))
                .globalOperationParameters(setHeaderToken());
    }


    @Bean
    public Docket createVrsRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo()).groupName("ARRANGE模块")
                .select()
                //此包路径下的类,才生成接口文档
                .apis(RequestHandlerSelectors.basePackage("com.eastroc"))
                //加了ApiOperation注解的类,才生成接口文档
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(Collections.singletonList(securityScheme()));
//                .globalOperationParameters(setHeaderToken());
    }

    /***
     * oauth2配置
     * 需要增加swagger授权回调地址
     * http://localhost:8888/webjars/springfox-swagger-ui/o2c.html
     * @return
     */
    @Bean
    SecurityScheme securityScheme() {
        return new ApiKey(DefContants.X_ACCESS_TOKEN, DefContants.X_ACCESS_TOKEN, "header");
    }

    /**
     * JWT token
     *
     * @return
     */
    private List<Parameter> setHeaderToken() {
        ParameterBuilder tokenPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<>();
        tokenPar.name(DefContants.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
        pars.add(tokenPar.build());
        return pars;
    }

    /**
     * api文档的详细信息函数,注意这里的注解引用的是哪个
     *
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                // //大标题
                .title("Jeecg-Boot 后台服务API接口文档")
                // 版本号
                .version("1.0")
//				.termsOfServiceUrl("NO terms of service")
                // 描述
                .description("后台API接口")
                // 作者
                .contact("JEECG团队")
                .license("The Apache License, Version 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
                .build();
    }

}
/**
 * @author : qinyingjie
 * @date : 2021/10/26
 * @desc : http://localhost:8080/ant/doc.html#/home
 */
@Configuration
@EnableOpenApi     //开启 Swagger3 ,可不写
@EnableKnife4j     //开启 knife4j ,可不写
public class Knife4jConfig {
    @Bean
    public Docket createRestApi() {
        // Swagger 2 使用的是:DocumentationType.SWAGGER_2
        // Swagger 3 使用的是:DocumentationType.OAS_30
        return new Docket(DocumentationType.OAS_30)
                // 定义是否开启swagger,false为关闭,可以通过变量控制
                .enable(true)
                // 将api的元信息设置为包含在json ResourceListing响应中。
                .apiInfo(new ApiInfoBuilder()
                        .title("ANT接口文档")
                        // 描述
                        .description("平台服务管理api")
                        .contact(new Contact("秦英杰", "深圳", "327782001@qq.com"))
                        .version("1.0.0")
                        .build())
                // 分组名称
                .groupName("1.0")
                // 选择哪些接口作为swagger的doc发布
                .select()
                // 要扫描的API(Controller)基础包
                .apis(RequestHandlerSelectors.basePackage("com.xiaofei"))
                //                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }
}

5.WebConfigurer

package com.eastroc.login;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.eastroc.common.enums.RoleEnum;
import com.eastroc.common.service.ISystemFixService;
import com.eastroc.common.utils.LoginUtils;
import com.eastroc.mine.entity.SystemFix;
import com.eastroc.mine.entity.UserWechat;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.exception.RoleException;
import org.jeecg.common.exception.SystemMaintenanceException;
import org.jeecg.common.exception.UserException;
import org.jeecg.common.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Objects;


@Slf4j
@Component
public class XcxRoleInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private ISystemFixService systemFixService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        List<SystemFix> systemFixes = systemFixService.list();
        if (CollectionUtils.isNotEmpty(systemFixes)) {
            SystemFix systemFix = systemFixes.get(0);
            //系统维护通知
            long startInterval = DateUtil.between(systemFix.getFixStart(), new Date(), DateUnit.MS, false);
            long endInterval = DateUtil.between(new Date(), systemFix.getFixEnd(), DateUnit.MS, false);
            if (startInterval > 0 && endInterval > 0) {
                String endDate = DateUtils.date2Str(systemFix.getFixEnd(), DateUtils.datetimeFormat.get());
                throw new SystemMaintenanceException("系统维护中,维护时间至:" + endDate);
            }
        }
        UserWechat user = LoginUtils.getCurrentUser(request);
        if (Objects.isNull(user)) {
            throw new UserException("登录信息没有" + request.getRequestURL());
        }
        if (Objects.isNull(user.getRoleId())) {
            throw new UserException("登录角色没有" + request.getRequestURL() + "" + user.toString());
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        XcxRole role = method.getAnnotation(XcxRole.class);
        if (Objects.isNull(role)) {
            return true;
        }
        if (role.roles().length > 0) {
            Integer currentRole = user.getRoleId();
            for (RoleEnum annotationRole : role.roles()) {
                if (currentRole.equals(annotationRole.getType())) {
                    return true;
                }
            }
        }
        throw new RoleException("用户越权访问接口");
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }

}

6.Result

package org.jeecg.common.api.vo;

import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.jeecg.common.constant.CommonConstant;
import lombok.Data;

/**
 *   接口返回数据格式
 * @author scott
 * @email jeecgos@163.com
 * @date  2019年1月19日
 */
@Data
@ApiModel(value="接口返回对象", description="接口返回对象")
public class Result<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * 成功标志
	 */
	@ApiModelProperty(value = "成功标志")
	private boolean success = true;

	/**
	 * 返回处理消息
	 */
	@ApiModelProperty(value = "返回处理消息")
	private String message = "操作成功!";

	/**
	 * 返回代码
	 */
	@ApiModelProperty(value = "返回代码")
	private Integer code = 0;

	/**
	 * 返回数据对象 data
	 */
	@ApiModelProperty(value = "返回数据对象")
	private T result;

	/**
	 * 时间戳
	 */
	@ApiModelProperty(value = "时间戳")
	private long timestamp = System.currentTimeMillis();

	public Result() {

	}

	public Result<T> success(String message) {
		this.message = message;
		this.code = CommonConstant.SC_OK_200;
		this.success = true;
		return this;
	}

	public Result<T> good(T t) {
		this.setResult(t);
		this.code = CommonConstant.SC_OK_200;
		this.success = true;
		return this;
	}

	public Result<T> good() {
		this.code = CommonConstant.SC_OK_200;
		this.success = true;
		this.setMessage("成功");
		return this;
	}

	public Result<T> fail(String msg) {
		this.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
		this.setMessage(msg);
		this.setSuccess(false);
		return this;
	}

	public static Result<Object> ok() {
		Result<Object> r = new Result<Object>();
		r.setSuccess(true);
		r.setCode(CommonConstant.SC_OK_200);
		r.setMessage("成功");
		return r;
	}

	public static Result<Object> ok(String msg) {
		Result<Object> r = new Result<Object>();
		r.setSuccess(true);
		r.setCode(CommonConstant.SC_OK_200);
		r.setMessage(msg);
		return r;
	}

	public static Result<Object> ok(Object data) {
		Result<Object> r = new Result<Object>();
		r.setSuccess(true);
		r.setCode(CommonConstant.SC_OK_200);
		r.setResult(data);
		return r;
	}

	public static Result<Object> error(String msg) {
		return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
	}

	public static Result<Object> error(int code, String msg) {
		Result<Object> r = new Result<Object>();
		r.setCode(code);
		r.setMessage(msg);
		r.setSuccess(false);
		return r;
	}

	public Result<T> error500(String message) {
		this.message = message;
		this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
		this.success = false;
		return this;
	}
	/**
	 * 无权限访问返回结果
	 */
	public static Result<Object> noauth(String msg) {
		return error(CommonConstant.SC_JEECG_NO_AUTHZ, msg);
	}
}

7.JeecgBootException

package org.jeecg.common.exception;

public class JeecgBootException extends RuntimeException {
    private static final long serialVersionUID = 1L;

    private Integer code;

    public JeecgBootException(String message) {
        super(message);
    }

    public JeecgBootException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public JeecgBootException(Throwable cause) {
        super(cause);
    }

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

8.JeecgBootExceptionHandler

package org.jeecg.common.exception;

import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.connection.PoolException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Arrays;

/**
 * 异常处理器
 *
 * @Author scott
 * @Date 2019
 */
@Slf4j
@RestControllerAdvice
public class JeecgBootExceptionHandler {

    @Value("${profileCurrentValue}")
    private String profileCurrentValue;

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(JeecgBootException.class)
    public Result<?> handleRRException(JeecgBootException e) {
        log.error(e.getMessage(), e);
        return Result.error(e.getMessage());
    }

    @ExceptionHandler(RoleException.class)
    public Result<?> handleRoleException(RoleException e) {
        log.error(e.getMessage(), e);
        return Result.error("用户角色异常");
    }

    @ExceptionHandler(UserException.class)
    public Result<?> handleUserException(UserException e) {
        log.error(e.getMessage(), e);
        return Result.error("用户登录异常");
    }

    @ExceptionHandler(SystemMaintenanceException.class)
    public Result<?> handleSystemMaintenanceException(SystemMaintenanceException e) {
        log.error(e.getMessage(), e);
        return Result.error(e.getMessage());
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public Result<?> handlerNoFoundException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.error(404, "路径不存在,请检查路径是否正确");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public Result<?> handleDuplicateKeyException(DuplicateKeyException e) {
        log.error(e.getMessage(), e);
        return Result.error("数据库中已存在该记录");
    }

    @ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
    public Result<?> handleAuthorizationException(AuthorizationException e) {
        log.error(e.getMessage(), e);
        return Result.noauth("没有权限,请联系管理员授权");
    }

    @ExceptionHandler({Exception.class})
    public Result<?> handleException(Exception e) {
        log.error(e.getMessage(), e);
        String env = "小程序";
        if ("dev".equals(profileCurrentValue)) {
            return Result.error("操作失败," + e.getMessage());
//			env = "开发环境";
        } else if ("test".equals(profileCurrentValue)) {
            env += "测试环境";
        } else if ("prod".equals(profileCurrentValue)) {
            env += "生产环境";
        }
        HttpRequest.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=8315d403-91d3-4bc2-bc72-91bd92a38a51")
                .header(Header.CONTENT_TYPE, "application/json")
                .body("  {\n" +
                        "        \"msgtype\": \"text\",\n" +
                        "        \"text\": {\n" +
                        "            \"content\": \"" + env + "\n" + e.toString() + "\n" + Arrays.toString(e.getStackTrace()).substring(0, 500) + "\"\n" +
                        "        }\n" +
                        "   }")
                .execute();
        return Result.error("操作失败," + e.getMessage());
    }


    /**
     * 自定义系统交互异常
     */
    @ExceptionHandler(SystemException.class)
    public Result<?> handleSystemException(SystemException e) {
        log.error(e.getMessage(), e);
        String env = "小程序";
        if ("dev".equals(profileCurrentValue)) {
//            return Result.error("操作失败," + e.getMessage());
            env = "开发环境";
        } else if ("test".equals(profileCurrentValue)) {
            env += "测试环境";
        } else if ("prod".equals(profileCurrentValue)) {
            env += "生产环境";
        }
        env = env + "--系统交互异常";
        HttpRequest.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=8315d403-91d3-4bc2-bc72-91bd92a38a51")
                .header(Header.CONTENT_TYPE, "application/json")
                .body("  {\n" +
                        "        \"msgtype\": \"text\",\n" +
                        "        \"text\": {\n" +
                        "            \"content\": \"" + env + "\n" + e.toString() + "\n" + e.getMessage() + "\"\n" +
                        "        }\n" +
                        "   }")
                .execute();
        return Result.error(e.getMessage());
    }

    /**
     * @param e
     * @return
     * @Author 政辉
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result<?> HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        StringBuffer sb = new StringBuffer();
        sb.append("不支持");
        sb.append(e.getMethod());
        sb.append("请求方法,");
        sb.append("支持以下");
        String[] methods = e.getSupportedMethods();
        if (methods != null) {
            for (String str : methods) {
                sb.append(str);
                sb.append("、");
            }
        }
        log.error(sb.toString(), e);
        //return Result.error("没有权限,请联系管理员授权");
        return Result.error(405, sb.toString());
    }

    /**
     * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        log.error(e.getMessage(), e);
        return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
        log.error(e.getMessage(), e);
        return Result.error("字段太长,超出数据库字段的长度");
    }

    @ExceptionHandler(PoolException.class)
    public Result<?> handlePoolException(PoolException e) {
        log.error(e.getMessage(), e);
        return Result.error("Redis 连接异常!");
    }

}
package com.xiaofei.common.constant;

public class CommonConstant {
    /**
     * 成功
     */
    public static final Integer SC_OK_200 = 200;
    /**
     * 服务器错误
     */
    public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
    /**
     * 未认证
     */
    public static final int SC_JEECG_NO_AUTHZ = 401;
}

9.MybatisPlusConfig

package org.jeecg.config;

import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.jeecg.config.mybatis.MetaHandler;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.aop.interceptor.PerformanceMonitorInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

/**
 * 单数据源配置(jeecg.datasource.open = false时生效)
 *
 * @Author zhoujf
 */
@Configuration
@MapperScan(value = {"org.jeecg.modules.**.mapper*", "com.eastroc.**.mapper*"})
public class MybatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        // 设置sql的limit为无限制,默认是500
        return new PaginationInterceptor().setLimit(-1);
    }

    /**
     * 自动填充功能
     *
     * @return
     */
    @Bean
    public GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setMetaObjectHandler(new MetaHandler());
        return globalConfig;
    }


    @Bean
    @Profile({"dev", "test"}) // 在dev和test环境中开启 SQL执行效率插件【生产环境可以关闭】
    public PerformanceMonitorInterceptor performanceMonitorInterceptor() {
        return new PerformanceMonitorInterceptor();
    }

    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }
}
package com.xiaofei.common.config;

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

import java.time.LocalDateTime;
import java.util.Date;
import java.util.function.Supplier;

public class MetaHandler implements MetaObjectHandler {
    private static String CREATE_TIME = "createTime";
    private static String UPDATE_TIME = "updateTime";

    /**
     * 插入使用
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        fillValue(metaObject, CREATE_TIME, () -> getDateValue(metaObject.getSetterType(CREATE_TIME)));
        fillValue(metaObject, UPDATE_TIME, () -> getDateValue(metaObject.getSetterType(UPDATE_TIME)));
    }


    /**
     * 更新使用
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        fillValue(metaObject, "et." + UPDATE_TIME, () -> getDateValue(metaObject.getSetterType("et." + UPDATE_TIME)));
    }

    private void fillValue(MetaObject metaObject, String fieldName, Supplier<Object> valueSupplier) {
        if (!metaObject.hasGetter(fieldName)) {
            return;
        }
        Object sidObj = metaObject.getValue(fieldName);
        if (sidObj == null && metaObject.hasSetter(fieldName) && valueSupplier != null) {
            setFieldValByName(fieldName, valueSupplier.get(), metaObject);
        }
    }

    private Object getDateValue(Class<?> setterType) {
        if (Date.class.equals(setterType)) {
            return new Date();
        } else if (LocalDateTime.class.equals(setterType)) {
            return LocalDateTime.now();
        } else if (Long.class.equals(setterType)) {
            return System.currentTimeMillis();
        }
        return null;
    }
}

10.RedisLock

package org.jeecg.common.aspect.annotation;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisLock {
    /**
     * 获取方法上的参数值生成key,spEl表达式:例如'#{data}'或者 '#{data.value}'或者 '#{data.value1}&#{data.value2}'
     */
    String key() default "";

    /**
     * 自定义后缀,字符串,加在key的后面
     */
    String suffix() default "";

    /**
     * key过期时间,毫秒,默认10秒
     */
    String expireTime() default "10000";

    /**
     * 是否包含token值,需要请求头里包含token
     */
    boolean includeToken() default false;
}
@RedisLock(key = "#data")
@AutoLog(value = "供应链新增订单到预约系统")
@ApiOperation(value = "供应链新增订单到预约系统", notes = "供应链新增订单到预约系统")
@PostMapping(value = "/expressOrder")
public Map<String, Object> expressOrder(@RequestBody String data) {}
package org.jeecg.modules.system.aspect;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.aspect.annotation.RedisLock;
import org.jeecg.common.util.redis.JedisClient;
import org.jeecg.common.util.redis.RedisTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.UUID;


@Slf4j
@Aspect
@Configuration
public class RedisLockAspect {

    @Autowired
    private JedisClient jedisClient;

    @Around(value = "@annotation(org.jeecg.common.aspect.annotation.RedisLock)")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        RedisLock redisLock = method.getAnnotation(RedisLock.class);
        Object[] arguments = pjp.getArgs();
        //解析SpEL表达式
        String key = String.valueOf(parseSpel(redisLock.key(), method, arguments));
        //解析UserId表达式
        String token = parseToken(redisLock.includeToken());
        Object result;
        String methodName = pjp.getSignature().getName();
        //唯一标识
        String requestId = UUID.randomUUID().toString();
        String lockKey = "vrs_" + methodName + "_" + token + key;
        //后缀
        if (StringUtils.isNotBlank(redisLock.suffix())) {
            lockKey = lockKey + "_" + redisLock.suffix();
        }
        try {
            //添加分布式锁
            boolean res = RedisTool.tryGetDistributedLock(jedisClient.getJedis(), lockKey, requestId, Integer.parseInt(redisLock.expireTime()));
            if (res) {
                //执行
                result = pjp.proceed();
            } else {
                log.info("重复提交的请求: " + lockKey);
                throw new Exception("重复提交的请求");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        } finally {
            //移除分布式锁
            RedisTool.releaseDistributedLock(jedisClient.getJedis(), lockKey, requestId);
            log.info("释放分布式锁成功: " + lockKey);
        }
        return result;
    }

    private String parseToken(boolean includeToken) {
        if (includeToken) {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            if (sra != null && sra.getRequest() != null) {
                HttpServletRequest request = sra.getRequest();
                Object token = request.getHeader("token_manage");
                return token == null ? "" : token.toString();
            }

        }
        return "";
    }

    /**
     * 解析SpEL表达式
     * @param key    SpEL表达式
     * @param method 反射得到的方法
     * @param args   反射得到的方法参数
     * @return 解析后SpEL表达式对应的值
     */
    private Object parseSpel(String key, Method method, Object[] args) {
        if (StringUtils.isNotBlank(key)) {
            // 创建解析器
            ExpressionParser parser = new SpelExpressionParser();
            // 通过Spring的LocalVariableTableParameterNameDiscoverer获取方法参数名列表
            LocalVariableTableParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
            String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
            // 构造上下文
            EvaluationContext context = new StandardEvaluationContext();
            if (args.length == parameterNames.length) {
                for (int i = 0, len = args.length; i < len; i++) {
                    // 使用setVariable方法来注册自定义变量
                    context.setVariable(parameterNames[i], args[i]);
                }
            }
            String[] keys = key.split("&");
            StringBuilder sb = new StringBuilder();
            if (keys.length > 0) {
                for (String k : keys) {
                    sb.append(parser.parseExpression(k).getValue(context));
                }
            }
            return sb.toString();
        }
        return "";
    }
}

11.redis

package org.jeecg.common.util.redis;

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import java.util.Collections;


@Component
public class RedisTool {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX"; //  NX 代表只在键不存在时,才对键进行设置操作
    private static final String SET_WITH_EXPIRE_TIME = "PX"; // PX 5000 设置键的过期时间为5000毫秒

    /**
     * 尝试获取分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        /**
         * 1、把key、value set到redis中,隐含覆盖,默认的ttl是-1(永不过期)
         *
         * 2、根据第三个参数,把key、value set到redis中
         *     nx : not exists, 只有key 不存在时才把key value set 到redis
         *     xx : is exists ,只有 key 存在是,才把key value set 到redis
         *
         * 3、4 和2 就相同,只是多加了个过期时间
         *      expx参数有两个值可选 :
         *           ex : seconds 秒
         *           px :   milliseconds 毫秒
         *      使用其他值,抛出 异常 : redis.clients.jedis.exceptions.JedisDataException : ERR syntax error
         */
        try {
            String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

            if (LOCK_SUCCESS.equals(result)) {
                return true;
            }
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }

        return false;

    }

    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 释放分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {

        try {
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

            if (RELEASE_SUCCESS.equals(result)) {
                return true;
            }
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }

        return false;

    }

}
package org.jeecg.common.util.redis;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;


@Data
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
public class JedisConfig {

    private String host;
    private String password;
    private String port;
    private String timeout;
    private String maxTotal;
    private String maxIdle;
    private String minIdle;
}
package org.jeecg.common.util.redis;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class JedisClient {

    @Autowired
    private JedisConfig jedisConfig;
    //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 15 * 1000;
    //超时时间
    private static int TIMEOUT = 10 * 1000;
    private JedisPool jedisPool = null;

    public JedisPool getJedisPool() {
        return jedisPool;
    }

    /**
     * Jedis实例获取返回码
     *
     * @author jqlin
     */
    public static class JedisStatus {
        /**
         * Jedis实例获取失败
         */
        public static final long FAIL_LONG = -5L;
        /**
         * Jedis实例获取失败
         */
        public static final int FAIL_INT = -5;
        /**
         * Jedis实例获取失败
         */
        public static final String FAIL_STRING = "-5";
    }

    @PostConstruct
    private void initialPool() {
        //Redis服务器IP
        String HOST = jedisConfig.getHost();
        //Redis的端口号
        int PORT = NumberUtils.toInt(jedisConfig.getPort(), 6379);
        //访问密码
        String AUTH = jedisConfig.getPassword();
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            //最大连接数,如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
            config.setMaxTotal(NumberUtils.toInt(jedisConfig.getMaxTotal(), 400));
            //最大空闲数,控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
            config.setMaxIdle(NumberUtils.toInt(jedisConfig.getMaxIdle(), 50));
            //最小空闲数
            config.setMinIdle(NumberUtils.toInt(jedisConfig.getMinIdle(), 10));
            //是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
            config.setTestOnBorrow(false);
            //在return给pool时,是否提前进行validate操作
            config.setTestOnReturn(false);
            //在空闲时检查有效性,默认false
            config.setTestWhileIdle(true);
            //表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;
            //这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
            config.setMinEvictableIdleTimeMillis(30000);
            //表示idle object evitor两次扫描之间要sleep的毫秒数
            config.setTimeBetweenEvictionRunsMillis(60000);
            //表示idle object evitor每次扫描的最多的对象数
            config.setNumTestsPerEvictionRun(1000);
            //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
            config.setMaxWaitMillis(MAX_WAIT);
            if (StringUtils.isNotBlank(AUTH)) {
                jedisPool = new JedisPool(config, HOST, PORT, TIMEOUT, AUTH);
            } else {
                jedisPool = new JedisPool(config, HOST, PORT, TIMEOUT);
            }
        } catch (Exception e) {
            if (jedisPool != null) {
                jedisPool.close();
            }
            log.error("初始化Redis连接池失败", e);
        }
    }

    /**
     * 在多线程环境同步初始化
     */
    private synchronized void poolInit() {
        if (jedisPool == null) {
            initialPool();
        }
    }

    /**
     * 同步获取Jedis实例
     *
     * @return Jedis
     */
    public Jedis getJedis() {
        if (jedisPool == null) {
            poolInit();
        }
        Jedis jedis = null;
        try {
            if (jedisPool != null) {
                jedis = jedisPool.getResource();
            }
        } catch (Exception e) {
            log.error("同步获取Jedis实例失败" + e.getMessage(), e);
            jedis.close();
        }
        return jedis;
    }

    /**
     * 设置值
     *
     * @param key
     * @param value
     * @return -5:Jedis实例获取失败<br/>OK:操作成功<br/>null:操作失败
     * @author jqlin
     */
    public String set(String key, String value) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_STRING;
            }
            return jedis.set(key, value);
        } catch (Exception e) {
            log.error("[redis error] -> 设置值失败");
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置值
     *
     * @param key
     * @param value
     * @param expire 过期时间,单位:秒
     * @return -5:Jedis实例获取失败<br/>OK:操作成功<br/>null:操作失败
     * @author jqlin
     */
    public String set(String key, String value, int expire, TimeUnit timeUnit) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_STRING;
            }
            if (TimeUnit.MILLISECONDS.equals(timeUnit)) {
                expire = expire / 1000;
            } else if (!TimeUnit.SECONDS.equals(timeUnit)) {
                throw new RuntimeException("TimeUnit时间单位设置错误:请设置milliseconds或seconds");
            }
            return jedis.setex(key, expire, value);
        } catch (Exception e) {
            log.error("[redis error] -> 设置值失败");
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取值
     *
     * @param key
     * @return
     * @author jqlin
     */
    public String get(String key) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_STRING;
            }
            return jedis.get(key);
        } catch (Exception e) {
            log.error("[redis error] -> 设置值失败");
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置key的过期时间
     *
     * @param key
     * @param -5:Jedis实例获取失败,1:成功,0:失败
     * @return
     * @author jqlin
     */
    public long expire(String key, int seconds) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.expire(key, seconds);
        } catch (Exception e) {
            log.error(String.format("设置key=%s的过期时间失败:" + e.getMessage(), key));
            throw new RuntimeException(e);
        }
    }

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     * @author jqlin
     */
    public boolean exists(String key) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return false;
            }
            return jedis.exists(key);
        } catch (Exception e) {
            log.error(String.format("判断key=%s是否存在失败:" + e.getMessage(), key));
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除key
     *
     * @param keys
     * @return -5:Jedis实例获取失败,1:成功,0:失败
     * @author jqlin
     */
    public long del(String... keys) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.del(keys);
        } catch (Exception e) {
            log.error(String.format("删除key=%s失败:" + e.getMessage(), keys));
            throw new RuntimeException(e);
        }
    }

    /**
     * set if not exists,若key已存在,则setnx不做任何操作
     *
     * @param key
     * @param value key已存在,1:key赋值成功
     * @return
     * @author jqlin
     */
    public long setnx(String key, String value) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.setnx(key, value);
        } catch (Exception e) {
            log.error("设置值失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * set if not exists,若key已存在,则setnx不做任何操作
     *
     * @param key
     * @param value  key已存在,1:key赋值成功
     * @param expire 过期时间,单位:秒
     * @return
     * @author jqlin
     */
    public long setnx(String key, String value, int expire) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            Long result = jedis.setnx(key, value);
            expire(key, expire);
            return result;
        } catch (Exception e) {
            log.error("设置值失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 在列表key的头部插入元素
     *
     * @param key
     * @param values -5:Jedis实例获取失败,>0:返回操作成功的条数,0:失败
     * @return
     * @author jqlin
     */
    public long lpush(String key, String... values) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.lpush(key, values);
        } catch (Exception e) {
            log.error("在列表key的头部插入元素失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 在列表key的尾部插入元素
     *
     * @param key
     * @param values -5:Jedis实例获取失败,>0:返回操作成功的条数,0:失败
     * @return
     * @author jqlin
     */
    public long rpush(String key, String... values) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.rpush(key, values);
        } catch (Exception e) {
            log.error("在列表key的尾部插入元素失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 返回存储在key列表的特定元素
     *
     * @param key
     * @param start 开始索引,索引从0开始,0表示第一个元素,1表示第二个元素
     * @param end   结束索引,-1表示最后一个元素,-2表示倒数第二个元素
     * @return redis client获取失败返回null
     * @author jqlin
     */
    public List<String> lrange(String key, long start, long end) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return null;
            }
            return jedis.lrange(key, start, end);
        } catch (Exception e) {
            log.error("查询列表元素失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取List缓存对象
     *
     * @param key
     * @param start
     * @param end
     * @return List<T> 返回类型
     * @author jqlin
     */
    public <T> List<T> range(String key, long start, long end, Class<T> clazz) {
        List<String> dataList = lrange(key, start, end);
        if (CollectionUtils.isEmpty(dataList)) {
            return new ArrayList<>();
        }
        return JSON.parseArray(JSON.toJSONString(dataList), clazz);
    }

    /**
     * 获取列表长度
     *
     * @param key -5:Jedis实例获取失败
     * @return
     * @author jqlin
     */
    public long llen(String key) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.llen(key);
        } catch (Exception e) {
            log.error("获取列表长度失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 移除等于value的元素<br/><br/>
     * 当count>0时,从表头开始查找,移除count个;<br/>
     * 当count=0时,从表头开始查找,移除所有等于value的;<br/>
     * 当count<0时,从表尾开始查找,移除count个
     *
     * @param key
     * @param count
     * @param value
     * @return -5:Jedis实例获取失败
     * @author jqlin
     */
    public long lrem(String key, long count, String value) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.lrem(key, count, value);
        } catch (Exception e) {
            log.error("获取列表长度失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 对列表进行修剪
     *
     * @param key
     * @param start
     * @param end
     * @return -5:Jedis实例获取失败,OK:命令执行成功
     * @author jqlin
     */
    public String ltrim(String key, long start, long end) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_STRING;
            }
            return jedis.ltrim(key, start, end);
        } catch (Exception e) {
            log.error("获取列表长度失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置对象
     *
     * @param key
     * @param obj
     * @return
     * @author jqlin
     */
    public <T> String setObject(String key, T obj) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_STRING;
            }
            byte[] data = JSON.toJSONBytes(obj);
            return jedis.set(key.getBytes(), data);
        } catch (Exception e) {
            log.error("设置对象失败:" + e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取对象
     *
     * @param key
     * @return
     * @author jqlin
     */
    public <T> T getObject(String key) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                return null;
            }
            T result = null;
            byte[] data = jedis.get(key.getBytes());
            if (data != null && data.length > 0) {
                result = (T) JSON.parse(data);
            }
            return result;
        } catch (Exception e) {
            log.error("获取对象失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 缓存Map赋值
     *
     * @param key
     * @param field
     * @param value
     * @return -5:Jedis实例获取失败
     * @author jqlin
     */
    public long hset(String key, String field, String value) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_LONG;
            }
            return jedis.hset(key, field, value);
        } catch (Exception e) {
            log.error("缓存Map赋值失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取缓存的Map值
     *
     * @param key
     * @return
     */
    public String hget(String key, String field) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                return null;
            }
            return jedis.hget(key, field);
        } catch (Exception e) {
            log.error("获取缓存的Map值失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param map
     * @return
     */
    public String hmset(String key, Map<String, String> map) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                return JedisStatus.FAIL_STRING;
            }
            return jedis.hmset(key, map);
        } catch (Exception e) {
            log.error("缓存Map赋值失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取map所有的字段和值
     *
     * @param key
     * @return
     * @author jqlin
     */
    public Map<String, String> hgetAll(String key) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return new HashMap<>();
            }
            return jedis.hgetAll(key);
        } catch (Exception e) {
            log.error("获取map所有的字段和值失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 查看哈希表 key 中,指定的field字段是否存在。
     *
     * @param key
     * @param field
     * @return
     * @author jqlin
     */
    public Boolean hexists(String key, String field) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return null;
            }
            return jedis.hexists(key, field);
        } catch (Exception e) {
            log.error("查看哈希表field字段是否存在失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取所有哈希表中的字段
     *
     * @param key
     * @return
     * @author jqlin
     */
    public Set<String> hkeys(String key) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return new HashSet<>();
            }
            return jedis.hkeys(key);
        } catch (Exception e) {
            log.error("获取所有哈希表中的字段失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取所有哈希表中的值
     *
     * @param key
     * @return
     * @author jqlin
     */
    public List<String> hvals(String key) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return new ArrayList<>();
            }
            return jedis.hvals(key);
        } catch (Exception e) {
            log.error("获取所有哈希表中的值失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 从哈希表 key 中删除指定的field
     *
     * @param key
     * @param
     * @return
     * @author jqlin
     */
    public long hdel(String key, String... fields) {
        try (
            Jedis jedis = getJedis();
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return JedisStatus.FAIL_LONG;
            }
            return jedis.hdel(key, fields);
        } catch (Exception e) {
            log.error("map删除指定的field失败:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取正则匹配的key (慎用)
     *
     * @param pattern
     * @return
     */
    public Set<String> keys(String pattern) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return new HashSet<>();
            }
            return jedis.keys(pattern);
        } catch (Exception e) {
            log.error("操作keys失败:" + e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Redis Incrby 命令将 key 中储存的数字加上指定的增量值;
     * 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令;
     * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
     * 本操作的值限制在 64 位(bit)有符号数字表示之内。
     *
     * @return
     */
    public Long incrBy(String key, long integer) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return 0L;
            }
            return jedis.incrBy(key, integer);
        } catch (Exception e) {
            log.error("操作 Incrby 失败:" + e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Redis Incr 命令将 key 中储存的数字值增一。
     * 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。
     * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
     * 本操作的值限制在 64 位(bit)有符号数字表示之内
     */
    public Long incr(String key) {
        try (
            Jedis jedis = getJedis()
        ) {
            if (jedis == null) {
                log.warn("Jedis实例获取为空");
                return 0L;
            }
            return jedis.incr(key);
        } catch (Exception e) {
            log.error("操作 Incr 失败:" + e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }
}

12.RabbitMqConfig

package org.jeecg.config;

import com.eastroc.common.consts.ArrangeConstant;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class RabbitMqConfig {

    private final SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer;
    private final CachingConnectionFactory connectionFactory;

    @Bean(name = "syncshipmentOrderReportServiceQueue")
    public Queue syncshipmentOrderReportServiceQueue() {
        return QueueBuilder.durable(ArrangeConstant.Q_SYNC_SHIPMENT_ORDER_TO_REPORT_ONE).build();
    }


    @Bean
    public Binding syncShipmentOrderReportServiceBinding(Queue syncshipmentOrderReportServiceQueue, DirectExchange shipmentOrderReportExchange) {
        return BindingBuilder.bind(syncshipmentOrderReportServiceQueue).to(shipmentOrderReportExchange).with(ArrangeConstant.K_SHIPMENT_ORDER_REPORT_ONE);
    }


    @Bean(name = "shipmentOrderReportContainer")
    public SimpleRabbitListenerContainerFactory shipmentOrderReportContainer() {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factoryConfigurer.configure(factory, connectionFactory);
        factory.setAcknowledgeMode(AcknowledgeMode.NONE);
        factory.setPrefetchCount(10);
        return factory;
    }

    @Bean
    public DirectExchange shipmentOrderReportExchange() {
        return (DirectExchange) ExchangeBuilder.directExchange(ArrangeConstant.E_EXCHANGE).durable(true).build();
    }

}
package com.eastroc.common.consumer;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eastroc.common.consts.ArrangeConstant;
import com.eastroc.order.entity.*;
import com.eastroc.order.entity.StoreBase;
import com.eastroc.common.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
@RabbitListener(queues = ArrangeConstant.Q_SYNC_SHIPMENT_ORDER_TO_REPORT_ONE, containerFactory = "shipmentOrderReportContainer")
public class ShipmentOrderReportConsumer {

    @Resource
    private StoreBaseMapper storeBaseMapper;
    @Resource
    private ShipmentOrderMapper shipmentOrderMapper;
    @Resource
    private ShipmentOrderDetailMapper shipmentOrderDetailMapper;
    @Resource
    private ShipmentOrderReportMapper shipmentOrderReportMapper;
    @Resource
    private ShipmentOrderRelateDriverMapper shipmentOrderRelateDriverMapper;
    @Resource
    private AccessControlSystemCarInfoMapper accessControlSystemCarInfoMapper;
    @Resource
    private ShipmentOrderDetailGoodsInfoMapper shipmentOrderDetailGoodsInfoMapper;

    @RabbitHandler
    public void syncReport(String shipmentOrderId) {
        log.info("syncReport shipmentOrderId={}", shipmentOrderId);
        ShipmentOrder shipmentOrder = shipmentOrderMapper.selectOne(Wrappers.<ShipmentOrder>lambdaQuery().eq(ShipmentOrder::getId, shipmentOrderId));
        List<ShipmentOrderDetail> shipmentOrderDetails = shipmentOrderDetailMapper.selectList(Wrappers.<ShipmentOrderDetail>lambdaQuery()
                .eq(ShipmentOrderDetail::getShipmentOrderId, shipmentOrderId));
        if (CollectionUtils.isNotEmpty(shipmentOrderDetails)) {
            shipmentOrderDetails.forEach(item -> {
                String shipmentDetailId = item.getId();
                ShipmentOrderRelateDriver shipmentOrderRelateDriver = shipmentOrderRelateDriverMapper.selectOne(Wrappers.<ShipmentOrderRelateDriver>lambdaQuery()
                        .eq(ShipmentOrderRelateDriver::getShipmentOrderId, shipmentOrderId)
                );
                List<ShipmentOrderDetailGoodsInfo> shipmentOrderDetailGoodsInfos = shipmentOrderDetailGoodsInfoMapper.selectList(Wrappers.<ShipmentOrderDetailGoodsInfo>lambdaQuery()
                        .eq(ShipmentOrderDetailGoodsInfo::getShipmentOrderDetailId, shipmentDetailId)
                );
                if (CollectionUtils.isNotEmpty(shipmentOrderDetailGoodsInfos)) {
                    shipmentOrderDetailGoodsInfos.forEach(goodsInfo -> {
                        ShipmentOrderReport shipmentOrderReport = shipmentOrderReportMapper.selectOne(Wrappers.<ShipmentOrderReport>lambdaQuery()
                                .eq(ShipmentOrderReport::getTrainNumber, shipmentOrder.getTrainNumber())
                                .eq(ShipmentOrderReport::getOrderNumber, item.getOrderNumber())
                                .eq(ShipmentOrderReport::getGoodsType, goodsInfo.getGoodsType())
                                .eq(ShipmentOrderReport::getProductCode, goodsInfo.getProductCode()));
                        if (shipmentOrderReport == null) {
                            shipmentOrderReport = new ShipmentOrderReport();
                            this.buildShipmentOrderReport(shipmentOrder, item, shipmentOrderRelateDriver, goodsInfo, shipmentOrderReport);
                            shipmentOrderReportMapper.insert(shipmentOrderReport);
                        } else {
                            this.buildShipmentOrderReport(shipmentOrder, item, shipmentOrderRelateDriver, goodsInfo, shipmentOrderReport);
                            shipmentOrderReportMapper.updateById(shipmentOrderReport);
                        }
                    });
                }
                if (Objects.isNull(shipmentOrderRelateDriver)) {
                    shipmentOrderReportMapper.update(new ShipmentOrderReport(), Wrappers.<ShipmentOrderReport>lambdaUpdate()
                            .set(ShipmentOrderReport::getPeriodDay, null)
                            .set(ShipmentOrderReport::getDriverName, null)
                            .set(ShipmentOrderReport::getDriverPhone, null)
                            .set(ShipmentOrderReport::getCarNumber, null)
                            .eq(ShipmentOrderReport::getTrainNumber, shipmentOrder.getTrainNumber())
                    );
                }
            });
        }
    }


    /**
     * 构建报表信息
     *
     * @param shipmentOrder
     * @param item
     * @param shipmentOrderRelateDriver
     * @param goodsInfo
     * @param shipmentOrderReport
     */
    private void buildShipmentOrderReport(ShipmentOrder shipmentOrder, ShipmentOrderDetail item, ShipmentOrderRelateDriver shipmentOrderRelateDriver
            , ShipmentOrderDetailGoodsInfo goodsInfo, ShipmentOrderReport shipmentOrderReport) {

        //构建基础信息
        this.buildBaseInfo(shipmentOrder, shipmentOrderReport);

        //构建详细信息
        this.buildDetailInfo(item, shipmentOrderReport);

        //构建约车信息
        this.buildDriverInfo(shipmentOrderRelateDriver, shipmentOrderReport);

        //构建产品信息
        this.buildGoodsInfo(goodsInfo, shipmentOrderReport);
    }

    /**
     * 构建产品信息
     *
     * @param goodsInfo
     * @param shipmentOrderReport
     */
    private void buildGoodsInfo(ShipmentOrderDetailGoodsInfo goodsInfo, ShipmentOrderReport shipmentOrderReport) {
        shipmentOrderReport.setGoodsType(goodsInfo.getGoodsType());
        shipmentOrderReport.setProductCode(goodsInfo.getProductCode());
        shipmentOrderReport.setProductName(goodsInfo.getProductName());
        shipmentOrderReport.setProductType(goodsInfo.getProductType());
        shipmentOrderReport.setProductWeight(goodsInfo.getProductWeight());
        shipmentOrderReport.setProductSize(goodsInfo.getProductSize());
        shipmentOrderReport.setProductNumber(goodsInfo.getProductNumber());
        shipmentOrderReport.setProductUnit(goodsInfo.getProductUnit());
        shipmentOrderReport.setDelFlag(goodsInfo.getDelFlag());
        shipmentOrderReport.setCreateTime(goodsInfo.getCreateTime());
        shipmentOrderReport.setUpdateTime(goodsInfo.getUpdateTime());
        shipmentOrderReport.setCreateBy(goodsInfo.getCreateBy());
        shipmentOrderReport.setUpdateBy(goodsInfo.getUpdateBy());
    }


    /**
     * 构建预约信息
     *
     * @param shipmentOrderRelateDriver
     * @param shipmentOrderReport
     */
    private void buildDriverInfo(ShipmentOrderRelateDriver shipmentOrderRelateDriver, ShipmentOrderReport shipmentOrderReport) {
        if (Objects.nonNull(shipmentOrderRelateDriver)) {
            shipmentOrderReport.setDriverPhone(shipmentOrderRelateDriver.getDriverPhone());
            shipmentOrderReport.setDriverName(shipmentOrderRelateDriver.getDriverName());
            shipmentOrderReport.setPeriodDay(shipmentOrderRelateDriver.getPeriodDay());
            shipmentOrderReport.setCarNumber(shipmentOrderRelateDriver.getCarNumber());
        }
    }


    /**
     * 构建订单详情
     *
     * @param item
     * @param shipmentOrderReport
     */
    private void buildDetailInfo(ShipmentOrderDetail item, ShipmentOrderReport shipmentOrderReport) {
        shipmentOrderReport.setAddress(item.getAddress());
        shipmentOrderReport.setCardBoard(item.getCardBoard());
        shipmentOrderReport.setOrderNumber(item.getOrderNumber());
        shipmentOrderReport.setDetailId(item.getId());
        shipmentOrderReport.setConsigneeName(item.getConsigneeName());
        shipmentOrderReport.setConsigneePhone(item.getConsigneePhone());
        shipmentOrderReport.setRealReceiveNumber(item.getRealReceiveNumber());
        shipmentOrderReport.setDealerNumber(item.getDealerNumber());
        shipmentOrderReport.setDealerName(item.getDealerName());
    }


    /**
     * 构建车次基础信息
     *
     * @param shipmentOrder
     * @param shipmentOrderReport
     */
    private void buildBaseInfo(ShipmentOrder shipmentOrder, ShipmentOrderReport shipmentOrderReport) {
        shipmentOrderReport.setTrainNumber(shipmentOrder.getTrainNumber());
        shipmentOrderReport.setOrderStatus(shipmentOrder.getOrderStatus());
        shipmentOrderReport.setOutTime(shipmentOrder.getOutTime());
        shipmentOrderReport.setCompany(shipmentOrder.getCompany());
        shipmentOrderReport.setOutType(shipmentOrder.getOutType());
        shipmentOrderReport.setDeliveryMode(shipmentOrder.getDeliveryMode());
        shipmentOrderReport.setDispatchDate(shipmentOrder.getCreateTime());
        String storeBaseId = shipmentOrder.getStoreBaseId();
        shipmentOrderReport.setStoreBaseId(storeBaseId);
        shipmentOrderReport.setStoreBaseName(shipmentOrder.getStoreBaseName());
        if (StringUtils.isNotBlank(storeBaseId)) {
            StoreBase storeBase = storeBaseMapper.selectById(storeBaseId);
            shipmentOrderReport.setStoreBaseCode(storeBase.getBaseCode());
        }
        shipmentOrderReport.setModes(shipmentOrder.getModes());
        AccessControlSystemCarInfo accessControlSystemCarInfo = accessControlSystemCarInfoMapper.selectOne(Wrappers.<AccessControlSystemCarInfo>lambdaQuery()
                .eq(AccessControlSystemCarInfo::getTrainNumber, shipmentOrder.getTrainNumber())
                .orderByDesc(AccessControlSystemCarInfo::getCreateTime)
                .last("limit 1")
        );
        if (accessControlSystemCarInfo != null) {
            shipmentOrderReport.setInTime(accessControlSystemCarInfo.getInTime());
            shipmentOrderReport.setSecondWeightTime(accessControlSystemCarInfo.getSecondWeightTime());
        }
    }
}
package com.eastroc.common.utils;

import com.eastroc.common.consts.ArrangeConstant;
import org.jeecg.common.util.ExecutorServiceFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.concurrent.CompletableFuture;

@Component
public class TransactionSynchronizationUtil {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * mq同步到历史订单报表
     *
     * @param shipmentOrderId
     */
    public void syncReportTransaction(String shipmentOrderId) {
        try {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    CompletableFuture.runAsync(() -> {
                        rabbitTemplate.convertAndSend(ArrangeConstant.E_EXCHANGE, ArrangeConstant.K_SHIPMENT_ORDER_REPORT_ONE, shipmentOrderId);
                    }, ExecutorServiceFactory.getInstance());
                }
            });
        } catch (
                Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * mq同步到历史订单报表
     *
     * @param shipmentOrderId
     */
    public void syncReport(String shipmentOrderId) {
        CompletableFuture.runAsync(() -> {
            rabbitTemplate.convertAndSend(ArrangeConstant.E_EXCHANGE, ArrangeConstant.K_SHIPMENT_ORDER_REPORT_ONE, shipmentOrderId);
        }, ExecutorServiceFactory.getInstance());
    }
}

觉得有用的话点个赞 👍🏻 呗。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

img

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 1. 首先,在IDE中创建一个Spring Boot项目。 2. 在项目中添加所需的依赖项,例如Spring Boot Starter Web,Spring Boot Starter Data JPA等。 3. 在application.properties文件中配置数据库连接信息,例如数据库URL,用户名和密码等。 4. 创建实体类和数据访问对象(DAO)类,以便在应用程序中访问数据库。 5. 创建服务类和控制器类,以便在应用程序中实现业务逻辑和处理HTTP请求。 6. 在控制器类中使用@RestController注解,以便将其转换为RESTful Web服务。 7. 在应用程序的启动类中使用@SpringBootApplication注解,以便自动配置Spring Boot应用程序。 8. 运行应用程序并测试其功能。 ### 回答2: 在配置Idea开发环境中,首先需要创建一个Spring Boot项目。在这里,我会选择使用Spring Initializr进行创建。 步骤概述: 1. 打开Idea后,选择Create New Project 2. 选择Spring Initializr 3. 选择Spring Boot项目类型 4. 输入项目名称和项目位置 5. 配置项目信息,包括项目依赖信息、项目描述等 6. 点击Finish完成项目创建 在项目创建完成后,接下来需要对项目进行配置。 1. 配置Maven 在Idea中,Maven会自动的进行配置,但是有些时候可能会遇到一些问题,需要手动进行配置。具体的配置方法可以参考Maven的官方文档。 2. 配置Spring Boot配置Spring Boot时,需要在pom文件中添加Spring Boot相关的依赖,如spring-boot-starter-web、spring-boot-devtools等。这些依赖可以通过Maven自动添加到pom文件中。 3. 配置数据库连接 在使用Spring Boot进行开发时,通常需要使用到数据库,因此需要对数据库进行配置Spring Boot支持多种数据库,包括MySQL、PostgreSQL、Oracle等。在配置数据库时,需要在application.properties或者application.yml文件中添加数据库相关的配置信息。 4. 配置日志 在开发过程中,日志是十分重要的,它可以帮助我们快速定位问题。在Spring Boot中,默认使用Logback作为日志框架。如果需要进行定制,可以在pom文件中添加Logback的相关依赖,并在logback.xml文件中进行配置。 5. 配置启动方式 在Spring Boot中,有多种启动方式,包括通过IDEA启动、通过命令行启动等。在IDEA中,我们可以通过Spring Boot面板来启动项目。 总结: 通过以上的步骤,我们可以成功的配置一个Spring Boot项目,实现基本的开发功能。当然,在实际的开发过程中,还需要根据不同的业务需求进行更加详细的配置。 ### 回答3: 在使用IDEA配置Spring Boot项目时,我们需要执行以下步骤: 1. 创建一个Spring Boot项目 首先,我们需要在IDEA中创建一个Spring Boot项目。可以选择在“New Project”对话框中选择“Spring Initializr”来创建项目。然后,在弹出的对话框中指定项目拥有的基本信息,例如项目类型、名称、描述和所需的依赖项。单击“Next”按钮来创建项目。 2. 配置项目依赖项 一旦我们创建了项目,我们需要为其添加所需的依赖项。对项目进行右键单击,选择“Add Framework Support”选项,然后从列表中选择所需的依赖项。如果我们需要添加自定义依赖项,则可以在“pom.xml”文件中手动添加。 3. 配置数据库连接 在“application.properties”文件中配置数据库连接,配置数据库的连接地址、端口、用户名、密码等。 4. 创建实体类 创建与数据库表对应的实体类。实体类负责定义数据表中的字段和属性。 5. 创建DAO层 创建一个与实体类相对应的DAO类,并在其中定义一些操作以与数据库进行交互。使用Spring Data JPA可以避免写大量的DAO层代码。 6. 编写业务逻辑 创建一个Service层并在其中实现业务逻辑。Service层是应用程序的核心,负责处理所有业务逻辑。 7. 创建控制器 创建一个Controller层并在其中实现一些API。API是Service层和前端之间的桥梁。 通过以上步骤,我们就可以使用IDEA来配置Spring Boot项目。当我们完全理解以上步骤,我们可以进一步深入研究Spring Boot框架中各种注解和工具来更好地掌握解决问题的技能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Kwan的解忧杂货铺

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

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

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

打赏作者

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

抵扣说明:

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

余额充值