Commit cbaf93de authored by 以墨为白's avatar 以墨为白 🎧

1

parents
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Intellij
*.iml
.idea/
logs/
<?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.example</groupId>
<artifactId>szpt_pre_service2</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<mysql-connector.version>8.0.16</mysql-connector.version>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
<druid.version>1.1.10</druid.version>
<swagger.version>2.9.2</swagger.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--启用热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.2</version>
</dependency>
</dependencies>
<build>
<defaultGoal>compile</defaultGoal>
<finalName>szpt_pre_service</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
package com.zksy.szpt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
* Hello world!
*/
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
})
@ServletComponentScan
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
package com.zksy.szpt.aspect;
import com.zksy.szpt.domain.HttpResult;
import com.zksy.szpt.domain.HttpResultState;
import com.zksy.szpt.service.AppStoreService;
import com.zksy.szpt.util.EncryptUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
//@Aspect//声明切面,标记类(1时间,2地点,3内容)
//@Component
public class AuthAspect {
private static final Logger logger = LoggerFactory.getLogger(AuthAspect.class);
@Resource
AppStoreService appStoreService;
//
@Pointcut("execution( * com.zksy.szpt.controller.*.*(..))")
private void auth() {
}
@Around(value = "auth()")
public Object auth(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
// 按请求参数名及参数值相互连接组成一个字符串
Map<String, String> param = new HashMap<>();
for (int i = 0; i < paramNames.length; i++) {
if (paramValues[i] instanceof Map) {//接口参数
Map<String, Object> bodyPara = (Map<String, Object>) paramValues[i];
Iterator<Map.Entry<String, Object>> iterator = bodyPara.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
String key = entry.getKey();
Object value = entry.getValue();
param.put(key, value == null ? "" : value.toString());
}
} else {//系统级参数
param.put(paramNames[i], paramValues[i].toString());
}
}
String appSecret = appStoreService.getAppSecretByAppKey(param.get("appKey"));
//appKey不存在
if (appSecret == null) {
HttpResultState httpResultState = HttpResultState.NOTIFICATION;
logger.info("appKey:{}不存在", param.get("appKey"));
httpResultState.setMessage("不存在的appKey");
return new HttpResult<String>(httpResultState);
}
//客户端传递过来的签名
String clientSign = param.get("sign");
param.remove("sign");
//根据客户端的参数生成的签名
String serverSign = EncryptUtil.getInstance().shaEncode(appSecret + sortJoin(param) + appSecret);
//传递的签名通过
if (serverSign.equals(clientSign)) {
return joinPoint.proceed();
} else {//传递的签名没有通过
logger.info("appKey:{}没有通过验证", param.get("appKey"));
return new HttpResult<String>(HttpResultState.INVALID_TOKEN);
}
}
private String sortJoin(Map<String, String> map) {
// 移除值为空的
map.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()) || "".equals(entry.getValue()));
List<Map.Entry<String, String>> infoIds = new ArrayList<>(map.entrySet());
// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
infoIds.sort((o1, o2) -> o1.getKey().compareToIgnoreCase(o2.getKey()));
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> infoId : infoIds) {
sb.append(infoId.getKey());
// sb.append("=");
sb.append(infoId.getValue());
// sb.append("&");
}
return sb.substring(0, sb.length());
}
}
package com.zksy.szpt.aspect;
import com.zksy.szpt.domain.HttpResult;
import com.zksy.szpt.domain.HttpResultState;
import org.apache.ibatis.javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;
/**
* Created by wcy on 2024/12/26.
* 全局异常处理,包括404
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
//一般错误
@ExceptionHandler(value = Exception.class)
@ResponseBody
public HttpResult<HttpResultState> defaultErrorHandle(HttpServletRequest req, Exception e) {
logger.error("错误信息如下:", e);
HttpResultState state = HttpResultState.ERROR;
return new HttpResult<>(state);
}
//not found
@ResponseBody
@ExceptionHandler(value = {NotFoundException.class, NoHandlerFoundException.class})
public HttpResult<HttpResultState> handlerNotFoundException(HttpServletRequest req, Exception e) {
HttpResultState state = HttpResultState.NOT_FOUND;
state.setMessage("请求的资源" + req.getRequestURL() + "不存在");
return new HttpResult<>(state);
}
//region 输入参数相关的异常
//valid注解
//(Bean 校验异常)
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public HttpResult<HttpResultState> handlerMethodArgumentNotValidException(HttpServletRequest req, MethodArgumentNotValidException e) {
logger.warn(e.getMessage());
HttpResultState state = HttpResultState.INVALID_PARAMETER;
state.setMessage(e.getBindingResult().getFieldErrors().stream().map(k -> k.getField() + "[" + k.getRejectedValue() + "]" + k.getDefaultMessage()).collect(Collectors.joining(";")));
return new HttpResult<>(state);
}
//validate注解
//(方法参数校验异常)如实体类中的@Size注解配置和数据库中该字段的长度不统一等问题
@ExceptionHandler(value = ConstraintViolationException.class)
@ResponseBody
public HttpResult<HttpResultState> handlerConstraintViolationException(HttpServletRequest req, ConstraintViolationException e) {
logger.warn(e.getMessage());
HttpResultState state = HttpResultState.INVALID_PARAMETER;
state.setMessage(e.getMessage());
return new HttpResult<>(state);
}
//RequestBody反序列化失败
@ResponseBody
@ExceptionHandler({HttpMessageNotReadableException.class})
public HttpResult<HttpResultState> messageExceptionHandler(HttpMessageNotReadableException e) {
logger.warn("http请求参数转换异常: " + e.getMessage());
HttpResultState state = HttpResultState.INVALID_PARAMETER;
state.setMessage("请求参数不正确");
return new HttpResult<>(state);
}
//RequestParam参数缺失
@ResponseBody
@ExceptionHandler({MissingServletRequestParameterException.class})
public HttpResult<HttpResultState> MissParameterExceptionHandler(MissingServletRequestParameterException e) {
logger.warn(e.getMessage());
HttpResultState state = HttpResultState.INVALID_PARAMETER;
state.setMessage(e.getMessage());
return new HttpResult<>(state);
}
//RequestParam参数类型错误
@ResponseBody
@ExceptionHandler({MethodArgumentTypeMismatchException.class})
public HttpResult<HttpResultState> MethodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException e) {
logger.warn(e.getMessage());
HttpResultState state = HttpResultState.INVALID_PARAMETER;
state.setMessage(e.getCause().getMessage());
return new HttpResult<>(state);
}
// @ResponseBody
// @ExceptionHandler({ParameterDataTypeException.class})
// public HttpResult<HttpResultState> ParameterDataTypeExceptionHandler(ParameterDataTypeException e) {
// logger.warn(e.getMessage());
// HttpResultState state = HttpResultState.INVALID_PARAMETER;
// state.setMessage(e.getMessage());
// return new HttpResult<>(state);
// }
//endregion
//region 数据库相关异常
//处理数据层面的顶级异常
@ResponseBody
@ExceptionHandler({DataAccessException.class})
public HttpResult<HttpResultState> DataAccessExceptionHandler(DataAccessException e) {
logger.error(e.getMessage());
HttpResultState state = HttpResultState.DATABASE;
return new HttpResult<>(state);
}
//违反唯一约束
@ResponseBody
@ExceptionHandler({DuplicateKeyException.class})
public HttpResult<HttpResultState> DuplicateKeyExceptionHandler(DuplicateKeyException e) {
logger.warn(e.getMessage());
HttpResultState state = HttpResultState.DUPLICATED_KEY;
state.setMessage(e.getCause().getMessage());
return new HttpResult<>(state);
}
//endregion
// @ResponseBody
// @ExceptionHandler({NotificationException.class})
// public HttpResult<HttpResultState> NotificationExceptionHandler(NotificationException e) {
// HttpResultState state = HttpResultState.NOTIFICATION;
// state.setMessage(e.getMessage());
// return new HttpResult<>(state);
// }
}
package com.zksy.szpt.aspect;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.szpt.domain.HttpResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
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;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
@RestControllerAdvice(basePackages = "com.zksy.szpt.controller")
public class ResponseBodyAnalysis implements ResponseBodyAdvice {
private final ObjectMapper Mapper;
public ResponseBodyAnalysis(ObjectMapper mapper) {
Mapper = mapper;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter arg1,
MediaType arg2, Class arg3, ServerHttpRequest arg4,
ServerHttpResponse arg5) {
if (body instanceof HttpResult) {
return body;//异常处理
} else {
HttpResult httpResult = new HttpResult(body);
if (body instanceof String) {//如果control层返回的结果是字符串,则需要手动转换
try {
return Mapper.writeValueAsString(httpResult);
} catch (JsonProcessingException e) {
}
} else if (body == null) {//特殊情况需要,string却返回null的时候
Method method = arg1.getMethod();
Type type = method.getReturnType();
if ("java.lang.String".equals(type.getTypeName())) {
try {
return Mapper.writeValueAsString(httpResult);
} catch (JsonProcessingException e) {
}
}
}
return httpResult;//其他类型处理
}
}
@Override
public boolean supports(MethodParameter arg0, Class arg1) {
return true;
}
}
\ No newline at end of file
package com.zksy.szpt.aspect;
import cn.hutool.crypto.digest.DigestUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.szpt.domain.HttpResult;
import com.zksy.szpt.domain.HttpResultState;
import com.zksy.szpt.service.AppStoreService;
import com.zksy.szpt.util.EncryptUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@Aspect//声明切面,标记类(1时间,2地点,3内容)
@Component
public class SignatureAspect {
private static final Logger logger = LoggerFactory.getLogger(AuthAspect.class);
@Resource
AppStoreService appStoreService;
@Resource
ObjectMapper objectMapper;
//
@Pointcut("execution( * com.zksy.szpt.controller.*.*(..))")
private void auth() {
}
@Around(value = "auth()")
public Object auth(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
// 获取请求头中的参数
String appId = request.getHeader("appId");
String nonce = request.getHeader("nonce");
String timestamp = request.getHeader("timestamp");
String signature = request.getHeader("signature");
String appSecret = appStoreService.getAppSecretByAppKey(appId);
// String generatedSignature = EncryptUtil.getInstance().shaEncode(appId + nonce + timestamp + objectMapper.writeValueAsString(paramValues[0]) + appSecret);
String generatedSignature = DigestUtil.md5Hex(appId + nonce + timestamp + objectMapper.writeValueAsString(paramValues[0]) + appSecret);
if (!generatedSignature.equals(signature)) {
logger.error("签名验证失败,请求参数:{}", paramValues[0]);
HttpResultState httpResultState = HttpResultState.INVALID_TOKEN;
httpResultState.setMessage("签名验证失败");
return new HttpResult<String>(httpResultState);
} else {
return joinPoint.proceed();
}
}
}
package com.zksy.szpt.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
@Configuration
@MapperScan(basePackages = {"com.zksy.szpt.mapper"}, sqlSessionTemplateRef = "sqlSessionTemplate")
public class MybatisConfig {
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource getDateSource() {
return DataSourceBuilder.create().type(DruidDataSource.class).build();
}
@Bean(name = "sqlSessionFactory")
@Primary
public SqlSessionFactory getSqlSessionFactory(@Qualifier("dataSource") DataSource datasource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setCallSettersOnNulls(true);
configuration.setMapUnderscoreToCamelCase(true);
configuration.setLogImpl(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
bean.setConfiguration(configuration);
Interceptor interceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "mysql");
interceptor.setProperties(properties);
bean.setPlugins(interceptor);
org.springframework.core.io.Resource[] resources1 = new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml");
List<org.springframework.core.io.Resource> list = new ArrayList<>(Arrays.asList(resources1));
list.addAll(new ArrayList<>(Arrays.asList(resources1)));
bean.setMapperLocations(list.toArray(new org.springframework.core.io.Resource[0]));
return bean.getObject();
}
@Primary
@Bean(name = "transactionManager")
public DataSourceTransactionManager getTransactionManager() {
return new DataSourceTransactionManager(getDateSource());
}
@Bean("sqlSessionTemplate")
// 表示这个数据源是默认数据源
@Primary
public SqlSessionTemplate getSqlSessionTemplate(
@Qualifier("sqlSessionFactory") SqlSessionFactory sessionFactory) {
return new SqlSessionTemplate(sessionFactory);
}
}
package com.zksy.szpt.config;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Component
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// InterceptorRegistration interceptorRegistration = registry.addInterceptor(signatureInterceptor).order(1);
// addPathPatterns 用于添加拦截规则
// interceptorRegistration.addPathPatterns("/**");
// excludePathPatterns 用户排除拦截
//排除swagger
// interceptorRegistration.excludePathPatterns("/v2/**");
// interceptorRegistration.excludePathPatterns("/webjars/**");
// interceptorRegistration.excludePathPatterns("/swagger-resources/**");
// interceptorRegistration.excludePathPatterns("/configuration/**");
// //排除登录
// interceptorRegistration.excludePathPatterns("/rest/user/login");
// interceptorRegistration.excludePathPatterns("/rest/user/loginByToken");
// registry.addInterceptor(logInterceptor).order(2);
}
}
package com.zksy.szpt.controller;
import com.zksy.szpt.domain.dto.AppStoreDTO;
import com.zksy.szpt.service.AppStoreService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class InfSettingController {
private final AppStoreService appStoreService;
public InfSettingController(AppStoreService infApiSettingService) {
this.appStoreService = infApiSettingService;
}
@PostMapping("/infSetting")
public Object infSetting(@RequestBody AppStoreDTO appStoreDTO) {
return appStoreService.getAppSecretByAppKey("1");
}
}
package com.zksy.szpt.domain;
public class HttpResult<T> {
private T data;
private int code;
private String message;
private long timestamp;
public HttpResult() {
this.code = HttpResultState.SUCCESS.getCode();
this.message = HttpResultState.SUCCESS.getMessage();
this.timestamp = System.currentTimeMillis();
}
public HttpResult(T data) {
this.data = data;
this.code = HttpResultState.SUCCESS.getCode();
this.message = HttpResultState.SUCCESS.getMessage();
this.timestamp = System.currentTimeMillis();
}
public HttpResult(HttpResultState state) {
this.code = state.getCode();
this.message = state.getMessage();
this.timestamp = System.currentTimeMillis();
}
public static <T> HttpResult<T> success() {
return new HttpResult<>();
}
public static <T> HttpResult<T> success(T data) {
return new HttpResult<>(data);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
\ No newline at end of file
package com.zksy.szpt.domain;
public enum HttpResultState {
SUCCESS(9000, "成功"),
INVALID_PARAMETER(9020, "无效的输入参数"),
NOTIFICATION(9030, "警告"),
MULTI_DEVICE_LOGIN(9040, "登录已失效,账户已在别处登录,请重新登录"),
EXPIRE(9041, "登录已经过期,请重新登录"),
INVALID_TOKEN(9042, "身份验证失败"),
GATEWAY(9050, "请求的服务不存在,请联系管理员"),
DATABASE(9060, "服务器错误1,请联系管理员"),
DUPLICATED_KEY(9061, "数据已存在"),
NOT_FOUND(9070, "请求的资源不存在"),
DEGRADATION(9080, "服务降级"),
ERROR(9999, "服务器错误2,请联系管理员");
HttpResultState(Integer code, String message) {
this.code = code;
this.message = message;
}
private Integer code;
private String message;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.zksy.szpt.domain.dto;
public class AppStoreDTO {
private Long id;
private String appKey;
private String appSecret;
private String create_time;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
public String getCreate_time() {
return create_time;
}
public void setCreate_time(String create_time) {
this.create_time = create_time;
}
}
package com.zksy.szpt.domain.po;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@TableName("tb_app_store")
public class AppStore {
@TableId
private Long id;
private String appKey;
private String appSecret;
private String create_time;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
public String getCreate_time() {
return create_time;
}
public void setCreate_time(String create_time) {
this.create_time = create_time;
}
}
package com.zksy.szpt.filter;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
/**
* 该类用于包装HttpServletRequest,以便在读取请求体后仍可重复读取
*/
public class ReusableBodyRequestWrapper extends HttpServletRequestWrapper {
//参数字节数组,用于存储请求体的字节数据
private byte[] requestBody;
//Http请求对象
private HttpServletRequest request;
/**
* 构造函数,初始化包装类
* @param request 原始HttpServletRequest对象
* @throws IOException 如果读取请求体时发生IO错误
*/
public ReusableBodyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
this.request = request;
}
/**
* 重写getInputStream方法,实现请求体的重复读取
* @return 包含请求体数据的ServletInputStream对象
* @throws IOException 如果读取请求体时发生IO错误
*/
@Override
public ServletInputStream getInputStream() throws IOException {
/**
* 每次调用此方法时将数据流中的数据读取出来,然后再回填到InputStream之中
* 解决通过@RequestBody和@RequestParam(POST方式)读取一次后控制器拿不到参数问题
*/
//仅当requestBody未初始化时,从请求中读取并存储到requestBody
if (null == this.requestBody) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(request.getInputStream(), baos);
this.requestBody = baos.toByteArray();
}
//创建一个 ByteArrayInputStream 对象,用于重复读取requestBody
final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public boolean isFinished() {
//始终返回false,表示数据流未完成
return false;
}
@Override
public boolean isReady() {
//始终返回false,表示数据流未准备好
return false;
}
@Override
public void setReadListener(ReadListener listener) {
//不执行任何操作,因为该数据流不支持异步操作
}
@Override
public int read() {
//从ByteArrayInputStream中读取数据
return bais.read();
}
};
}
/**
* 获取请求体的字节数组
* @return 请求体的字节数组
*/
public byte[] getRequestBody() {
return requestBody;
}
/**
* 重写getReader方法,返回一个基于getInputStream的BufferedReader
* @return 包含请求体数据的BufferedReader对象
* @throws IOException 如果读取请求体时发生IO错误
*/
@Override
public BufferedReader getReader() throws IOException {
//基于getInputStream创建BufferedReader
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
\ No newline at end of file
package com.zksy.szpt.filter;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.szpt.domain.HttpResult;
import com.zksy.szpt.domain.HttpResultState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@Order(1)
@WebFilter(urlPatterns = "/**", filterName = "SignatureVerificationFilter")
@Component
public class SignatureVerificationFilter extends OncePerRequestFilter {
public static Logger logger = LoggerFactory.getLogger(SignatureVerificationFilter.class);
private final ObjectMapper objectMapper;
public SignatureVerificationFilter(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 对request进行包装,支持重复读取body
ReusableBodyRequestWrapper requestWrapper = new ReusableBodyRequestWrapper(request);
// 校验签名
if (this.verifySignature(requestWrapper, response)) {
filterChain.doFilter(requestWrapper, response);
}
}
// 签名秘钥
private String secretKey = "2";
/**
* 校验签名
*
* @param request HTTP请求
* @param response HTTP响应
* @return 签名验证结果
* @throws IOException 如果读取请求体失败
*/
public boolean verifySignature(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 签名
String appId = request.getHeader("appId");
// 签名
String sign = request.getHeader("signature");
// 随机数
String nonce = request.getHeader("nonce");
// 时间戳
String timestampStr = request.getHeader("timestamp");
if (!StringUtils.hasText(sign) || !StringUtils.hasText(nonce) || !StringUtils.hasText(timestampStr)) {
this.write(response, "参数错误");
return false;
}
// timestamp 10分钟内有效
// long timestamp = Long.parseLong(timestampStr);
// long currentTimestamp = System.currentTimeMillis() / 1000;
// if (Math.abs(currentTimestamp - timestamp) > 600) {
// this.write(response, "请求已过期");
// return false;
// }
// 防止请求重放,nonce只能用一次,放在redis中,有效期 20分钟
// String nonceKey = "SignatureVerificationFilter:nonce:" + nonce;
// if (!this.redisTemplate.opsForValue().setIfAbsent(nonceKey, "1", 20, TimeUnit.MINUTES)) {
// this.write(response, "nonce无效");
// return false;
// }
// 请求体
String body = objectMapper.writeValueAsString(objectMapper.readValue(StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8), Map.class));
// 需要签名的数据:secretKey+noce+timestampStr+body
// 校验签名
String data = String.format("%s%s%s%s%s", appId, nonce, timestampStr, body, this.secretKey);
if (!DigestUtil.md5Hex(data).equals(sign)) {
write(response, "签名有误");
return false;
}
return true;
}
/**
* 向客户端写入响应信息
*
* @param response HTTP响应
* @param msg 响应信息
* @throws IOException 如果写入失败
*/
private void write(HttpServletResponse response, String msg) throws IOException {
HttpResultState httpResultState = HttpResultState.INVALID_TOKEN;
httpResultState.setMessage(msg);
HttpResult<String> httpResult = new HttpResult<>(httpResultState);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write(JSONUtil.toJsonStr(httpResult));
}
}
package com.zksy.szpt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zksy.szpt.domain.po.AppStore;
public interface AppStoreMapper extends BaseMapper<AppStore> {
}
package com.zksy.szpt.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zksy.szpt.domain.po.AppStore;
import com.zksy.szpt.mapper.AppStoreMapper;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AppStoreService {
private final AppStoreMapper appStoreMapper;
public AppStoreService(AppStoreMapper appStoreMapper) {
this.appStoreMapper = appStoreMapper;
}
public String getAppSecretByAppKey(String appKey) {
LambdaQueryWrapper<AppStore> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AppStore::getAppKey, appKey);
List<AppStore> tbAppStorePOList = appStoreMapper.selectList(queryWrapper);
if (tbAppStorePOList != null && !tbAppStorePOList.isEmpty()) {
return tbAppStorePOList.get(0).getAppSecret();
}
return null;
}
}
package com.zksy.szpt.util;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
public class EncryptUtil {
private static final String DES = "DES";
private static final String AES = "AES";
/**
* 编码格式;默认使用uft-8
*/
private final String charset = "utf-8";
/**
* DES
*/
private final int keySizeDES = 0;
/**
* AES
*/
private final int keySizeAES = 128;
private static EncryptUtil instant;
private EncryptUtil() {
//单例
}
//双重锁
public static EncryptUtil getInstance() {
if (instant == null) {
synchronized (EncryptUtil.class) {
if (instant == null) {
instant = new EncryptUtil();
}
}
}
return instant;
}
/**
* 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错
*
* @param res 加密的原文
* @param algorithm 加密使用的算法名称
* @param key 加密的秘钥
* @param keySize
* @param isEncode
*/
private String keyGeneratorES(String res, String algorithm, String key, int keySize, boolean isEncode) {
try {
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
if (keySize == 0) {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(new SecureRandom(keyBytes));
} else if (key == null) {
kg.init(keySize);
} else {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(keySize, new SecureRandom(keyBytes));
}
SecretKey sk = kg.generateKey();
SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
if (isEncode) {
cipher.init(Cipher.ENCRYPT_MODE, sks);
byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
return parseByte2HexStr(cipher.doFinal(resBytes));
} else {
cipher.init(Cipher.DECRYPT_MODE, sks);
return new String(cipher.doFinal(parseHexStr2Byte(res)));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将二进制转换成16进制
*/
public String parseByte2HexStr(byte[] buf) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* 将16进制转换为二进制
*/
public byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
/**
* 使用DES加密算法进行加密(可逆)
*
* @param res 需要加密的原文
* @param key 秘钥
*/
private String DESEncode(String res, String key) {
return keyGeneratorES(res, DES, key, keySizeDES, true);
}
/**
* 对使用DES加密算法的密文进行解密(可逆)
*
* @param res 需要解密的密文
* @param key 秘钥
*/
private String DESDecode(String res, String key) {
return keyGeneratorES(res, DES, key, keySizeDES, false);
}
/**
* 使用AES加密算法经行加密(可逆)
*
* @param res 需要加密的密文
* @param key 秘钥
*/
public String AESEncode(String res, String key) {
return keyGeneratorES(res, AES, key, keySizeAES, true);
}
/**
* 对使用AES加密算法的密文进行解密
*
* @param res 需要解密的密文
* @param key 秘钥
*/
private String AESDecode(String res, String key) {
return keyGeneratorES(res, AES, key, keySizeAES, false);
}
/**
* 使用Base64进行加密
*
* @param res 密文
*/
public String Base64Encode(String res) {
return Base64.encode(res.getBytes());
}
/**
* 使用Base64进行解密
*
* @param res
*/
public String Base64Decode(String res) {
byte[] bytes = Base64.decode(res);
return null == bytes ? null : new String(bytes);
}
//md5
public String md5Hex(String src) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bs = md5.digest(src.getBytes());
return parseByte2HexStr(bs);
} catch (Exception e) {
return null;
}
}
public String shaEncode(String inStr) {
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance("SHA");
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
return "";
}
byte[] byteArray = inStr.getBytes(StandardCharsets.UTF_8);
byte[] md5Bytes = sha.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
public String encrypt_ECB_PKCS5Padding(String keyValue, String data) {
byte[] result = null;
SecretKey key = new SecretKeySpec(parseHexStr2Byte(keyValue), "AES");
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
result = cipher.doFinal(parseHexStr2Byte(data));
} catch (Exception e) {
e.printStackTrace();
}
return parseByte2HexStr(result);
}
}
\ No newline at end of file
package com.zksy.szpt.util;
import cn.hutool.crypto.digest.DigestUtil;
import org.springframework.util.StringUtils;
import java.util.UUID;
public class SignatureUtil {
/**
* 生成签名
*
* @param body 请求体
* @param secretKey 密钥
* @param nonce 随机数
* @param timestamp 时间戳
* @return 签名
*/
public static String generateSignature(String body, String secretKey, String nonce, String timestamp) {
if (!StringUtils.hasText(body) || !StringUtils.hasText(secretKey) || !StringUtils.hasText(nonce) || !StringUtils.hasText(timestamp)) {
throw new IllegalArgumentException("参数不能为空");
}
// 按照 secretKey + nonce + timestamp + body 的顺序拼接字符串
String data = String.format("%s%s%s%s", secretKey, nonce, timestamp, body);
System.out.println("data = " + data);
// 使用MD5算法计算签名
String sign = DigestUtil.md5Hex(data);
return sign;
}
public static void main(String[] args) {
// 示例参数
String body = "{\n" +
" \"fromAccountId\": \"张三\",\n" +
" \"toAccountId\": \"李四\",\n" +
" \"transferPrice\": 100\n" +
"}";
//秘钥
String secretKey = "b0e8668b-bcf2-4d73-abd4-893bbc1c6079";
// 随机数
String nonce = UUID.randomUUID().toString().replace("-", "");
// 时间戳
long timestamp = System.currentTimeMillis() / 1000;
// 生成签名
String sign = generateSignature(body, secretKey, nonce, String.valueOf(timestamp));
// 输出生成的签名
System.out.println("X-Sign: " + sign);
System.out.println("X-Nonce: " + nonce);
System.out.println("X-Timestamp: " + timestamp);
}
}
spring:
datasource:
url: jdbc:mysql://192.168.168.110:3306/swagger?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
server:
port: 8086
spring:
profiles:
active: dev
main:
allow-bean-definition-overriding: true
mvc:
throw-exception-if-no-handler-found: true
resources:
add-mappings: false
# 文件上传大小限制
servlet:
multipart:
enabled: true #是否启用http上传处理
max-request-size: 2000MB #最大请求文件的大小
max-file-size: 1000MB #设置单个文件最大长度
file-size-threshold: 500MB #当文件达到多少时进行磁盘写入
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义属性,设置控制台打印模板-->
<property name="STDOUT_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %boldYellow(%thread) %boldGreen(%logger) %boldMagenta(%L) %msg%n"/>
<property name="LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%L] - %msg%n"/>
<!--文件日志-->
<appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>logs/%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<!--日志文件最大的大小-->
<maxFileSize>100MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!--输出日志级别等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
<!-- onMatch="ACCEPT" 表示匹配该级别及以上-->
<!-- onMatch="DENY" 表示不匹配该级别及以上-->
<!-- onMatch="NEUTRAL" 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上-->
<!-- onMismatch="ACCEPT" 表示匹配该级别以下-->
<!-- onMismatch="NEUTRAL" 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的-->
<!-- onMismatch="DENY" 表示不匹配该级别以下的-->
</filter>
</appender>
<!--异常文件日志-->
<appender name="errorFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>logs/%d{yyyy-MM-dd}-[ERROR].%i.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
<maxFileSize>100MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!--输出日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>
<!--sql文件日志-->
<appender name="sqlFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>logs/%d{yyyy-MM-dd}-[SQL].%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<!--日志文件最大的大小-->
<maxFileSize>100MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--控制台-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${STDOUT_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--定义了三种记录器,优先级由高到低-->
<!-- mybatis sql-->
<!--根据包路径-->
<!-- <logger name="com.zksy.szpcs" level="INFO" additivity="false">-->
<!-- <appender-ref ref="fileAppender"/>-->
<!-- <appender-ref ref="STDOUT"/>-->
<!-- <appender-ref ref="errorFileAppender"/>-->
<!-- </logger>-->
<!--getLogger找不到的时候调用 尽量不用,不然引用的jar包中打印的日志也会显示-->
<!-- <root level="INFO">-->
<!-- <appender-ref ref="STDOUT"/>-->
<!-- <appender-ref ref="fileAppender"/>-->
<!-- <appender-ref ref="errorFileAppender"/>-->
<!-- </root>-->
<!-- 屏蔽swagger包的日志-->
<logger name="springfox.documentation" level="OFF">
</logger>
<!-- 根据配置文件spring.profiles.active选择不同的日志配置-->
<springProfile name="dev, default">
<logger name="com.zksy.szpt.mapper" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="prod">
<logger name="com.zksy.szpt.mapper" level="DEBUG" additivity="false">
<appender-ref ref="sqlFileAppender"/>
</logger>
<root level="INFO">
<appender-ref ref="fileAppender"/>
<appender-ref ref="errorFileAppender"/>
</root>
</springProfile>
</configuration>
package com.zksy.szpt;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/**
* A simple unit test
*/
public class MainTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment