commit
a865ed59c2
42 changed files with 2981 additions and 0 deletions
@ -0,0 +1,42 @@ |
|||
package com.qs.cost; |
|||
|
|||
import org.springframework.boot.SpringApplication; |
|||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|||
import org.springframework.boot.builder.SpringApplicationBuilder; |
|||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; |
|||
import org.springframework.scheduling.annotation.EnableScheduling; |
|||
import org.springframework.transaction.annotation.EnableTransactionManagement; |
|||
|
|||
import javax.annotation.PostConstruct; |
|||
import javax.servlet.ServletContext; |
|||
import javax.servlet.ServletException; |
|||
import java.util.TimeZone; |
|||
|
|||
/** |
|||
* @author USER |
|||
*/ |
|||
@EnableScheduling |
|||
@EnableTransactionManagement |
|||
@SpringBootApplication |
|||
public class Application extends SpringBootServletInitializer { |
|||
|
|||
public static void main(String[] args) { |
|||
SpringApplication.run(Application.class,args); |
|||
} |
|||
|
|||
@Override |
|||
public void onStartup(ServletContext servletContext) throws ServletException { |
|||
super.onStartup(servletContext); |
|||
} |
|||
|
|||
@Override |
|||
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { |
|||
return builder.sources(Application.class); |
|||
} |
|||
|
|||
@PostConstruct |
|||
void started() { |
|||
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,19 @@ |
|||
package com.qs.cost.common.conf; |
|||
|
|||
import org.springframework.cache.annotation.EnableCaching; |
|||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
@EnableCaching |
|||
@Configuration |
|||
public class CacheConfig { |
|||
|
|||
@Bean |
|||
public ConcurrentMapCacheManager cacheManager() { |
|||
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(); |
|||
//cacheManager.setStoreByValue(true); //true表示缓存一份副本,否则缓存引用
|
|||
return cacheManager; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,28 @@ |
|||
package com.qs.cost.common.conf; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonInclude; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.context.annotation.Primary; |
|||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; |
|||
|
|||
/** |
|||
* @Author: YenHex |
|||
* @Date: 2021/3/11 |
|||
* @Version: 1.0 |
|||
**/ |
|||
@Slf4j |
|||
@Configuration |
|||
public class JacksonConfig { |
|||
@Bean |
|||
@Primary |
|||
@ConditionalOnMissingBean(ObjectMapper.class) |
|||
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { |
|||
ObjectMapper objectMapper = builder.createXmlMapper(false).build(); |
|||
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); |
|||
return objectMapper; |
|||
} |
|||
} |
@ -0,0 +1,27 @@ |
|||
package com.qs.cost.common.conf; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
import org.springframework.boot.context.properties.ConfigurationProperties; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/7/7 |
|||
*/ |
|||
|
|||
@Getter |
|||
@Setter |
|||
@Component |
|||
@ConfigurationProperties(prefix = "server") |
|||
public class MainServerProperties { |
|||
|
|||
private String host; |
|||
|
|||
private String book; |
|||
|
|||
private String year; |
|||
|
|||
private String u8url; |
|||
|
|||
} |
@ -0,0 +1,40 @@ |
|||
package com.qs.cost.common.conf; |
|||
|
|||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
|||
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.mybatis.spring.annotation.MapperScan; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.transaction.annotation.EnableTransactionManagement; |
|||
|
|||
|
|||
/** |
|||
* @Author: YenHex |
|||
* @Date: 2021/3/4 |
|||
* @Version: 1.0 |
|||
**/ |
|||
@Slf4j |
|||
@Configuration |
|||
@EnableTransactionManagement |
|||
@MapperScan({ |
|||
"com.qs.cost.module.mapper", |
|||
}) |
|||
public class MyBatisConfig { |
|||
|
|||
|
|||
@Bean |
|||
public MybatisPlusInterceptor mybatisPlusInterceptor() { |
|||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); |
|||
// 添加防止全表更新与删除拦截器
|
|||
interceptor.addInnerInterceptor(blockAttackInnerInterceptor()); |
|||
return interceptor; |
|||
} |
|||
|
|||
public BlockAttackInnerInterceptor blockAttackInnerInterceptor(){ |
|||
BlockAttackInnerInterceptor blockAttackInnerInterceptor=new BlockAttackInnerInterceptor(); |
|||
return blockAttackInnerInterceptor; |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,47 @@ |
|||
package com.qs.cost.common.conf; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.web.cors.CorsConfiguration; |
|||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
|||
import org.springframework.web.filter.CorsFilter; |
|||
import org.springframework.web.multipart.MultipartResolver; |
|||
import org.springframework.web.multipart.commons.CommonsMultipartResolver; |
|||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/24 |
|||
*/ |
|||
@AllArgsConstructor |
|||
@Configuration(proxyBeanMethods = false) |
|||
public class SpringMvcConfig implements WebMvcConfigurer { |
|||
|
|||
|
|||
@Bean |
|||
public CorsFilter corsFilter() { |
|||
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); |
|||
final CorsConfiguration corsConfiguration = new CorsConfiguration(); |
|||
/*是否允许请求带有验证信息*/ |
|||
corsConfiguration.setAllowCredentials(false); |
|||
/*允许访问的客户端域名*/ |
|||
corsConfiguration.addAllowedOrigin("*"); |
|||
/*允许服务端访问的客户端请求头*/ |
|||
corsConfiguration.addAllowedHeader("*"); |
|||
/*允许访问的方法名,GET POST等*/ |
|||
corsConfiguration.addAllowedMethod("*"); |
|||
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); |
|||
return new CorsFilter(urlBasedCorsConfigurationSource); |
|||
} |
|||
|
|||
//@Bean
|
|||
public MultipartResolver multipartResolver(){ |
|||
CommonsMultipartResolver resolver = new CommonsMultipartResolver(); |
|||
resolver.setMaxInMemorySize(5120); |
|||
resolver.setMaxInMemorySize(300 * 1024 * 1024); |
|||
resolver.setDefaultEncoding("UTF-8"); |
|||
return resolver; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,50 @@ |
|||
package com.qs.cost.common.consts; |
|||
|
|||
/** |
|||
* ERP API地址 |
|||
* @Author: YenHex |
|||
* @Date: 2021/3/12 |
|||
* @Version: 1.0 |
|||
**/ |
|||
public class ApiUrlConst { |
|||
|
|||
public static final String lzyunli = "lzyunli"; |
|||
|
|||
public static final String U8API = "/Service/13Service.asmx/U8API"; |
|||
|
|||
/** |
|||
* 删除专业发票 |
|||
*/ |
|||
public static final String GET_ORDER = "https://sc.gdjiajin.com/index.php/getOrder"; |
|||
|
|||
/** |
|||
* 删除普通发票 |
|||
*/ |
|||
public static final String UPD_ORDER = "https://sc.gdjiajin.com/index.php/upOrder"; |
|||
|
|||
/** |
|||
* 添加销售订单 |
|||
*/ |
|||
public static final String U8_ADD_XSDD = "XSDDAdd"; |
|||
|
|||
/** |
|||
* 添加销售报价单 |
|||
*/ |
|||
public static final String U8_ADD_XSBJ = "XSBJDAdd"; |
|||
|
|||
/** |
|||
* 添加专业发票 |
|||
*/ |
|||
public static final String U8_ADD_ZYFP = "ZYFPAdd"; |
|||
|
|||
/** |
|||
* 添加普通发票 |
|||
*/ |
|||
public static final String U8_ADD_PTFP = "PTFPAdd"; |
|||
|
|||
/** |
|||
* 获取销售订单编码 |
|||
*/ |
|||
public static final String U8_GET_XSDD_CODE = "GETXSDDCODE"; |
|||
|
|||
} |
@ -0,0 +1,17 @@ |
|||
package com.qs.cost.common.dto; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/25 |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@AllArgsConstructor |
|||
public class BeanParams{ |
|||
private String json; |
|||
private String keyId; |
|||
} |
@ -0,0 +1,30 @@ |
|||
package com.qs.cost.common.dto; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 对请求结果统一封装 |
|||
* @author YenHex |
|||
* @since 2022/2/25 |
|||
*/ |
|||
@Data |
|||
public class HttpResult { |
|||
|
|||
public HttpResult(Integer code,String message){ |
|||
this.message = message; |
|||
this.code = code; |
|||
} |
|||
|
|||
public HttpResult(Integer code,String message,String data){ |
|||
this.data = data; |
|||
this.message = message; |
|||
this.code = code; |
|||
} |
|||
|
|||
private String message; |
|||
|
|||
private Integer code; |
|||
|
|||
private String data; |
|||
|
|||
} |
@ -0,0 +1,45 @@ |
|||
package com.qs.cost.common.dto; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
@Getter |
|||
@Setter |
|||
public class PageVo<T>{ |
|||
|
|||
/** |
|||
* 页幅 |
|||
*/ |
|||
private Integer pageSize; |
|||
|
|||
/** |
|||
* 页眉 |
|||
*/ |
|||
private Integer pageNum; |
|||
|
|||
/** |
|||
* 总数据数 |
|||
*/ |
|||
private Integer total; |
|||
|
|||
/** |
|||
* 总页数 |
|||
*/ |
|||
private Integer totalPage; |
|||
|
|||
/** |
|||
* 数据列表 |
|||
*/ |
|||
private List<T> list; |
|||
|
|||
public void initPageNum(Integer total,Integer pageSize,Integer pageNum){ |
|||
this.pageNum = pageNum; |
|||
this.pageSize = pageSize; |
|||
if(pageSize==null||pageSize==0){ return; } |
|||
this.totalPage = total%pageSize==0?total/pageSize:(total/pageSize+1); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,105 @@ |
|||
package com.qs.cost.common.dto; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 统一返回封装 |
|||
* 1.替代旧版的ViewResult |
|||
* 2.支持SmartDoc |
|||
* @author JcYen |
|||
* @date 2021/4/22 |
|||
* @version 2.0 |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
public class R<T>{ |
|||
|
|||
public R( int status, String message) { |
|||
this.status = status; |
|||
this.message = message; |
|||
} |
|||
|
|||
public R( int status, String message, T data) { |
|||
this.status = status; |
|||
this.message = message; |
|||
this.data = data; |
|||
} |
|||
|
|||
/** |
|||
* 状态码 |
|||
*/ |
|||
private Integer status; |
|||
|
|||
/** |
|||
* 信息 |
|||
*/ |
|||
private String message; |
|||
|
|||
/** |
|||
* 数据 |
|||
*/ |
|||
private T data; |
|||
|
|||
public static final int SUCCESS_STATUS = 200; |
|||
public static final int LOGOUT_STATUS = 401; |
|||
public static final int FORBIDDEN_STATUS = 403; |
|||
public static final int NOT_FOUND_STATUS = 434; |
|||
public static final int FAILED_STATUS = 500; |
|||
|
|||
public static final String SUCCESS_TIPS = "操作成功"; |
|||
public static final String FAILED_TIPS = "操作失败"; |
|||
public static final String LOGOUT_TIPS = "登录无效"; |
|||
public static final String FORBIDDEN_TIPS = "无权限访问"; |
|||
public static final String NOT_FOUND_TIPS = "数据不存在或被移除"; |
|||
|
|||
public static R ok() { |
|||
return new R(SUCCESS_STATUS,SUCCESS_TIPS,null); |
|||
} |
|||
|
|||
public static R ok(String msg) { |
|||
return new R<>(SUCCESS_STATUS,msg,null); |
|||
} |
|||
|
|||
public static <TYPE> R<TYPE> ok(TYPE data) { |
|||
return new R<>(SUCCESS_STATUS,SUCCESS_TIPS,data); |
|||
} |
|||
|
|||
public static <TYPE> R<TYPE> ok(TYPE data,String message) { |
|||
return new R<>(SUCCESS_STATUS,message,data); |
|||
} |
|||
|
|||
public static R isTrue(Boolean bool){ |
|||
if(bool==null|| !bool){ |
|||
return error(); |
|||
} |
|||
return ok(); |
|||
} |
|||
|
|||
public R isTrue(Boolean bool, String message){ |
|||
if(bool==null|| !bool){ |
|||
return error(message); |
|||
} |
|||
return ok(null,message); |
|||
} |
|||
|
|||
|
|||
public static <TYPE> R<TYPE> isNotNull(TYPE object){ |
|||
if(object==null){ |
|||
return error(); |
|||
} |
|||
return ok(object,SUCCESS_TIPS); |
|||
} |
|||
|
|||
public static R error(String message) { |
|||
return new R<>(FAILED_STATUS,message,null); |
|||
} |
|||
|
|||
public static R error() { |
|||
return new R<>(FAILED_STATUS,FAILED_TIPS,null); |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,51 @@ |
|||
package com.qs.cost.common.dto.u8; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.IdType; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* 请求记录历史 实体类 |
|||
* @author YenHex |
|||
* @since 2022-02-28 |
|||
*/ |
|||
@Data |
|||
public class U8CallbackVo implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** id */ |
|||
@TableId(type = IdType.INPUT) |
|||
private String id; |
|||
|
|||
/** 账套、租户 */ |
|||
private String tenant; |
|||
|
|||
/** 客户端IP */ |
|||
private String clientHost; |
|||
|
|||
/** 接口名称 */ |
|||
private String apiCmd; |
|||
|
|||
/** 接口数据主键 */ |
|||
private String apiPk; |
|||
|
|||
/** 接口年份 */ |
|||
private String apiYear; |
|||
|
|||
/** 接口keyId */ |
|||
private String apiKeyId; |
|||
|
|||
/** 请求参数 */ |
|||
private String reqParams; |
|||
|
|||
|
|||
/** 数据返回结果 */ |
|||
private String respContext; |
|||
|
|||
|
|||
|
|||
} |
|||
|
@ -0,0 +1,74 @@ |
|||
package com.qs.cost.common.dto.u8; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import javax.validation.constraints.Max; |
|||
import javax.validation.constraints.Min; |
|||
import javax.validation.constraints.NotNull; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/25 |
|||
*/ |
|||
@Data |
|||
public class U8RequestBo { |
|||
|
|||
/** |
|||
* 业务主键ID |
|||
* <p>用于记录,便于维护查询</p> |
|||
* <p>实例:订单号,订单id</p> |
|||
*/ |
|||
private String pk; |
|||
|
|||
/** |
|||
* U8业务请求命令 |
|||
*/ |
|||
@NotNull |
|||
private String cmd; |
|||
|
|||
/** |
|||
* 年度 |
|||
*/ |
|||
@NotNull(message = "年度不能为空") |
|||
private String year; |
|||
|
|||
/** |
|||
* 账套 |
|||
*/ |
|||
@NotNull(message = "账套不能为空") |
|||
private String book; |
|||
|
|||
/** |
|||
* 请求json字符串 |
|||
*/ |
|||
@NotNull(message = "请求json字符串不能为空") |
|||
private String jsonBody; |
|||
|
|||
/** |
|||
* 暂无意义 |
|||
*/ |
|||
private String keyId; |
|||
|
|||
/** |
|||
* 设置失败重连次数 |
|||
*/ |
|||
@Max(value = 10,message = "重连次数不能超过10次") |
|||
@Min(value = 1,message = "重连次数不能少于1次") |
|||
private Integer settingRetryTimes; |
|||
|
|||
/** |
|||
* 是否回调(0-否;1-是) |
|||
*/ |
|||
private String callbackState; |
|||
|
|||
/** |
|||
* 回调地址(callbackState=1时,不能为空) |
|||
*/ |
|||
private String callbackHost; |
|||
|
|||
/** |
|||
* 立马运行(默认false) |
|||
*/ |
|||
private Boolean immediatelyRun; |
|||
|
|||
} |
@ -0,0 +1,32 @@ |
|||
package com.qs.cost.common.enums; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
|
|||
/** |
|||
* 请求状态码 |
|||
* @author YenHex |
|||
* @since 2022/2/28 |
|||
*/ |
|||
@Getter |
|||
@AllArgsConstructor |
|||
public enum HttpCode { |
|||
|
|||
/** 基本参数 */ |
|||
SUCCESS(200,"操作成功"), |
|||
ERROR(200,"操作失败"), |
|||
ERROR_CALLBACK_URL_EMPTY(200,"回调地址为空"), |
|||
|
|||
/** 资源权限相关 */ |
|||
FORBIDDEN_403(403,"无权访问"), |
|||
FORBIDDEN_403_1(403,"账套未注册,无权访问"), |
|||
FORBIDDEN_403_2(403,"IP地址未注册,无权访问"), |
|||
|
|||
FORBIDDEN_404(404,"资源不存在或被移除"), |
|||
|
|||
; |
|||
|
|||
Integer code; |
|||
String msg; |
|||
|
|||
} |
@ -0,0 +1,17 @@ |
|||
package com.qs.cost.common.framework.exception; |
|||
|
|||
/** |
|||
* @author JcYen |
|||
* @Date 2020/6/11 |
|||
* @Version 1.0 |
|||
*/ |
|||
public abstract class BaseException extends RuntimeException { |
|||
|
|||
public BaseException(String message){ |
|||
super(message); |
|||
} |
|||
|
|||
public abstract int getCode(); |
|||
|
|||
|
|||
} |
@ -0,0 +1,27 @@ |
|||
package com.qs.cost.common.framework.exception; |
|||
|
|||
import lombok.Getter; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* @author JcYen |
|||
* @Date 2020/6/11 |
|||
* @Version 1.0 |
|||
*/ |
|||
public class BusinessException extends BaseException implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
private Integer status; |
|||
|
|||
public BusinessException(String message,Integer status) { |
|||
super(message); |
|||
this.status = status; |
|||
} |
|||
|
|||
@Override |
|||
public int getCode() { |
|||
return status; |
|||
} |
|||
} |
@ -0,0 +1,90 @@ |
|||
package com.qs.cost.common.framework.exception; |
|||
|
|||
import com.qs.cost.common.dto.R; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.ConversionNotSupportedException; |
|||
import org.springframework.beans.TypeMismatchException; |
|||
import org.springframework.http.converter.HttpMessageNotReadableException; |
|||
import org.springframework.http.converter.HttpMessageNotWritableException; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.validation.BindException; |
|||
import org.springframework.validation.ObjectError; |
|||
import org.springframework.web.HttpMediaTypeNotAcceptableException; |
|||
import org.springframework.web.HttpMediaTypeNotSupportedException; |
|||
import org.springframework.web.HttpRequestMethodNotSupportedException; |
|||
import org.springframework.web.bind.MethodArgumentNotValidException; |
|||
import org.springframework.web.bind.MissingPathVariableException; |
|||
import org.springframework.web.bind.MissingServletRequestParameterException; |
|||
import org.springframework.web.bind.ServletRequestBindingException; |
|||
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.context.request.async.AsyncRequestTimeoutException; |
|||
import org.springframework.web.multipart.support.MissingServletRequestPartException; |
|||
import org.springframework.web.servlet.NoHandlerFoundException; |
|||
|
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* @Author JcYen |
|||
* @Date 2019/6/7 |
|||
* @Version 1.0 |
|||
*/ |
|||
@Slf4j |
|||
@Component |
|||
@ControllerAdvice |
|||
public class UnifiedExceptionHandler { |
|||
|
|||
@ExceptionHandler(value = BindException.class) |
|||
@ResponseBody |
|||
public R handleBindException(BindException e) { |
|||
log.warn("参数绑定异常", e); |
|||
return R.error(); |
|||
} |
|||
|
|||
@ExceptionHandler(value = BusinessException.class) |
|||
@ResponseBody |
|||
public R handleBindException(BusinessException e) { |
|||
return new R(e.getCode(),e.getMessage()); |
|||
} |
|||
|
|||
@ExceptionHandler(MethodArgumentNotValidException.class) |
|||
@ResponseBody |
|||
public R handleValidException(MethodArgumentNotValidException e) { |
|||
StringBuilder sb = new StringBuilder(); |
|||
List<ObjectError> allErrors = e.getBindingResult().getAllErrors(); |
|||
String message = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining(";")); |
|||
log.warn("参数校验异常:{}",message); |
|||
return R.error(); |
|||
} |
|||
|
|||
@ExceptionHandler({ |
|||
NoHandlerFoundException.class, |
|||
HttpRequestMethodNotSupportedException.class, |
|||
HttpMediaTypeNotSupportedException.class, |
|||
MissingPathVariableException.class, |
|||
MissingServletRequestParameterException.class, |
|||
TypeMismatchException.class, |
|||
HttpMessageNotReadableException.class, |
|||
HttpMessageNotWritableException.class, |
|||
HttpMediaTypeNotAcceptableException.class, |
|||
ServletRequestBindingException.class, |
|||
ConversionNotSupportedException.class, |
|||
MissingServletRequestPartException.class, |
|||
AsyncRequestTimeoutException.class |
|||
}) |
|||
@ResponseBody |
|||
public R handleServletException(Exception e) { |
|||
log.error("Servlet异常\n异常类型:{}\n异常信息:{}\n异常体:",e.getClass().getSimpleName(),e.getMessage(),e); |
|||
return R.error(); |
|||
} |
|||
|
|||
|
|||
@ExceptionHandler(value = Exception.class) |
|||
@ResponseBody |
|||
public R handleException(Exception e) { |
|||
log.error("Servlet异常\n异常类型:{}\n异常信息:{}\n异常体:",e.getClass().getSimpleName(),e.getMessage(),e); |
|||
return R.error(); |
|||
} |
|||
} |
@ -0,0 +1,31 @@ |
|||
package com.qs.cost.common.framework.interceptor; |
|||
|
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import javax.servlet.http.HttpServletResponse; |
|||
|
|||
import org.springframework.web.servlet.HandlerInterceptor; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.PrintWriter; |
|||
|
|||
|
|||
/** |
|||
* @author JcYen |
|||
* @Date 2020/6/11 |
|||
* @Version 1.0 |
|||
*/ |
|||
public class ForbiddenInterceptor implements HandlerInterceptor { |
|||
|
|||
@Override |
|||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { |
|||
try { |
|||
PrintWriter printWriter = response.getWriter(); |
|||
printWriter.println("{\"status\":403,\"message\":\"403 forbidden\"}"); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,21 @@ |
|||
package com.qs.cost.common.framework.mvc; |
|||
|
|||
import io.undertow.server.DefaultByteBufferPool; |
|||
import io.undertow.websockets.jsr.WebSocketDeploymentInfo; |
|||
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; |
|||
import org.springframework.boot.web.server.WebServerFactoryCustomizer; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Component |
|||
public class CustomizationBean implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> { |
|||
|
|||
@Override |
|||
public void customize(UndertowServletWebServerFactory factory) { |
|||
factory.addDeploymentInfoCustomizers(deploymentInfo -> { |
|||
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo(); |
|||
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 1024)); |
|||
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo); |
|||
}); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,161 @@ |
|||
package com.qs.cost.common.framework.mvc; |
|||
|
|||
import com.qs.cost.common.utils.DateUtil; |
|||
import com.qs.cost.common.utils.ServletUtil; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.core.annotation.Order; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.util.StringUtils; |
|||
|
|||
import javax.servlet.*; |
|||
import javax.servlet.annotation.WebFilter; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
import javax.servlet.http.HttpServletRequestWrapper; |
|||
import java.io.BufferedReader; |
|||
import java.io.ByteArrayInputStream; |
|||
import java.io.IOException; |
|||
import java.io.InputStreamReader; |
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
/** |
|||
* HttpServletRequest 过滤器 |
|||
* 解决: request.getInputStream()只能读取一次的问题 |
|||
* 目标: 流可重复读 |
|||
* @Author YenHex |
|||
* @Date 2021/4/9 |
|||
* @Version: 1.0 |
|||
**/ |
|||
@Slf4j |
|||
@Component |
|||
@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/") |
|||
@Order(10000) |
|||
public class HttpServletRequestFilter implements Filter{ |
|||
|
|||
|
|||
@Override |
|||
public void init(FilterConfig filterConfig) throws ServletException { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { |
|||
RequestWrapper requestWrapper = null; |
|||
if(servletRequest instanceof HttpServletRequest) { |
|||
requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest); |
|||
} |
|||
//servletResponse.setContentType("allowedOriginPatterns");
|
|||
long startTime = System.currentTimeMillis(); |
|||
//获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中
|
|||
// 在chain.doFiler方法中传递新的request对象
|
|||
if(null == requestWrapper) { |
|||
filterChain.doFilter(servletRequest, servletResponse); |
|||
} else { |
|||
filterChain.doFilter(requestWrapper, servletResponse); |
|||
} |
|||
long endTime = System.currentTimeMillis(); |
|||
double diffTime = DateUtil.printRunTime(startTime,endTime); |
|||
assert servletRequest instanceof HttpServletRequest; |
|||
HttpServletRequest request = (HttpServletRequest)servletRequest; |
|||
//String tenant = request.getHeader("tenant");
|
|||
//String authorization = request.getHeader("Authorization");
|
|||
String url = request.getRequestURL().toString(); |
|||
String method = request.getMethod(); |
|||
String queryStr = request.getQueryString(); |
|||
String ip = request.getRemoteHost(); |
|||
//HttpSession session = request.getSession();
|
|||
//session.removeAttribute("JSESSIONID");
|
|||
//String sessionId = session.getId();
|
|||
String reqBody = ""; |
|||
if (ServletUtil.isJsonRequest(request)) { |
|||
reqBody = requestWrapper.getBody(); |
|||
} |
|||
//String host = request.getRemoteHost();
|
|||
//String servletPath = request.getServletPath();
|
|||
StringBuffer buffer = new StringBuffer("["+method+"] "+url + " IP: "+ip); |
|||
if(!StringUtils.isEmpty(queryStr)){ |
|||
buffer.append("\n参数: "+queryStr); |
|||
} |
|||
if(!StringUtils.isEmpty(reqBody)){ |
|||
buffer.append("\n请求体: "+reqBody); |
|||
} |
|||
buffer.append("\n耗时: "+diffTime+"秒"); |
|||
if(diffTime>4){ |
|||
log.warn("访问速度:{}秒,接口:{},参数:{},请求体:{}",diffTime,"["+method+"] "+url,queryStr,reqBody); |
|||
} |
|||
//buffer.append("\n耗时: "+diffTime+"秒 Session:"+sessionId);
|
|||
System.out.println(buffer.toString()); |
|||
} |
|||
|
|||
@Override |
|||
public void destroy() { |
|||
|
|||
} |
|||
|
|||
/*** |
|||
* HttpServletRequest 包装器 |
|||
* 解决: request.getInputStream()只能读取一次的问题 |
|||
* 目标: 流可重复读 |
|||
*/ |
|||
public class RequestWrapper extends HttpServletRequestWrapper { |
|||
|
|||
/** |
|||
* 请求体 |
|||
*/ |
|||
private String mBody; |
|||
|
|||
public RequestWrapper(HttpServletRequest request) { |
|||
super(request); |
|||
mBody = getBody(request); |
|||
} |
|||
|
|||
/** |
|||
* 获取请求体 |
|||
* @param request 请求 |
|||
* @return 请求体 |
|||
*/ |
|||
private String getBody(HttpServletRequest request) { |
|||
return ServletUtil.getBodyString(request); |
|||
} |
|||
|
|||
/** |
|||
* 获取请求体 |
|||
* @return 请求体 |
|||
*/ |
|||
public String getBody() { |
|||
return mBody; |
|||
} |
|||
|
|||
@Override |
|||
public BufferedReader getReader() throws IOException { |
|||
return new BufferedReader(new InputStreamReader(getInputStream())); |
|||
} |
|||
|
|||
@Override |
|||
public ServletInputStream getInputStream() throws IOException { |
|||
// 创建字节数组输入流
|
|||
final ByteArrayInputStream bais = new ByteArrayInputStream(mBody.getBytes(StandardCharsets.UTF_8)); |
|||
|
|||
return new ServletInputStream() { |
|||
@Override |
|||
public boolean isFinished() { |
|||
return false; |
|||
} |
|||
|
|||
@Override |
|||
public boolean isReady() { |
|||
return false; |
|||
} |
|||
|
|||
@Override |
|||
public void setReadListener(ReadListener readListener) { |
|||
} |
|||
|
|||
@Override |
|||
public int read() throws IOException { |
|||
return bais.read(); |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,20 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import com.qs.cost.common.enums.HttpCode; |
|||
import com.qs.cost.common.framework.exception.BusinessException; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/25 |
|||
*/ |
|||
public class Assert { |
|||
|
|||
public static void throwEx(Integer code,String msg){ |
|||
throw new BusinessException(msg, code); |
|||
} |
|||
|
|||
public static void throwEx(HttpCode httpCode){ |
|||
throw new BusinessException(httpCode.getMsg(),httpCode.getCode()); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,93 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import org.springframework.cglib.beans.BeanCopier; |
|||
|
|||
import java.io.*; |
|||
import java.util.Collection; |
|||
import java.util.Map; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
|
|||
/** |
|||
* 取代BeanUtils.CP |
|||
* @Author JcYen |
|||
* @Date 2019/6/3 |
|||
* @Version 1.0 |
|||
*/ |
|||
public class BeanCopierUtil { |
|||
|
|||
private static final Map<String, BeanCopier> BEAN_COPIERS = new ConcurrentHashMap<String, BeanCopier>(); |
|||
|
|||
private static String genKey(Class<?> source, Class<?> target) { |
|||
return source.getName() + target.getName(); |
|||
} |
|||
|
|||
/** |
|||
* target字段值,会被source字段值覆盖(包括null) |
|||
* @param source |
|||
* @param target |
|||
*/ |
|||
public static <T> T copy(Object source, T target) { |
|||
String key = genKey(source.getClass(), target.getClass()); |
|||
BeanCopier copier; |
|||
if (!BEAN_COPIERS.containsKey(key)) { |
|||
copier = BeanCopier.create(source.getClass(), target.getClass(), false); |
|||
BEAN_COPIERS.put(key, copier); |
|||
} else { |
|||
copier = BEAN_COPIERS.get(key); |
|||
} |
|||
copier.copy(source, target, null); |
|||
return target; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 采用对象的序列化完成对象的深克隆 |
|||
* @param obj 待克隆的对象 |
|||
* @return |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <T extends Serializable> T cloneObject(T obj) { |
|||
T cloneObj = null; |
|||
try { |
|||
// 写入字节流
|
|||
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|||
ObjectOutputStream obs = new ObjectOutputStream(out); |
|||
obs.writeObject(obj); |
|||
obs.close(); |
|||
|
|||
// 分配内存,写入原始对象,生成新对象
|
|||
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); |
|||
ObjectInputStream ois = new ObjectInputStream(ios); |
|||
// 返回生成的新对象
|
|||
cloneObj = (T) ois.readObject(); |
|||
ois.close(); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return cloneObj; |
|||
} |
|||
|
|||
/** |
|||
* 利用序列化完成集合的深克隆 |
|||
* |
|||
* @param collection 待克隆的集合 |
|||
* @return |
|||
* @throws ClassNotFoundException |
|||
* @throws IOException |
|||
*/ |
|||
@SuppressWarnings("unchecked") |
|||
public static <T> Collection<T> cloneCollection(Collection<T> collection) throws ClassNotFoundException, IOException{ |
|||
ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); |
|||
ObjectOutputStream out = new ObjectOutputStream(byteOut); |
|||
out.writeObject(collection); |
|||
out.close(); |
|||
|
|||
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); |
|||
ObjectInputStream in = new ObjectInputStream(byteIn); |
|||
Collection<T> dest = (Collection<T>) in.readObject(); |
|||
in.close(); |
|||
|
|||
return dest; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,131 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import java.util.*; |
|||
|
|||
/** |
|||
* 常用数据工具类 |
|||
* |
|||
* @Author JcYen |
|||
* @Date 2019/5/23 |
|||
* @Version 1.0 |
|||
*/ |
|||
public class CollectionUtil { |
|||
|
|||
private CollectionUtil() { |
|||
super(); |
|||
} |
|||
|
|||
/** |
|||
* 判断一个集合是否为空 |
|||
*/ |
|||
public static <T> boolean isEmpty(Collection<T> col) { |
|||
if (col == null || col.isEmpty()) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public static <T> List<T> setToList(Set<T> colSet){ |
|||
if (colSet == null || colSet.isEmpty()){ |
|||
return new ArrayList<>(); |
|||
} |
|||
List<T> rs = new ArrayList<>(colSet); |
|||
return rs; |
|||
} |
|||
|
|||
/** |
|||
* 判断一个集合是否不为空 |
|||
*/ |
|||
public static <T> boolean isNotEmpty(Collection<T> col) { |
|||
return !isEmpty(col); |
|||
} |
|||
|
|||
/** |
|||
* 判断Map是否为空 |
|||
*/ |
|||
public static <K, V> boolean isEmpty(Map<K, V> map) { |
|||
if (map == null || map.isEmpty()) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 判断Map是否不为空为空 |
|||
*/ |
|||
public static <K, V> boolean isNotEmpty(Map<K, V> map) { |
|||
return !isEmpty(map); |
|||
} |
|||
|
|||
/** |
|||
* 去除list中的重复数据 |
|||
*/ |
|||
public static <T> List<T> removeRepeat(List<T> list) { |
|||
if (isEmpty(list)) { |
|||
return list; |
|||
} |
|||
List<T> result = new ArrayList<T>(); |
|||
for (T e : list) { |
|||
if (!result.contains(e)) { |
|||
result.add(e); |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
public static boolean hasNull(Object... objects){ |
|||
for (int i = 0; i < objects.length; i++) { |
|||
if(objects[i]==null){return true;} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public static boolean hasNotNull(Object... objects){ |
|||
for (int i = 0; i < objects.length; i++) { |
|||
if(objects[i]!=null){return true;} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 将集合转换为String数组 |
|||
*/ |
|||
public static <T> String[] toArray(List<T> list) { |
|||
if (isEmpty(list)) { |
|||
return null; |
|||
} |
|||
String[] result = new String[list.size()]; |
|||
for (int i = 0; i < list.size(); i++) { |
|||
result[i] = String.valueOf(list.get(i)); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 将list拆分成多给指定的大小的list |
|||
*/ |
|||
public static <T> List<List<T>> createList(List<T> target, int size) { |
|||
List<List<T>> listArr = new ArrayList<>(); |
|||
//获取被拆分的数组个数
|
|||
int arrSize = target.size()%size==0?target.size()/size:target.size()/size+1; |
|||
for(int i=0;i<arrSize;i++) { |
|||
List<T> sub = new ArrayList<T>(); |
|||
//把指定索引数据放入到list中
|
|||
for(int j=i*size;j<=size*(i+1)-1;j++) { |
|||
if(j<=target.size()-1) { |
|||
sub.add(target.get(j)); |
|||
} |
|||
} |
|||
listArr.add(sub); |
|||
} |
|||
return listArr; |
|||
} |
|||
|
|||
public static <T> T selectFirst(List<T> list){ |
|||
if(isNotEmpty(list)){ |
|||
return list.get(0); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,194 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import java.text.ParseException; |
|||
import java.text.SimpleDateFormat; |
|||
import java.time.LocalDateTime; |
|||
import java.time.ZoneId; |
|||
import java.time.ZonedDateTime; |
|||
import java.util.Calendar; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* 日期工具类 |
|||
* Created by macro on 2019/1/29. |
|||
*/ |
|||
public class DateUtil { |
|||
|
|||
public static final String FORMAT_SIMPLE_DATE_OF_YEAR_NUM = "MMdd"; |
|||
public static final String FORMAT_SIMPLE_DATE_OF_YEAR = "MM-dd"; |
|||
public static final String FORMAT_DATE_OF_YEAR = "MM-dd HH:mm:ss"; |
|||
public static final String FORMAT_DATE = "yyyy-MM-dd HH:mm:ss"; |
|||
public static final String FORMAT_SIMPLE_DATE_NUM = "yyyyMMdd"; |
|||
public static final String FORMAT_DATE_NUM = "yyyyMMddHHmmss"; |
|||
public static final String FORMAT_CRON = "ss mm HH dd MM ?"; |
|||
|
|||
public static final String FORMAT_SIMPLE_DATE_ZH = "yyyy年MM月dd日"; |
|||
public static final String FORMAT_DATE_ZH = "yyyy年MM月dd日 HH时mm分ss秒"; |
|||
|
|||
|
|||
public static final String FORMAT_SIMPLE_DATE = "yyyy-MM-dd"; |
|||
public static final String FORMAT_SIMPLE_DATE2 = "yyyy/MM/dd"; |
|||
public static final String FORMAT_SIMPLE_MONTH = "yyyy-MM"; |
|||
public static final String FORMAT_SIMPLE_YEAR = "yyyy"; |
|||
|
|||
|
|||
/** |
|||
* LocalDateTime转为日期 |
|||
* |
|||
* @param localDateTime LocalDateTime |
|||
* @return 日期 |
|||
*/ |
|||
public static Date localDateTimeToDate(final LocalDateTime localDateTime) { |
|||
if (null == localDateTime) { |
|||
return null; |
|||
} |
|||
final ZoneId zoneId = ZoneId.systemDefault(); |
|||
final ZonedDateTime zdt = localDateTime.atZone(zoneId); |
|||
final Date date = Date.from(zdt.toInstant()); |
|||
return date; |
|||
} |
|||
|
|||
/** |
|||
* 转换格式 |
|||
* @param dateStr |
|||
* @param format |
|||
* @return |
|||
*/ |
|||
public static Date getDateByFormatStr(String dateStr,String format){ |
|||
if(dateStr==null||format==null){return null;} |
|||
SimpleDateFormat sdf = new SimpleDateFormat(format); |
|||
Date date = null; |
|||
try { |
|||
date = sdf.parse(dateStr); |
|||
} catch (ParseException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return date; |
|||
} |
|||
|
|||
public static Double getDiffSecond(long beganTime, long endTime){ |
|||
return (double)(endTime - beganTime) / 1000.0D; |
|||
} |
|||
|
|||
/** 格式化日期字符串*/ |
|||
public static String formatDate(Date date,String format){ |
|||
SimpleDateFormat sdf = new SimpleDateFormat(format); |
|||
if(date!=null){ |
|||
return sdf.format(date); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public static Date format(Date date,String format){ |
|||
String dateString = formatDate(date, format); |
|||
SimpleDateFormat sdf = new SimpleDateFormat(format); |
|||
try { |
|||
if(dateString!=null){ |
|||
return sdf.parse(dateString); |
|||
} |
|||
} catch (ParseException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
|
|||
public static double printRunTime(long beganTime, long endTime) { |
|||
return (double)(endTime - beganTime) / 1000.0D; |
|||
} |
|||
|
|||
/** 获取一天的起始时间*/ |
|||
public static Date getBeginDateOfDay(Date date){ |
|||
Calendar calendar = Calendar.getInstance(); |
|||
calendar.setTime(date); |
|||
int day = calendar.get(Calendar.DATE); |
|||
calendar.set(Calendar.DATE,day-1); |
|||
calendar.set(Calendar.HOUR_OF_DAY,23); |
|||
calendar.set(Calendar.MINUTE,59); |
|||
calendar.set(Calendar.SECOND,59); |
|||
calendar.set(Calendar.MILLISECOND,99); |
|||
/*calendar.set(Calendar.HOUR_OF_DAY,0); |
|||
calendar.set(Calendar.MINUTE,0); |
|||
calendar.set(Calendar.SECOND,0); |
|||
calendar.set(Calendar.MILLISECOND,0);*/ |
|||
return calendar.getTime(); |
|||
} |
|||
|
|||
/** 获取一天的结束时间(23:59:59)*/ |
|||
public static Date getEndDateOfDay(Date date){ |
|||
Calendar calendar = Calendar.getInstance(); |
|||
calendar.setTime(date); |
|||
int day = calendar.get(Calendar.DATE); |
|||
calendar.set(Calendar.DATE,day+1); |
|||
calendar.set(Calendar.HOUR_OF_DAY,0); |
|||
calendar.set(Calendar.MINUTE,0); |
|||
calendar.set(Calendar.SECOND,0); |
|||
calendar.set(Calendar.MILLISECOND,0); |
|||
/*calendar.set(Calendar.HOUR_OF_DAY,23); |
|||
calendar.set(Calendar.MINUTE,59); |
|||
calendar.set(Calendar.SECOND,59); |
|||
calendar.set(Calendar.MILLISECOND,999);*/ |
|||
return calendar.getTime(); |
|||
} |
|||
|
|||
/** |
|||
* 获取未来某时间 |
|||
* @param date |
|||
* @param somedate |
|||
* @param calendarTimeSpan |
|||
*/ |
|||
public static Date getAfterSomedate(Date date,int somedate,int calendarTimeSpan){ |
|||
final Calendar calendar = Calendar.getInstance(); |
|||
calendar.setTime(date); |
|||
calendar.add(calendarTimeSpan,somedate); |
|||
return calendar.getTime(); |
|||
} |
|||
|
|||
/** 获取传入日期在某时间第一天 */ |
|||
public static Date getFirstDay(Date date,int calendarTimeSpan) { |
|||
Calendar cal = Calendar.getInstance(); |
|||
cal.setTime(date); |
|||
int last = cal.getActualMinimum(calendarTimeSpan); |
|||
cal.set(calendarTimeSpan, last); |
|||
return cal.getTime(); |
|||
} |
|||
|
|||
/** 获取传入日期在某时间最后一天 */ |
|||
public static Date getLastDay(Date date,int calendarTimeSpan) { |
|||
Calendar cal = Calendar.getInstance(); |
|||
cal.setTime(date); |
|||
int last = cal.getActualMaximum(calendarTimeSpan); |
|||
cal.set(calendarTimeSpan, last); |
|||
return cal.getTime(); |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 计算时差 |
|||
* @param smallDate |
|||
* @param bigDate |
|||
* @param unit 0天 1时 2分 3秒 |
|||
* @return |
|||
*/ |
|||
public static Long diffTime(Date smallDate,Date bigDate,int unit){ |
|||
long nd = 1000*24*60*60;//一天的毫秒数
|
|||
long nh = 1000*60*60;//一小时的毫秒数
|
|||
long nm = 1000*60;//一分钟的毫秒数
|
|||
long ns = 1000;//一秒钟的毫秒数
|
|||
|
|||
long t1 = smallDate.getTime(); |
|||
long t2 = bigDate.getTime(); |
|||
long diff = t2 - t1; |
|||
if(unit==0){ |
|||
return diff/nd; |
|||
}else if (unit==1){ |
|||
return diff%nd/nh; |
|||
}else if(unit==2){ |
|||
return diff%nd%nh/nm; |
|||
}else if(unit==3){ |
|||
return diff%nd%nh%nm/ns; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,479 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.http.HttpEntity; |
|||
import org.apache.http.HttpResponse; |
|||
import org.apache.http.HttpStatus; |
|||
import org.apache.http.NameValuePair; |
|||
import org.apache.http.client.ClientProtocolException; |
|||
import org.apache.http.client.config.RequestConfig; |
|||
import org.apache.http.client.entity.UrlEncodedFormEntity; |
|||
import org.apache.http.client.methods.CloseableHttpResponse; |
|||
import org.apache.http.client.methods.HttpGet; |
|||
import org.apache.http.client.methods.HttpPost; |
|||
import org.apache.http.client.methods.HttpRequestBase; |
|||
import org.apache.http.client.utils.URIBuilder; |
|||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; |
|||
import org.apache.http.entity.StringEntity; |
|||
import org.apache.http.impl.client.CloseableHttpClient; |
|||
import org.apache.http.impl.client.HttpClientBuilder; |
|||
import org.apache.http.impl.client.HttpClients; |
|||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; |
|||
import org.apache.http.message.BasicNameValuePair; |
|||
import org.apache.http.protocol.HTTP; |
|||
import org.apache.http.ssl.SSLContextBuilder; |
|||
import org.apache.http.ssl.TrustStrategy; |
|||
import org.apache.http.util.EntityUtils; |
|||
|
|||
import javax.net.ssl.SSLContext; |
|||
import java.io.*; |
|||
import java.net.URISyntaxException; |
|||
import java.nio.charset.Charset; |
|||
import java.security.cert.CertificateException; |
|||
import java.security.cert.X509Certificate; |
|||
import java.util.*; |
|||
|
|||
/** |
|||
* Created by JcYen on 2019/5/13 |
|||
* |
|||
* @Version v1.0 |
|||
**/ |
|||
@Slf4j |
|||
public class HttpService { |
|||
|
|||
private static PoolingHttpClientConnectionManager cm; |
|||
private static RequestConfig requestConfig; |
|||
private static String UTF_8 = "UTF-8"; |
|||
|
|||
private static void init() { |
|||
Integer poolSize = 10; |
|||
Integer connSize = 5; |
|||
Integer socketTimeout = 200; |
|||
Integer reqTimeout = 200; |
|||
Integer connTimeout = 200; |
|||
if (cm == null) { |
|||
cm = new PoolingHttpClientConnectionManager(); |
|||
cm.setMaxTotal(poolSize);// 整个连接池最大连接数
|
|||
cm.setDefaultMaxPerRoute(connSize);// 每路由最大连接数,默认值是2
|
|||
requestConfig = RequestConfig.custom() // 建立构造器
|
|||
.setConnectTimeout(connTimeout*1000)// 设置连接超时
|
|||
.setConnectionRequestTimeout(reqTimeout*1000)// 设置从连接池获取连接实例的超时
|
|||
.setSocketTimeout(socketTimeout*1000)// 设置读取超时
|
|||
.build();// 在提交请求之前 测试连接是否可用
|
|||
} |
|||
} |
|||
|
|||
/* 通过连接池获取HttpClient */ |
|||
private static CloseableHttpClient getHttpClient() { |
|||
init(); |
|||
return HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig).build(); |
|||
} |
|||
|
|||
/* get的URL请求 */ |
|||
public static String httpGetRequest(String url) { |
|||
HttpGet httpGet = new HttpGet(url); |
|||
return getResult(httpGet); |
|||
} |
|||
|
|||
public static InputStream httpGetStream(String url) { |
|||
HttpGet httpGet = new HttpGet(url); |
|||
CloseableHttpClient httpClient = getHttpClient(); |
|||
try { |
|||
CloseableHttpResponse response = httpClient.execute(httpGet); |
|||
HttpEntity entity = response.getEntity(); |
|||
if (entity != null) { |
|||
return entity.getContent(); |
|||
} |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/* get的URL的参数map请求 */ |
|||
public static String httpGetRequest(String url, Map<String, Object> params) throws URISyntaxException { |
|||
URIBuilder ub = new URIBuilder(); |
|||
ub.setPath(url); |
|||
ArrayList<NameValuePair> pairs = covertParams2NVPS(params); |
|||
ub.setParameters(pairs); |
|||
HttpGet httpGet = new HttpGet(ub.build()); |
|||
return getResult(httpGet); |
|||
} |
|||
|
|||
/* get的URL参数map,头map参数 */ |
|||
public static String httpGetRequest(String url, Map<String, Object> headers, Map<String, Object> params) |
|||
throws URISyntaxException { |
|||
URIBuilder ub = new URIBuilder(); |
|||
ub.setPath(url); |
|||
ArrayList<NameValuePair> pairs = covertParams2NVPS(params); |
|||
ub.setParameters(pairs); |
|||
HttpGet httpGet = new HttpGet(ub.build()); |
|||
for (Map.Entry<String, Object> param : headers.entrySet()) { |
|||
httpGet.addHeader(param.getKey(), String.valueOf(param.getValue())); |
|||
} |
|||
return getResult(httpGet); |
|||
} |
|||
|
|||
/* post的URL请求 */ |
|||
public static String httpPostRequest(String url) { |
|||
HttpPost httpPost = new HttpPost(url); |
|||
return getResult(httpPost); |
|||
} |
|||
|
|||
/* post的URL的参数map请求 */ |
|||
public static String httpPostRequest(String url, Map<String, Object> params) throws UnsupportedEncodingException { |
|||
HttpPost httpPost = new HttpPost(url); |
|||
ArrayList<NameValuePair> pairs = covertParams2NVPS(params); |
|||
httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8)); |
|||
log.debug("httpPostRequest -> URL:",httpPost.getURI().getPath()); |
|||
return getResult(httpPost); |
|||
} |
|||
/* post的URL的参数map请求 */ |
|||
public static HttpResult httpPostRequestWithResult(String url, Map<String, Object> params) { |
|||
HttpPost httpPost = new HttpPost(url); |
|||
ArrayList<NameValuePair> pairs = covertParams2NVPS(params); |
|||
try { |
|||
httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8)); |
|||
} catch (UnsupportedEncodingException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
log.debug("httpPostRequest -> URL:",httpPost.getURI().getPath()); |
|||
return getHttpResult(httpPost); |
|||
} |
|||
|
|||
/* post的URL的参数map请求map头 */ |
|||
public static String httpPostRequest(String url, Map<String, Object> headers, Map<String, Object> params) |
|||
throws UnsupportedEncodingException { |
|||
HttpPost httpPost = new HttpPost(url); |
|||
for (Map.Entry<String, Object> param : headers.entrySet()) { |
|||
httpPost.addHeader(param.getKey(), String.valueOf(param.getValue())); |
|||
} |
|||
ArrayList<NameValuePair> pairs = covertParams2NVPS(params); |
|||
httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8)); |
|||
return getResult(httpPost); |
|||
} |
|||
|
|||
/* post的URL的参数map请求map头及body信息 */ |
|||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
|||
public static String postMap(String url, Map<String, String> headerMap, Map<String, String> contentMap) { |
|||
String result = null; |
|||
CloseableHttpClient httpClient = HttpClients.createDefault(); |
|||
HttpPost post = new HttpPost(url); |
|||
List<NameValuePair> content = new ArrayList<NameValuePair>(); |
|||
Iterator iterator = contentMap.entrySet().iterator(); // 将content生成entity
|
|||
while (iterator.hasNext()) { |
|||
Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next(); |
|||
content.add(new BasicNameValuePair(elem.getKey(), elem.getValue())); |
|||
} |
|||
CloseableHttpResponse response = null; |
|||
try { |
|||
Iterator headerIterator = headerMap.entrySet().iterator(); // 循环增加header
|
|||
while (headerIterator.hasNext()) { |
|||
Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIterator.next(); |
|||
post.addHeader(elem.getKey(), elem.getValue()); |
|||
} |
|||
if (content.size() > 0) { |
|||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(content, "UTF-8"); |
|||
post.setEntity(entity); |
|||
} |
|||
response = httpClient.execute(post); // 发送请求并接收返回数据
|
|||
if (response != null && response.getStatusLine().getStatusCode() == 200) { |
|||
HttpEntity entity = response.getEntity(); // 获取response的body部分
|
|||
result = EntityUtils.toString(entity); // 读取reponse的body部分并转化成字符串
|
|||
} |
|||
return result; |
|||
} catch (UnsupportedEncodingException e) { |
|||
e.printStackTrace(); |
|||
} catch (ClientProtocolException e) { |
|||
e.printStackTrace(); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
try { |
|||
httpClient.close(); |
|||
if (response != null) { |
|||
response.close(); |
|||
} |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
|
|||
/* 中间工具 */ |
|||
private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) { |
|||
ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>(); |
|||
for (Map.Entry<String, Object> param : params.entrySet()) { |
|||
pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue()))); |
|||
} |
|||
return pairs; |
|||
} |
|||
|
|||
/* 发送的json的参数请求 */ |
|||
public static String httpPostJSON(String url, String json) throws UnsupportedEncodingException { |
|||
log.info("json"+json); |
|||
HttpPost httpPost = new HttpPost(url); |
|||
StringEntity entity = new StringEntity(json); |
|||
entity.setContentEncoding(UTF_8); |
|||
entity.setContentType("application/json");// 发送json数据需要设置contentType
|
|||
httpPost.setEntity(entity); |
|||
return getResult(httpPost); |
|||
} |
|||
|
|||
/* 发送的json的参数请求 */ |
|||
public static HttpResponse httpImagePostJSON(String url, String json) throws UnsupportedEncodingException { |
|||
CloseableHttpClient httpClient = HttpClientBuilder.create().build(); |
|||
HttpPost httpPost = new HttpPost(url); |
|||
httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json"); |
|||
StringEntity entity; |
|||
entity = new StringEntity(json); |
|||
entity.setContentType("image/png"); |
|||
httpPost.setEntity(entity); |
|||
HttpResponse response = null; |
|||
try { |
|||
response = httpClient.execute(httpPost); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return response; |
|||
} |
|||
|
|||
/* 发送的xml字符串 */ |
|||
public static String httpPostXML(String url, String xmlData) throws UnsupportedEncodingException { |
|||
HttpPost post = new HttpPost(url); |
|||
StringEntity entity = new StringEntity(xmlData); |
|||
entity.setContentEncoding(UTF_8); |
|||
entity.setContentType("text/xml;charset=UTF-8"); |
|||
return getResult(post); |
|||
} |
|||
|
|||
private static String getResult(HttpRequestBase request) { |
|||
return getHttpResult(request).getData(); |
|||
} |
|||
|
|||
private static HttpResult getHttpResult(HttpRequestBase request) { |
|||
CloseableHttpClient httpClient = getHttpClient(); |
|||
String errMsg = null; |
|||
Integer code = 500; |
|||
try { |
|||
CloseableHttpResponse response = httpClient.execute(request); |
|||
code = response.getStatusLine().getStatusCode(); |
|||
HttpEntity entity = response.getEntity(); |
|||
if (entity != null) { |
|||
String data = EntityUtils.toString(entity, UTF_8); |
|||
response.close(); |
|||
HttpResult result = new HttpResult(code,null,data); |
|||
return result; |
|||
} |
|||
} catch (ClientProtocolException e) { |
|||
log.error(e.getMessage()); |
|||
errMsg = e.getMessage(); |
|||
} catch (IOException e) { |
|||
log.error(e.getMessage()); |
|||
errMsg = e.getMessage(); |
|||
} |
|||
return new HttpResult(code,errMsg); |
|||
} |
|||
|
|||
public static String getXMLString() { |
|||
StringBuffer sb = new StringBuffer(); |
|||
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); |
|||
sb.append("<AastraIPPhoneInputScreen type=\"string\">"); |
|||
sb.append("<Title>Hello world!</Title>"); |
|||
sb.append("<Prompt>Enter value</Prompt>"); |
|||
sb.append("<URL>http://localhost/xmlserver/test.do</URL>"); |
|||
sb.append("<Parameter>value</Parameter>"); |
|||
sb.append("<Default></Default>"); |
|||
sb.append("</AastraIPPhoneInputScreen>"); |
|||
return sb.toString(); |
|||
} |
|||
|
|||
public static String doPost(String apiUrl, Object json) { |
|||
CloseableHttpClient httpClient = HttpClients.createDefault(); |
|||
String httpStr = null; |
|||
HttpPost httpPost = new HttpPost(apiUrl); |
|||
CloseableHttpResponse response = null; |
|||
try { |
|||
httpPost.setConfig(requestConfig); |
|||
StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");// 解决中文乱码问题
|
|||
stringEntity.setContentEncoding("UTF-8"); |
|||
stringEntity.setContentType("application/json"); |
|||
httpPost.setEntity(stringEntity); |
|||
response = httpClient.execute(httpPost); |
|||
HttpEntity entity = response.getEntity(); |
|||
System.out.println(response.getStatusLine().getStatusCode()); |
|||
httpStr = EntityUtils.toString(entity, "UTF-8"); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
if (response != null) { |
|||
try { |
|||
EntityUtils.consume(response.getEntity()); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
} |
|||
return httpStr; |
|||
} |
|||
|
|||
/** |
|||
* 发送 SSL POST 请求(HTTPS),K-V形式 |
|||
*/ |
|||
public static String doPostSSLXml(String apiUrl, String xml) { |
|||
CloseableHttpClient httpClient = createSSLClientDefault(); |
|||
HttpPost httpPost = new HttpPost(apiUrl); |
|||
CloseableHttpResponse response = null; |
|||
String httpStr = null; |
|||
try { |
|||
httpPost.setConfig(requestConfig); |
|||
StringEntity stringEntity = new StringEntity(xml, "UTF-8");// 解决中文乱码问题
|
|||
stringEntity.setContentEncoding("UTF-8"); |
|||
stringEntity.setContentType("text/xml;charset=UTF-8"); |
|||
httpPost.setEntity(stringEntity); |
|||
response = httpClient.execute(httpPost); |
|||
System.out.println(response); |
|||
// int statusCode = response.getStatusLine().getStatusCode();
|
|||
// if (statusCode != HttpStatus.SC_OK) {
|
|||
// return null;
|
|||
// }
|
|||
HttpEntity entity = response.getEntity(); |
|||
// if (entity == null) {
|
|||
// return null;
|
|||
// }
|
|||
httpStr = EntityUtils.toString(entity, "utf-8"); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
if (response != null) { |
|||
try { |
|||
EntityUtils.consume(response.getEntity()); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
} |
|||
return httpStr; |
|||
} |
|||
|
|||
public static String doGetSSL(String apiUrl) throws ClientProtocolException, IOException { |
|||
CloseableHttpClient httpClient = createSSLClientDefault(); |
|||
HttpGet httpget = new HttpGet(apiUrl); |
|||
CloseableHttpResponse response = null; |
|||
String httpStr = null; |
|||
httpget.setConfig(requestConfig); |
|||
response = httpClient.execute(httpget); |
|||
HttpEntity entity = response.getEntity(); |
|||
httpStr = EntityUtils.toString(entity, "utf-8"); |
|||
return httpStr; |
|||
} |
|||
|
|||
public static String doPostSSL(String apiUrl, Map<String, Object> params) |
|||
throws ClientProtocolException, IOException { |
|||
CloseableHttpClient httpClient = createSSLClientDefault(); |
|||
HttpPost httpPost = new HttpPost(apiUrl); |
|||
CloseableHttpResponse response = null; |
|||
String httpStr = null; |
|||
httpPost.setConfig(requestConfig); |
|||
List<NameValuePair> pairList = new ArrayList<NameValuePair>(params.size()); |
|||
for (Map.Entry<String, Object> entry : params.entrySet()) { |
|||
NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString()); |
|||
pairList.add(pair); |
|||
} |
|||
httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("utf-8"))); |
|||
response = httpClient.execute(httpPost); |
|||
HttpEntity entity = response.getEntity(); |
|||
httpStr = EntityUtils.toString(entity, "utf-8"); |
|||
return httpStr; |
|||
} |
|||
|
|||
/** |
|||
* 发送 SSL POST 请求(HTTPS),JSON形式 |
|||
* |
|||
* @param apiUrl |
|||
* API接口URL |
|||
* @param json |
|||
* JSON对象 |
|||
* @return |
|||
*/ |
|||
public static String doPostSSL(String apiUrl, Object json) { |
|||
CloseableHttpClient httpClient = createSSLClientDefault(); |
|||
HttpPost httpPost = new HttpPost(apiUrl); |
|||
CloseableHttpResponse response = null; |
|||
String httpStr = null; |
|||
try { |
|||
httpPost.setConfig(requestConfig); |
|||
StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");// 解决中文乱码问题
|
|||
stringEntity.setContentEncoding("UTF-8"); |
|||
stringEntity.setContentType("application/json"); |
|||
httpPost.setEntity(stringEntity); |
|||
response = httpClient.execute(httpPost); |
|||
int statusCode = response.getStatusLine().getStatusCode(); |
|||
if (statusCode != HttpStatus.SC_OK) { |
|||
return null; |
|||
} |
|||
HttpEntity entity = response.getEntity(); |
|||
if (entity == null) { |
|||
return null; |
|||
} |
|||
httpStr = EntityUtils.toString(entity, "utf-8"); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
if (response != null) { |
|||
try { |
|||
EntityUtils.consume(response.getEntity()); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
} |
|||
return httpStr; |
|||
} |
|||
|
|||
|
|||
|
|||
public static CloseableHttpClient createSSLClientDefault() { |
|||
try { |
|||
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { |
|||
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { |
|||
return true; |
|||
} |
|||
}).build(); |
|||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext); |
|||
return HttpClients.custom().setSSLSocketFactory(sslsf).build(); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return HttpClients.createDefault(); |
|||
} |
|||
|
|||
@Getter |
|||
@Setter |
|||
public static class HttpResult { |
|||
|
|||
public HttpResult(Integer code,String message){ |
|||
this.massage = message; |
|||
this.code = code; |
|||
} |
|||
|
|||
public HttpResult(Integer code,String message,String data){ |
|||
this.data = data; |
|||
this.massage = message; |
|||
this.code = code; |
|||
} |
|||
|
|||
private String massage; |
|||
|
|||
private Integer code; |
|||
|
|||
private String data; |
|||
|
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,121 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import com.qs.cost.common.dto.HttpResult; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.http.HttpEntity; |
|||
import org.apache.http.NameValuePair; |
|||
import org.apache.http.client.ClientProtocolException; |
|||
import org.apache.http.client.config.RequestConfig; |
|||
import org.apache.http.client.entity.UrlEncodedFormEntity; |
|||
import org.apache.http.client.methods.CloseableHttpResponse; |
|||
import org.apache.http.client.methods.HttpGet; |
|||
import org.apache.http.client.methods.HttpPost; |
|||
import org.apache.http.client.methods.HttpRequestBase; |
|||
import org.apache.http.entity.StringEntity; |
|||
import org.apache.http.impl.client.CloseableHttpClient; |
|||
import org.apache.http.impl.client.HttpClients; |
|||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; |
|||
import org.apache.http.message.BasicNameValuePair; |
|||
import org.apache.http.util.EntityUtils; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.UnsupportedEncodingException; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.ArrayList; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/28 |
|||
*/ |
|||
@Slf4j |
|||
public class HttpUtil { |
|||
|
|||
private static PoolingHttpClientConnectionManager cm; |
|||
private static RequestConfig requestConfig; |
|||
private static String UTF8 = "UTF-8"; |
|||
|
|||
private static void init() { |
|||
int poolSize = 10; |
|||
int connSize = 5; |
|||
int socketTimeout = 2000; |
|||
int reqTimeout = 2000; |
|||
int connTimeout = 2000; |
|||
if (cm == null) { |
|||
cm = new PoolingHttpClientConnectionManager(); |
|||
// 整个连接池最大连接数
|
|||
cm.setMaxTotal(poolSize); |
|||
// 每路由最大连接数,默认值是2
|
|||
cm.setDefaultMaxPerRoute(connSize); |
|||
// 建立构造器
|
|||
requestConfig = RequestConfig.custom() |
|||
// 设置连接超时
|
|||
.setConnectTimeout(connTimeout*1000) |
|||
// 设置从连接池获取连接实例的超时
|
|||
.setConnectionRequestTimeout(reqTimeout*1000) |
|||
// 设置读取超时
|
|||
.setSocketTimeout(socketTimeout*1000) |
|||
// 在提交请求之前 测试连接是否可用
|
|||
.build(); |
|||
} |
|||
} |
|||
/** 通过连接池获取HttpClient */ |
|||
private static CloseableHttpClient getHttpClient() { |
|||
init(); |
|||
return HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig).build(); |
|||
} |
|||
|
|||
public static HttpResult get(String url){ |
|||
HttpGet httpGet = new HttpGet(url); |
|||
httpGet.setHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"); |
|||
return getHttpResult(httpGet); |
|||
} |
|||
|
|||
/** post的URL的参数map请求 */ |
|||
public static HttpResult post(String url, String json) { |
|||
HttpPost httpPost = new HttpPost(url); |
|||
httpPost.setHeader("Accept","application/json"); |
|||
httpPost.setHeader("Content-Type","application/json"); |
|||
httpPost.setEntity(new StringEntity(json, StandardCharsets.UTF_8)); |
|||
return getHttpResult(httpPost); |
|||
} |
|||
|
|||
/** |
|||
* 请求返回统一封装 |
|||
* @param request |
|||
* @return |
|||
*/ |
|||
private static HttpResult getHttpResult(HttpRequestBase request) { |
|||
CloseableHttpClient httpClient = getHttpClient(); |
|||
String errMsg = null; |
|||
Integer code = 500; |
|||
try { |
|||
CloseableHttpResponse response = httpClient.execute(request); |
|||
code = response.getStatusLine().getStatusCode(); |
|||
HttpEntity entity = response.getEntity(); |
|||
if (entity != null) { |
|||
String data = EntityUtils.toString(entity, UTF8); |
|||
response.close(); |
|||
HttpResult result = new HttpResult(code,null,data); |
|||
return result; |
|||
} |
|||
} catch (ClientProtocolException e) { |
|||
log.error(e.getMessage()); |
|||
errMsg = e.getMessage(); |
|||
} catch (IOException e) { |
|||
log.error(e.getMessage()); |
|||
errMsg = e.getMessage(); |
|||
} |
|||
return new HttpResult(code,errMsg); |
|||
} |
|||
|
|||
/** 中间工具 */ |
|||
private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) { |
|||
ArrayList<NameValuePair> pairs = new ArrayList<>(); |
|||
for (Map.Entry<String, Object> param : params.entrySet()) { |
|||
pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue()))); |
|||
} |
|||
return pairs; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,16 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/28 |
|||
*/ |
|||
public class IdUtil { |
|||
|
|||
public static final IdWorker ID_WORKER = new IdWorker(0,0); |
|||
|
|||
public static Long getLong(){ |
|||
return ID_WORKER.nextId()-1541318968076140673L; |
|||
} |
|||
} |
@ -0,0 +1,155 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import java.lang.management.ManagementFactory; |
|||
import java.net.InetAddress; |
|||
import java.net.NetworkInterface; |
|||
|
|||
/** |
|||
* <p>名称:IdWorker.java</p> |
|||
* <p>描述:分布式自增长ID</p> |
|||
* <pre> |
|||
* Twitter的 Snowflake JAVA实现方案 |
|||
* </pre> |
|||
* 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用: |
|||
* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000 |
|||
* 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间, |
|||
* 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识), |
|||
* 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。 |
|||
* 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分), |
|||
* 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。 |
|||
* <p> |
|||
* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) |
|||
* @author USER |
|||
*/ |
|||
public class IdWorker { |
|||
|
|||
// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
|
|||
private final static long twepoch = 1288834974657L; |
|||
// 机器标识位数
|
|||
private final static long workerIdBits = 5L; |
|||
// 数据中心标识位数
|
|||
private final static long datacenterIdBits = 5L; |
|||
// 机器ID最大值
|
|||
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits); |
|||
// 数据中心ID最大值
|
|||
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); |
|||
// 毫秒内自增位
|
|||
private final static long sequenceBits = 12L; |
|||
// 机器ID偏左移12位
|
|||
private final static long workerIdShift = sequenceBits; |
|||
// 数据中心ID左移17位
|
|||
private final static long datacenterIdShift = sequenceBits + workerIdBits; |
|||
// 时间毫秒左移22位
|
|||
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; |
|||
|
|||
private final static long sequenceMask = -1L ^ (-1L << sequenceBits); |
|||
/* 上次生产id时间戳 */ |
|||
private static long lastTimestamp = -1L; |
|||
// 0,并发控制
|
|||
private long sequence = 0L; |
|||
|
|||
private final long workerId; |
|||
// 数据标识id部分
|
|||
private final long datacenterId; |
|||
|
|||
public IdWorker(){ |
|||
this.datacenterId = getDatacenterId(maxDatacenterId); |
|||
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); |
|||
} |
|||
/** |
|||
* @param workerId 工作机器ID |
|||
* @param datacenterId 序列号 |
|||
*/ |
|||
public IdWorker(long workerId, long datacenterId) { |
|||
if (workerId > maxWorkerId || workerId < 0) { |
|||
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); |
|||
} |
|||
if (datacenterId > maxDatacenterId || datacenterId < 0) { |
|||
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); |
|||
} |
|||
this.workerId = workerId; |
|||
this.datacenterId = datacenterId; |
|||
} |
|||
/** |
|||
* 获取下一个ID |
|||
* @return |
|||
*/ |
|||
public synchronized long nextId() { |
|||
long timestamp = timeGen(); |
|||
if (timestamp < lastTimestamp) { |
|||
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); |
|||
} |
|||
|
|||
if (lastTimestamp == timestamp) { |
|||
// 当前毫秒内,则+1
|
|||
sequence = (sequence + 1) & sequenceMask; |
|||
if (sequence == 0) { |
|||
// 当前毫秒内计数满了,则等待下一秒
|
|||
timestamp = tilNextMillis(lastTimestamp); |
|||
} |
|||
} else { |
|||
sequence = 0L; |
|||
} |
|||
lastTimestamp = timestamp; |
|||
// ID偏移组合生成最终的ID,并返回ID
|
|||
long nextId = ((timestamp - twepoch) << timestampLeftShift) |
|||
| (datacenterId << datacenterIdShift) |
|||
| (workerId << workerIdShift) | sequence; |
|||
|
|||
return nextId; |
|||
} |
|||
|
|||
private long tilNextMillis(final long lastTimestamp) { |
|||
long timestamp = this.timeGen(); |
|||
while (timestamp <= lastTimestamp) { |
|||
timestamp = this.timeGen(); |
|||
} |
|||
return timestamp; |
|||
} |
|||
|
|||
private long timeGen() { |
|||
return System.currentTimeMillis(); |
|||
} |
|||
|
|||
/** |
|||
* 获取 maxWorkerId |
|||
*/ |
|||
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { |
|||
StringBuffer mpid = new StringBuffer(); |
|||
mpid.append(datacenterId); |
|||
String name = ManagementFactory.getRuntimeMXBean().getName(); |
|||
if (!name.isEmpty()) { |
|||
/* |
|||
* GET jvmPid |
|||
*/ |
|||
mpid.append(name.split("@")[0]); |
|||
} |
|||
/* |
|||
* MAC + PID 的 hashcode 获取16个低位 |
|||
*/ |
|||
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); |
|||
} |
|||
|
|||
/** |
|||
* 数据标识id部分 |
|||
*/ |
|||
protected static long getDatacenterId(long maxDatacenterId) { |
|||
long id = 0L; |
|||
try { |
|||
InetAddress ip = InetAddress.getLocalHost(); |
|||
NetworkInterface network = NetworkInterface.getByInetAddress(ip); |
|||
if (network == null) { |
|||
id = 1L; |
|||
} else { |
|||
byte[] mac = network.getHardwareAddress(); |
|||
id = ((0x000000FF & (long) mac[mac.length - 1]) |
|||
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; |
|||
id = id % (maxDatacenterId + 1); |
|||
} |
|||
} catch (Exception e) { |
|||
System.out.println(" getDatacenterId: " + e.getMessage()); |
|||
} |
|||
return id; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,83 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.fasterxml.jackson.annotation.JsonInclude; |
|||
import com.fasterxml.jackson.core.JsonProcessingException; |
|||
//import com.fasterxml.jackson.databind.DeserializationFeature;
|
|||
import com.fasterxml.jackson.databind.JavaType; |
|||
//import com.fasterxml.jackson.databind.MapperFeature;
|
|||
import com.fasterxml.jackson.databind.MapperFeature; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
|
|||
/** |
|||
* Jackson json序列化和反序列化工具类 |
|||
* @Author JcYen |
|||
* @Date 2019/6/3 |
|||
* @Version 1.0 |
|||
*/ |
|||
public class JsonUtil { |
|||
|
|||
/** |
|||
* jackson对象 |
|||
*/ |
|||
static final ObjectMapper MAPPER = new ObjectMapper(); |
|||
|
|||
static { |
|||
MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); |
|||
MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); |
|||
} |
|||
|
|||
/** |
|||
* 将对象转换成json字符串。 |
|||
*/ |
|||
public static String objectToJson(Object data) { |
|||
try { |
|||
String string = MAPPER.writeValueAsString(data); |
|||
return string; |
|||
} catch (JsonProcessingException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 将json结果集转化为对象 |
|||
* |
|||
* @param jsonData json数据 |
|||
* @param beanType 对象中的object类型 |
|||
*/ |
|||
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { |
|||
try { |
|||
T t = MAPPER.readValue(jsonData, beanType); |
|||
return t; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 将json数据转换成pojo对象list |
|||
*/ |
|||
public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) { |
|||
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); |
|||
try { |
|||
List<T> list = MAPPER.readValue(jsonData, javaType); |
|||
return list; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public static Map<String, Object> jsonToMap(String jsonStr){ |
|||
Map<String, Object> json = JSONObject.parseObject(jsonStr, Map.class); |
|||
return json; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,47 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import com.qs.cost.common.utils.model.DesUtils; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/25 |
|||
*/ |
|||
public class SecureUtil extends cn.hutool.crypto.SecureUtil { |
|||
|
|||
|
|||
|
|||
/** |
|||
* 加密 |
|||
* @param secretKey |
|||
* @param clientId |
|||
* @return |
|||
*/ |
|||
public static String desEncrypt(String secretKey,String clientId){ |
|||
String formatStr = clientId+"-"+System.currentTimeMillis(); |
|||
DesUtils des = new DesUtils(secretKey); |
|||
try { |
|||
return des.encrypt(formatStr); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 解密 |
|||
* @param secretKey |
|||
* @param encryptText |
|||
* @return clientId |
|||
*/ |
|||
public static String desDecrypt(String secretKey,String encryptText){ |
|||
DesUtils des = new DesUtils(secretKey); |
|||
try { |
|||
String formatStr = des.decrypt(encryptText); |
|||
return formatStr.split("-")[0]; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,123 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.http.MediaType; |
|||
import org.springframework.web.context.request.RequestContextHolder; |
|||
import org.springframework.web.context.request.ServletRequestAttributes; |
|||
|
|||
import javax.servlet.ServletException; |
|||
import javax.servlet.ServletRequest; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.BufferedReader; |
|||
import java.io.IOException; |
|||
import java.io.InputStream; |
|||
import java.io.InputStreamReader; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.Enumeration; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/2/25 |
|||
*/ |
|||
@Slf4j |
|||
public class ServletUtil { |
|||
|
|||
/** |
|||
* 获取用户真实IP |
|||
* |
|||
* @return |
|||
*/ |
|||
public static String getIpAddress(HttpServletRequest request) { |
|||
// 优先取X-Real-IP
|
|||
String ip = request.getHeader("X-Real-IP"); |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { |
|||
ip = request.getHeader("x-forwarded-for"); |
|||
} |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { |
|||
ip = request.getRemoteAddr(); |
|||
if ("0:0:0:0:0:0:0:1".equals(ip)) { |
|||
ip = "undefined"; |
|||
} |
|||
} |
|||
if ("unknown".equalsIgnoreCase(ip)) { |
|||
ip = "undefined"; |
|||
return ip; |
|||
} |
|||
int pos = ip.indexOf(','); |
|||
if (pos >= 0) { |
|||
ip = ip.substring(0, pos); |
|||
} |
|||
return ip; |
|||
} |
|||
|
|||
/** |
|||
* 判断本次请求的数据类型是否为json |
|||
* @param request request |
|||
* @return true: 是 JSON 数据; false: 非 json 数据 |
|||
*/ |
|||
public static boolean isJsonRequest(HttpServletRequest request) { |
|||
if (request.getContentType() != null) { |
|||
return request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) || |
|||
request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 获取query参数 |
|||
* @param request |
|||
* @return |
|||
*/ |
|||
public static Map<String, String> getParameterMapAll(HttpServletRequest request) { |
|||
Enumeration<String> parameters = request.getParameterNames(); |
|||
Map<String, String> params = new HashMap<>(); |
|||
while (parameters.hasMoreElements()) { |
|||
String parameter = parameters.nextElement(); |
|||
String value = request.getParameter(parameter); |
|||
params.put(parameter, value); |
|||
} |
|||
return params; |
|||
} |
|||
|
|||
/** |
|||
* 获取请求Body |
|||
* |
|||
* @param request |
|||
* @return |
|||
*/ |
|||
public static String getBodyString(ServletRequest request) { |
|||
StringBuilder sb = new StringBuilder(); |
|||
InputStream inputStream = null; |
|||
BufferedReader reader = null; |
|||
try { |
|||
inputStream = request.getInputStream(); |
|||
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); |
|||
String line = ""; |
|||
while ((line = reader.readLine()) != null) { |
|||
sb.append(line); |
|||
} |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
if (inputStream != null) { |
|||
try { |
|||
inputStream.close(); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
if (reader != null) { |
|||
try { |
|||
reader.close(); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,132 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import java.text.NumberFormat; |
|||
import java.util.Random; |
|||
|
|||
/** |
|||
* @Description 创建字符串工具类 |
|||
* @Author JcYen |
|||
* @Date 2019/4/9 |
|||
* @Version v1.0 |
|||
**/ |
|||
public class StringCreateUtil { |
|||
|
|||
private static final String CHARSET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; |
|||
|
|||
private static final String CHARSET2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; |
|||
|
|||
/** |
|||
* 根据长度随机生成字符串(根据时间,有出现重复现象) |
|||
*/ |
|||
public static String randomTimeStr(int length) { |
|||
String randomStr = ""; |
|||
int randomInt; |
|||
Random random = new Random(System.currentTimeMillis()); |
|||
for (int i = 0; i < length; i++) { |
|||
randomInt = random.nextInt(CHARSET.length()); |
|||
randomStr += CHARSET.charAt(randomInt); |
|||
} |
|||
return randomStr; |
|||
} |
|||
|
|||
/** |
|||
* ID对应字符串匹配 |
|||
* @param id |
|||
* @return |
|||
*/ |
|||
public static String caveIdString(Long id){ |
|||
String idString = id.toString(); |
|||
String rs = ""; |
|||
for(int i=0;i<idString.length();i++){ |
|||
Integer c2idx = Integer.parseInt(idString.charAt(i)+""); |
|||
rs += CHARSET2.charAt(c2idx); |
|||
} |
|||
return reverseStr(rs); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 字符串倒序输出 |
|||
* @param str |
|||
* @return |
|||
*/ |
|||
private static String reverseStr(String str) { |
|||
StringBuffer buffer = new StringBuffer(str); |
|||
return buffer.reverse().toString().toLowerCase(); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 根据长度随机生成字符串 |
|||
*/ |
|||
public static String randomStr(int length){ |
|||
Random random=new Random(); |
|||
StringBuffer sb=new StringBuffer(); |
|||
for(int i=0;i<length;i++){ |
|||
int number=random.nextInt(3); |
|||
long result=0; |
|||
switch(number){ |
|||
case 0: |
|||
result= Math.round(Math.random()*25+65); |
|||
sb.append(String.valueOf((char)result)); |
|||
break; |
|||
case 1: |
|||
result= Math.round(Math.random()*25+97); |
|||
sb.append(String.valueOf((char)result)); |
|||
break; |
|||
case 2: |
|||
sb.append(String.valueOf(new Random().nextInt(10))); |
|||
break; |
|||
} |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 生成随机数字字符串 |
|||
*/ |
|||
public static String randomNumStr(int length) { |
|||
Random random = new Random(); |
|||
String result = ""; |
|||
for (int i = 0; i < length; i++) { |
|||
result += random.nextInt(10); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 返回随机数 |
|||
* @param length |
|||
* @return |
|||
*/ |
|||
public static int randomNum(int length){ |
|||
String str = randomNumStr(length); |
|||
return Integer.parseInt(str); |
|||
} |
|||
|
|||
public static String ellipticalTitle(String title, Integer len){ |
|||
if(title!=null&&title.length()>len){ |
|||
return title.substring(len)+"..."; |
|||
}return title; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* description: 格式化数字,实现左侧补 0. |
|||
* @param num 格式化的数字 |
|||
* @param min 最小位数 |
|||
* @param max 最大位数 |
|||
*/ |
|||
public static String fill(int num , int min , int max) { |
|||
NumberFormat numberFormat = NumberFormat.getInstance(); |
|||
// 禁用数字格式化分组。 如: 000,001
|
|||
numberFormat.setGroupingUsed(false); |
|||
// 保留最小位数
|
|||
numberFormat.setMinimumIntegerDigits(min); |
|||
// 保留最大位数
|
|||
numberFormat.setMaximumIntegerDigits(max); |
|||
return numberFormat.format(num); |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,20 @@ |
|||
package com.qs.cost.common.utils; |
|||
|
|||
import org.springframework.util.StringUtils; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @version 1.0 |
|||
* @date 2021/6/16 |
|||
**/ |
|||
public class StringUtil { |
|||
|
|||
public static boolean isEmpty(Object obj){ |
|||
return StringUtils.isEmpty(obj); |
|||
} |
|||
|
|||
public static boolean isNotEmpty(String str){ |
|||
return str!=null && str.trim().length()>0; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,126 @@ |
|||
package com.qs.cost.common.utils.model; |
|||
|
|||
import java.security.Key; |
|||
|
|||
import javax.crypto.Cipher; |
|||
|
|||
/** |
|||
* 使用DES算法对字符串进行加密解密 (加密解密的操作步骤正好相反, 参考 {@link #encrypt(String)}, {@link #decrypt(String)}) |
|||
*/ |
|||
public class DesUtils { |
|||
private static String defaultSecretKey = "default_secret_key"; //默认密钥
|
|||
private Cipher encryptCipher = null; //加密器
|
|||
private Cipher decryptCipher = null; //解密器
|
|||
|
|||
public DesUtils() throws Exception { |
|||
this(defaultSecretKey); |
|||
} |
|||
|
|||
/** |
|||
* @param secretKey 加密解密使用的密钥 |
|||
*/ |
|||
public DesUtils(String secretKey) { |
|||
Key key; |
|||
try { |
|||
key = getKey(secretKey.getBytes()); |
|||
encryptCipher = Cipher.getInstance("DES"); |
|||
encryptCipher.init(Cipher.ENCRYPT_MODE, key); |
|||
decryptCipher = Cipher.getInstance("DES"); |
|||
decryptCipher.init(Cipher.DECRYPT_MODE, key); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 加密 (逻辑: 1. 将要加密的字符串转换为字节数组(byte array)<br/> |
|||
* 2. 将第一步的字节数组作为输入使用加密器(Cipher)的doFinal方法进行加密, 返回字节数组<br/> |
|||
* 3. 把加密后的字节数组转换成十六进制的字符串)<br/> |
|||
* @param strIn 要加密的字符串 |
|||
* @return 返回加密后的十六进制字符串 |
|||
* @throws Exception |
|||
*/ |
|||
public String encrypt(String strIn) throws Exception { |
|||
return byteArr2HexStr(encrypt(strIn.getBytes())); |
|||
} |
|||
|
|||
public byte[] encrypt(byte[] arrB) throws Exception { |
|||
return encryptCipher.doFinal(arrB); |
|||
} |
|||
|
|||
/** |
|||
* 解密 (逻辑: 1. 把加密后的十六进制字符串转换成字节数组(byte array)<br/> |
|||
* 2. 将第一步的字节数组作为输入使用加密器(Cipher)的doFinal方法进行解密, 返回字节数组(byte array)<br/> |
|||
* 3. 把解密后的字节数组转换成字符串)<br/> |
|||
* @param strIn |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
public String decrypt(String strIn) throws Exception { |
|||
return new String(decrypt(hexStr2ByteArr(strIn))); |
|||
} |
|||
|
|||
public byte[] decrypt(byte[] arrB) throws Exception { |
|||
return decryptCipher.doFinal(arrB); |
|||
} |
|||
|
|||
public static String byteArr2HexStr(byte[] arrB) throws Exception { |
|||
int iLen = arrB.length; |
|||
// 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
|
|||
StringBuffer sb = new StringBuffer(iLen * 2); |
|||
for (int i = 0; i < iLen; i++) { |
|||
int intTmp = arrB[i]; |
|||
// 把负数转换为正数
|
|||
while (intTmp < 0) { |
|||
intTmp = intTmp + 256; |
|||
} |
|||
// 小于0F的数需要在前面补0
|
|||
if (intTmp < 16) { |
|||
sb.append("0"); |
|||
} |
|||
sb.append(Integer.toString(intTmp, 16)); |
|||
} |
|||
return sb.toString(); |
|||
} |
|||
|
|||
public static byte[] hexStr2ByteArr(String strIn) throws Exception { |
|||
byte[] arrB = strIn.getBytes(); |
|||
int iLen = arrB.length; |
|||
// 两个字符表示一个字节,所以字节数组长度是字符串长度除以2
|
|||
byte[] arrOut = new byte[iLen / 2]; |
|||
for (int i = 0; i < iLen; i = i + 2) { |
|||
String strTmp = new String(arrB, i, 2); |
|||
arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16); |
|||
} |
|||
return arrOut; |
|||
} |
|||
|
|||
private Key getKey(byte[] arrBTmp) throws Exception { |
|||
// 创建一个空的8位字节数组(默认值为0)
|
|||
byte[] arrB = new byte[8]; |
|||
// 将原始字节数组转换为8位
|
|||
for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) { |
|||
arrB[i] = arrBTmp[i]; |
|||
} |
|||
// 生成密钥
|
|||
Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES"); |
|||
return key; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 用法实例 |
|||
*/ |
|||
public static void main(String[] args) { |
|||
try { |
|||
String test = "liwc"; |
|||
DesUtils des = new DesUtils("leemenz"); //自定义密钥
|
|||
System.out.println("加密前的字符:" + test); |
|||
System.out.println("加密后的字符:" + des.encrypt(test)); |
|||
System.out.println("解密后的字符:" + des.decrypt(des.encrypt(test))); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.qs.cost.module.controller; |
|||
|
|||
import com.qs.cost.common.dto.R; |
|||
import com.qs.cost.common.dto.u8.U8CallbackVo; |
|||
import com.qs.cost.common.utils.JsonUtil; |
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/7/7 |
|||
*/ |
|||
@AllArgsConstructor |
|||
@RestController |
|||
@RequestMapping("/u8") |
|||
public class LzOrderController { |
|||
|
|||
@PostMapping("/callback") |
|||
public R callback(@RequestBody U8CallbackVo requestVo){ |
|||
System.out.println(JsonUtil.objectToJson(requestVo)); |
|||
return R.ok(); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,64 @@ |
|||
package com.qs.cost.module.domain; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableField; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import lombok.Data; |
|||
|
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/9/27 |
|||
*/ |
|||
@Data |
|||
public class VmSupplierPo { |
|||
|
|||
@TableId(value = "serialNumber") |
|||
private String serialNumber; |
|||
|
|||
@TableField(value = "empNo") |
|||
private String empNo; |
|||
|
|||
@TableField(value = "name") |
|||
private String name; |
|||
|
|||
@TableField(value = "applyDate") |
|||
private Date applyDate; |
|||
|
|||
@TableField(value = "applyType") |
|||
private String applyType; |
|||
|
|||
@TableField(value = "cVenCode") |
|||
private String cVenCode; |
|||
|
|||
@TableField(value = "cVenName") |
|||
private String cVenName; |
|||
|
|||
@TableField(value = "cVenAbbName") |
|||
private String cVenAbbName; |
|||
|
|||
@TableField(value = "cVCCode") |
|||
private String cVCCode; |
|||
|
|||
@TableField(value = "cVCName") |
|||
private String cVCName; |
|||
|
|||
@TableField(value = "cDCCode") |
|||
private String cDCCode; |
|||
|
|||
@TableField(value = "cDCName") |
|||
private String cDCName; |
|||
|
|||
@TableField(value = "cCusAddress") |
|||
private String cCusAddress; |
|||
|
|||
@TableField(value = "cCusEmail") |
|||
private String cCusEmail; |
|||
|
|||
@TableField(value = "cCusPerson") |
|||
private String cCusPerson; |
|||
|
|||
@TableField(value = "cCusPhone") |
|||
private String cCusPhone; |
|||
|
|||
} |
@ -0,0 +1,39 @@ |
|||
package com.qs.cost.module.domain.dto; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* |
|||
* Vendor t = new Vendor(); |
|||
* t.Editprop = "A";//编辑属性:A表新增,M表修改 string类型
|
|||
* t.cVenCode = "01020302";//供应商编码 (必填)
|
|||
* t.cVenName = "测试名称";//供应商名称 (必填)
|
|||
* t.cVenAbbName = "测试";//供应商简称
|
|||
* t.cVCCode = "01";//供应商分类编码(必填)
|
|||
* t.cDCCode = "";//地区编码
|
|||
* |
|||
* @author YenHex |
|||
* @since 2022/9/27 |
|||
*/ |
|||
@Data |
|||
public class U8Vendor { |
|||
|
|||
@JsonProperty("Editprop") |
|||
private String editprop; |
|||
|
|||
@JsonProperty("cVenCode") |
|||
private String cVenCode; |
|||
|
|||
@JsonProperty("cVenName") |
|||
private String cVenName; |
|||
|
|||
@JsonProperty("cVenAbbName") |
|||
private String cVenAbbName; |
|||
|
|||
@JsonProperty("cVCCode") |
|||
private String cVcCode; |
|||
|
|||
@JsonProperty("cDCCode") |
|||
private String cDCCode; |
|||
} |
@ -0,0 +1,13 @@ |
|||
package com.qs.cost.module.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.qs.cost.module.domain.VmSupplierPo; |
|||
import org.apache.ibatis.annotations.Mapper; |
|||
|
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/9/27 |
|||
*/ |
|||
public interface VmSupplierMapper extends BaseMapper<VmSupplierPo> { |
|||
|
|||
} |
@ -0,0 +1,59 @@ |
|||
package com.qs.cost.module.service; |
|||
|
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.qs.cost.common.conf.MainServerProperties; |
|||
import com.qs.cost.common.dto.u8.U8RequestBo; |
|||
import com.qs.cost.common.utils.HttpUtil; |
|||
import com.qs.cost.common.utils.JsonUtil; |
|||
import com.qs.cost.module.domain.VmSupplierPo; |
|||
import com.qs.cost.module.domain.dto.U8Vendor; |
|||
import com.qs.cost.module.mapper.VmSupplierMapper; |
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.time.LocalDateTime; |
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
/** |
|||
* @author YenHex |
|||
* @since 2022/9/27 |
|||
*/ |
|||
@Service |
|||
@AllArgsConstructor |
|||
public class VmSupplierService { |
|||
|
|||
private final VmSupplierMapper vmSupplierMapper; |
|||
private final MainServerProperties mainServerProperties; |
|||
|
|||
public void test() { |
|||
String host = mainServerProperties.getHost(); |
|||
String year = mainServerProperties.getYear(); |
|||
String book = mainServerProperties.getBook(); |
|||
List<VmSupplierPo> supplierPoList = vmSupplierMapper.selectList(new QueryWrapper<>()); |
|||
for (VmSupplierPo supplierPo : supplierPoList) { |
|||
U8Vendor vendor = new U8Vendor(); |
|||
//编辑属性:A表新增,M表修改 string类型
|
|||
vendor.setEditprop("A"); |
|||
vendor.setCVenCode(supplierPo.getCVenCode()); |
|||
vendor.setCVenName(supplierPo.getCVenName()); |
|||
vendor.setCVenAbbName(supplierPo.getCVenAbbName()); |
|||
vendor.setCDCCode(supplierPo.getCDCCode()); |
|||
vendor.setCVcCode(supplierPo.getCVCCode()); |
|||
String jsonBody = JsonUtil.objectToJson(vendor); |
|||
//发起U8服务中台
|
|||
U8RequestBo requestBo = new U8RequestBo(); |
|||
requestBo.setPk(vendor.getCVenCode()); |
|||
requestBo.setCmd("BasicVendor"); |
|||
requestBo.setYear(year); |
|||
requestBo.setBook(book); |
|||
requestBo.setJsonBody(jsonBody); |
|||
requestBo.setKeyId(""); |
|||
requestBo.setSettingRetryTimes(2); |
|||
requestBo.setCallbackState("1"); |
|||
requestBo.setCallbackHost( host + "/lzOrder/callback"); |
|||
HttpUtil.post(mainServerProperties.getU8url(),JsonUtil.objectToJson(requestBo)); |
|||
|
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,34 @@ |
|||
#服务配置 |
|||
server: |
|||
port: 7101 |
|||
#本服务访问根地址,用于回调 |
|||
host: 'http://127.0.0.1:7101' |
|||
#帐套 |
|||
book: 999 |
|||
#年份 |
|||
year: 2020 |
|||
#U8平台 |
|||
u8url: http://127.0.0.1:7100/api/jobRequest |
|||
#SpringBoot相关 |
|||
spring: |
|||
#数据源 |
|||
datasource: |
|||
#url: jdbc:mysql://127.0.0.1:3333/jsl_cost_api?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai |
|||
url: jdbc:sqlserver://192.168.10.7:1433;DatabaseName=JSLGROUPDB |
|||
username: sa |
|||
password: '#JSL2282125' |
|||
#driverClassName: com.mysql.cj.jdbc.Driver |
|||
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver |
|||
#mybatis plus |
|||
mybatis-plus: |
|||
type-aliases-package: com.qs.cost.module.domain |
|||
configuration: |
|||
map-underscore-to-camel-case: true |
|||
global-config: |
|||
banner: false |
|||
db-config: |
|||
logic-delete-value: 1 # 逻辑已删除值(默认为 1) |
|||
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) |
|||
# 日志配置 |
|||
logging: |
|||
config: classpath:logback-spring.xml |
@ -0,0 +1,3 @@ |
|||
spring: |
|||
profiles: |
|||
active: dev |
@ -0,0 +1,51 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<configuration> |
|||
<!-- 文件输出格式 --> |
|||
<property name="PATTERN" |
|||
value="%boldMagenta(%-12(%d{yyyy-MM-dd HH:mm:ss.SSS})) |- %highlight(%-5level) %cyan([%thread]) %green(%c [%L]) -| %msg%n"/> |
|||
<property name="LOG_NAME" value="qs"/> |
|||
<!--所在项目包 打印日志用--> |
|||
<property name="PACKAGE_NAME" value="com.qs"/> |
|||
<!-- test文件路径 --> |
|||
<property name="TEST_FILE_PATH" value="logs/${LOG_NAME}"/> |
|||
<!-- pro文件路径 --> |
|||
<property name="PROD_FILE_PATH" value="logs/${LOG_NAME}"/> |
|||
|
|||
<!-- 开发环境 --> |
|||
<springProfile name="dev"> |
|||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> |
|||
<encoder> |
|||
<pattern>${PATTERN}</pattern> |
|||
</encoder> |
|||
</appender> |
|||
<!-- 输出到文件 --> |
|||
<logger name="org.springframework.jdbc.core.JdbcTemplate" level="INFO"/> |
|||
<logger name="${PACKAGE_NAME}" level="debug"/> |
|||
<root level="info"> |
|||
<appender-ref ref="CONSOLE"/> |
|||
</root> |
|||
</springProfile> |
|||
|
|||
<!-- 生产环境 --> |
|||
<springProfile name="prod"> |
|||
<appender name="PROD_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<file>${PROD_FILE_PATH}${file.separator}${LOG_NAME}.log</file> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> |
|||
<!-- rollover daily --> |
|||
<fileNamePattern>${PROD_FILE_PATH}${file.separator}${LOG_NAME}-%d{yyyy-MM-dd}.%i.log</fileNamePattern> |
|||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB --> |
|||
<maxHistory>7</maxHistory> |
|||
<maxFileSize>100MB</maxFileSize> |
|||
<totalSizeCap>1GB</totalSizeCap> |
|||
</rollingPolicy> |
|||
<encoder> |
|||
<pattern> |
|||
[%date{yyyy-MM-dd HH:mm:ss.SSS}] %X{logthreadId} %-5level %logger{80} %method %line - %msg%n |
|||
</pattern> |
|||
</encoder> |
|||
</appender> |
|||
<root level="info"> |
|||
<appender-ref ref="PROD_FILE"/> |
|||
</root> |
|||
</springProfile> |
|||
</configuration> |
Loading…
Reference in new issue