mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-17 10:36:31 +08:00
created
This commit is contained in:
25
orange-admin-service/common/common-biz/pom.xml
Normal file
25
orange-admin-service/common/common-biz/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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>
|
||||
|
||||
<parent>
|
||||
<groupId>com.orange.admin</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>common-biz</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<name>common-biz</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.orange.admin</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.orange.admin.common.biz.advice;
|
||||
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Controller的环绕拦截类。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class MyControllerAdvice {
|
||||
|
||||
/**
|
||||
* 转换前端传入的日期变量参数为指定格式。
|
||||
*
|
||||
* @param binder 数据绑定参数。
|
||||
*/
|
||||
@InitBinder
|
||||
public void initBinder(WebDataBinder binder) {
|
||||
binder.registerCustomEditor(Date.class,
|
||||
new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.orange.admin.common.biz.advice;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.orange.admin.common.core.constant.ErrorCodeEnum;
|
||||
import com.orange.admin.common.core.exception.RedisCacheAccessException;
|
||||
import com.orange.admin.common.core.object.ResponseResult;
|
||||
import org.apache.ibatis.exceptions.PersistenceException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.PermissionDeniedDataAccessException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* 业务层的异常处理类,这里只是给出最通用的Exception的捕捉,今后可以根据业务需要,
|
||||
* 用不同的函数,处理不同类型的异常。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class MyExceptionHandler {
|
||||
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
public ResponseResult<?> exceptionHandle(Exception ex, HttpServletRequest request) {
|
||||
log.error("Unhandled exception from URL [" + request.getRequestURI() + "]", ex);
|
||||
return ResponseResult.error(ErrorCodeEnum.UNHANDLED_EXCEPTION);
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = DuplicateKeyException.class)
|
||||
public ResponseResult<?> duplicateKeyExceptionHandle(Exception ex, HttpServletRequest request) {
|
||||
log.error("DuplicateKeyException exception from URL [" + request.getRequestURI() + "]", ex);
|
||||
return ResponseResult.error(ErrorCodeEnum.DUPLICATED_UNIQUE_KEY);
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = DataAccessException.class)
|
||||
public ResponseResult<?> dataAccessExceptionHandle(Exception ex, HttpServletRequest request) {
|
||||
log.error("DataAccessException exception from URL [" + request.getRequestURI() + "]", ex);
|
||||
if (ex.getCause() instanceof PersistenceException
|
||||
&& ex.getCause().getCause() instanceof PermissionDeniedDataAccessException) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_PERM_ACCESS_FAILED);
|
||||
}
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_ACCESS_FAILED);
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = RedisCacheAccessException.class)
|
||||
public ResponseResult<?> redisCacheAccessExceptionHandle(Exception ex, HttpServletRequest request) {
|
||||
log.error("RedisCacheAccessException exception from URL [" + request.getRequestURI() + "]", ex);
|
||||
if (ex.getCause() instanceof TimeoutException) {
|
||||
return ResponseResult.error(ErrorCodeEnum.REDIS_CACHE_ACCESS_TIMEOUT);
|
||||
}
|
||||
return ResponseResult.error(ErrorCodeEnum.REDIS_CACHE_ACCESS_STATE_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.orange.admin.common.biz.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 应用程序自定义的通用属性配置文件。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "application.common-biz")
|
||||
public class CommonBizConfig {
|
||||
|
||||
/**
|
||||
* Snowflake计算主键Id时所需的WorkNode参数值。
|
||||
*/
|
||||
private Integer snowflakeWorkNode;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.orange.admin.common.biz.config;
|
||||
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* DTA 对象数据格式转换器,这里集成了alibaba的fastjson,作为消息格式转换工具
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Configuration
|
||||
public class FastjsonConfig {
|
||||
|
||||
@Bean
|
||||
public HttpMessageConverters fastJsonHttpMessageConverters() {
|
||||
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
|
||||
FastJsonConfig fastJsonConfig = new FastJsonConfig();
|
||||
fastJsonConfig.setSerializerFeatures(
|
||||
SerializerFeature.PrettyFormat, SerializerFeature.DisableCircularReferenceDetect);
|
||||
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
fastConverter.setFastJsonConfig(fastJsonConfig);
|
||||
return new HttpMessageConverters(fastConverter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.orange.admin.common.biz.config;
|
||||
|
||||
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
|
||||
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* tomcat配置对象。当前配置禁用了PUT和DELETE方法,防止渗透攻击。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Configuration
|
||||
public class TomcatConfig {
|
||||
|
||||
@Bean
|
||||
public TomcatServletWebServerFactory servletContainer() {
|
||||
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
|
||||
factory.addContextCustomizers(context -> {
|
||||
SecurityConstraint securityConstraint = new SecurityConstraint();
|
||||
securityConstraint.setUserConstraint("CONFIDENTIAL");
|
||||
SecurityCollection collection = new SecurityCollection();
|
||||
collection.addPattern("/*");
|
||||
collection.addMethod("HEAD");
|
||||
collection.addMethod("PUT");
|
||||
collection.addMethod("PATCH");
|
||||
collection.addMethod("DELETE");
|
||||
collection.addMethod("TRACE");
|
||||
collection.addMethod("COPY");
|
||||
collection.addMethod("SEARCH");
|
||||
collection.addMethod("PROPFIND");
|
||||
securityConstraint.addCollection(collection);
|
||||
context.addConstraint(securityConstraint);
|
||||
});
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.orange.admin.common.biz.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Subject {
|
||||
|
||||
/**
|
||||
* 语文。
|
||||
*/
|
||||
public static final int CHINESE = 0;
|
||||
/**
|
||||
* 数学。
|
||||
*/
|
||||
public static final int MATH = 1;
|
||||
/**
|
||||
* 英语。
|
||||
*/
|
||||
public static final int ENGLISH = 2;
|
||||
|
||||
public static final Map<Object, String> DICT_MAP = new HashMap<>(3);
|
||||
static {
|
||||
DICT_MAP.put(CHINESE, "语文");
|
||||
DICT_MAP.put(MATH, "数学");
|
||||
DICT_MAP.put(ENGLISH, "英语");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(int value) {
|
||||
return DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private Subject() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.orange.admin.common.biz.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class YesNo {
|
||||
|
||||
/**
|
||||
* 是。
|
||||
*/
|
||||
public static final int YES = 1;
|
||||
/**
|
||||
* 否。
|
||||
*/
|
||||
public static final int NO = 0;
|
||||
|
||||
public static final Map<Object, String> DICT_MAP = new HashMap<>(2);
|
||||
static {
|
||||
DICT_MAP.put(YES, "是");
|
||||
DICT_MAP.put(NO, "否");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(int value) {
|
||||
return DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private YesNo() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.orange.admin.common.biz.interceptor;
|
||||
|
||||
import com.orange.admin.common.core.object.GlobalThreadLocal;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 服务访问日志的拦截器,主要完成记录接口调用时长。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Slf4j
|
||||
public class AccessInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final ThreadLocal<Long> STARTTIME_THREADLOCAL = new ThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
STARTTIME_THREADLOCAL.set(System.currentTimeMillis());
|
||||
// 每次进入Controller接口之前,均主动打开数据权限验证。
|
||||
// 可以避免该Servlet线程在处理之前的请求时异常退出,从而导致该状态数据没有被正常清除。
|
||||
GlobalThreadLocal.setDataPerm(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
ModelAndView modelAndView) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
|
||||
throws Exception {
|
||||
long startTime = STARTTIME_THREADLOCAL.get();
|
||||
long elapse = System.currentTimeMillis() - startTime;
|
||||
String urlPath = request.getRequestURI();
|
||||
String controllerMethod = "Unknown";
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod hm = (HandlerMethod) handler;
|
||||
String controllerName = hm.getBean().getClass().getName();
|
||||
// 这里将cglib织入的部分去掉,提升日志的可读性
|
||||
int index = controllerName.indexOf("$$");
|
||||
if (index > 0) {
|
||||
controllerName = controllerName.substring(0, index);
|
||||
}
|
||||
controllerMethod = controllerName + "." + hm.getMethod().getName();
|
||||
}
|
||||
log.info("access: {} -- elapse {} ms -- {}.", controllerMethod, elapse, urlPath);
|
||||
STARTTIME_THREADLOCAL.remove();
|
||||
GlobalThreadLocal.clearDataPerm();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
package com.orange.admin.common.biz.interceptor;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.orange.admin.common.core.annotation.MyRequestBody;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* MyRequestBody解析器
|
||||
* 解决的问题:
|
||||
* 1、单个字符串等包装类型都要写一个对象才可以用@RequestBody接收;
|
||||
* 2、多个对象需要封装到一个对象里才可以用@RequestBody接收。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
public class MyRequestArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private static final String JSONBODY_ATTRIBUTE = "MY_REQUEST_BODY_ATTRIBUTE_XX";
|
||||
|
||||
private static Set<Class<?>> classSet = new HashSet<>();
|
||||
|
||||
static {
|
||||
classSet.add(Integer.class);
|
||||
classSet.add(Long.class);
|
||||
classSet.add(Short.class);
|
||||
classSet.add(Float.class);
|
||||
classSet.add(Double.class);
|
||||
classSet.add(Boolean.class);
|
||||
classSet.add(Byte.class);
|
||||
classSet.add(Character.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置支持的方法参数类型
|
||||
*
|
||||
* @param parameter 方法参数
|
||||
* @return 支持的类型
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(@NonNull MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(MyRequestBody.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数解析,利用fastjson
|
||||
* 注意:非基本类型返回null会报空指针异常,要通过反射或者JSON工具类创建一个空对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object resolveArgument(
|
||||
@NonNull MethodParameter parameter,
|
||||
ModelAndViewContainer mavContainer,
|
||||
@NonNull NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory) throws Exception {
|
||||
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
String contentType = servletRequest.getContentType();
|
||||
if (!HttpMethod.POST.name().equals(servletRequest.getMethod())) {
|
||||
throw new IllegalArgumentException("Only POST method can be applied @MyRequestBody annotation!");
|
||||
}
|
||||
if (!StringUtils.containsIgnoreCase(contentType, "application/json")) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only application/json Content-Type can be applied @MyRequestBody annotation!");
|
||||
}
|
||||
// 根据@MyRequestBody注解value作为json解析的key
|
||||
MyRequestBody parameterAnnotation = parameter.getParameterAnnotation(MyRequestBody.class);
|
||||
JSONObject jsonObject = getRequestBody(webRequest);
|
||||
if (jsonObject == null) {
|
||||
if (parameterAnnotation.required()) {
|
||||
throw new IllegalArgumentException("Request Body is EMPTY!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
String key = parameterAnnotation.value();
|
||||
if (StringUtils.isBlank(key)) {
|
||||
key = parameter.getParameterName();
|
||||
}
|
||||
Object value = jsonObject.get(key);
|
||||
if (value == null) {
|
||||
if (parameterAnnotation.required()) {
|
||||
throw new IllegalArgumentException(String.format("Required parameter %s is not present!", key));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// 获取参数类型。
|
||||
Class<?> parameterType = parameter.getParameterType();
|
||||
//基本类型
|
||||
if (parameterType.isPrimitive()) {
|
||||
return parsePrimitive(parameterType.getName(), value);
|
||||
}
|
||||
// 基本类型包装类
|
||||
if (isBasicDataTypes(parameterType)) {
|
||||
return parseBasicTypeWrapper(parameterType, value);
|
||||
// 字符串类型
|
||||
} else if (parameterType == String.class) {
|
||||
return value.toString();
|
||||
}
|
||||
if (value instanceof JSONArray) {
|
||||
Object o;
|
||||
if (!parameterType.equals(List.class)) {
|
||||
o = parameterType.newInstance();
|
||||
parameterType = (Class<?>) ((ParameterizedType)
|
||||
parameterType.getGenericSuperclass()).getActualTypeArguments()[0];
|
||||
} else {
|
||||
parameterType = parameterAnnotation.elementType();
|
||||
if (parameterType.equals(Class.class)) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("List Type parameter %s MUST have elementType!", key));
|
||||
}
|
||||
o = new LinkedList<>();
|
||||
}
|
||||
if (!(o instanceof List)) {
|
||||
throw new IllegalArgumentException(String.format("Required parameter %s is List!", key));
|
||||
}
|
||||
((List<Object>) o).addAll(((JSONArray) value).toJavaList(parameterType));
|
||||
return o;
|
||||
}
|
||||
// 其他复杂对象
|
||||
return JSONObject.toJavaObject((JSONObject) value, parameterType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本类型解析
|
||||
*/
|
||||
private Object parsePrimitive(String parameterTypeName, Object value) {
|
||||
final String booleanTypeName = "boolean";
|
||||
if (booleanTypeName.equals(parameterTypeName)) {
|
||||
return Boolean.valueOf(value.toString());
|
||||
}
|
||||
final String intTypeName = "int";
|
||||
if (intTypeName.equals(parameterTypeName)) {
|
||||
return Integer.valueOf(value.toString());
|
||||
}
|
||||
final String charTypeName = "char";
|
||||
if (charTypeName.equals(parameterTypeName)) {
|
||||
return value.toString().charAt(0);
|
||||
}
|
||||
final String shortTypeName = "short";
|
||||
if (shortTypeName.equals(parameterTypeName)) {
|
||||
return Short.valueOf(value.toString());
|
||||
}
|
||||
final String longTypeName = "long";
|
||||
if (longTypeName.equals(parameterTypeName)) {
|
||||
return Long.valueOf(value.toString());
|
||||
}
|
||||
final String floatTypeName = "float";
|
||||
if (floatTypeName.equals(parameterTypeName)) {
|
||||
return Float.valueOf(value.toString());
|
||||
}
|
||||
final String doubleTypeName = "double";
|
||||
if (doubleTypeName.equals(parameterTypeName)) {
|
||||
return Double.valueOf(value.toString());
|
||||
}
|
||||
final String byteTypeName = "byte";
|
||||
if (byteTypeName.equals(parameterTypeName)) {
|
||||
return Byte.valueOf(value.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本类型包装类解析
|
||||
*/
|
||||
private Object parseBasicTypeWrapper(Class<?> parameterType, Object value) {
|
||||
if (Number.class.isAssignableFrom(parameterType)) {
|
||||
if (value instanceof String) {
|
||||
return Convert.convert(parameterType, value);
|
||||
}
|
||||
Number number = (Number) value;
|
||||
if (parameterType == Integer.class) {
|
||||
return number.intValue();
|
||||
} else if (parameterType == Short.class) {
|
||||
return number.shortValue();
|
||||
} else if (parameterType == Long.class) {
|
||||
return number.longValue();
|
||||
} else if (parameterType == Float.class) {
|
||||
return number.floatValue();
|
||||
} else if (parameterType == Double.class) {
|
||||
return number.doubleValue();
|
||||
} else if (parameterType == Byte.class) {
|
||||
return number.byteValue();
|
||||
}
|
||||
} else if (parameterType == Boolean.class) {
|
||||
return value.toString();
|
||||
} else if (parameterType == Character.class) {
|
||||
return value.toString().charAt(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为基本数据类型包装类
|
||||
*/
|
||||
private boolean isBasicDataTypes(Class<?> clazz) {
|
||||
return classSet.contains(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求体JSON字符串
|
||||
*/
|
||||
private JSONObject getRequestBody(NativeWebRequest webRequest) {
|
||||
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
// 有就直接获取
|
||||
JSONObject jsonObject = (JSONObject) webRequest.getAttribute(JSONBODY_ATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
|
||||
// 没有就从请求中读取
|
||||
if (jsonObject == null) {
|
||||
try {
|
||||
String jsonBody = IOUtils.toString(servletRequest.getReader());
|
||||
jsonObject = JSON.parseObject(jsonBody);
|
||||
if (jsonObject != null) {
|
||||
webRequest.setAttribute(JSONBODY_ATTRIBUTE, jsonObject, NativeWebRequest.SCOPE_REQUEST);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.orange.admin.common.biz.listener;
|
||||
|
||||
import com.orange.admin.common.core.base.service.BaseDictService;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 应用程序启动后的事件监听对象。主要负责加载Model之间的字典关联和一对一关联所对应的Service结构关系。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Component
|
||||
public class LoadCachedDataListener implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
|
||||
Map<String, BaseDictService> serviceMap =
|
||||
applicationReadyEvent.getApplicationContext().getBeansOfType(BaseDictService.class);
|
||||
for (Map.Entry<String, BaseDictService> e : serviceMap.entrySet()) {
|
||||
e.getValue().loadCachedData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.orange.admin.common.biz.listener;
|
||||
|
||||
import com.orange.admin.common.core.base.service.BaseService;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 应用程序启动后的事件监听对象。主要负责加载Model之间的字典关联和一对一关联所对应的Service结构关系。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Component
|
||||
public class LoadServiceRelationListener implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
|
||||
Map<String, BaseService> serviceMap =
|
||||
applicationReadyEvent.getApplicationContext().getBeansOfType(BaseService.class);
|
||||
for (Map.Entry<String, BaseService> e : serviceMap.entrySet()) {
|
||||
e.getValue().loadRelationStruct();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.orange.admin.common.biz.util;
|
||||
|
||||
import cn.hutool.core.lang.Snowflake;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.orange.admin.common.biz.config.CommonBizConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* 全局共享的snowflake计算工具类。
|
||||
* 基于Hutool中的对应工具类实现,同时读取系统的配置参数并初始化该对象。如果今后
|
||||
* 升级为基于分布式Id生成服务的实现时,仅需修改内部实现,外部业务方法不会受到任何影响。
|
||||
*
|
||||
* @author Stephen.Liu
|
||||
* @date 2020-04-11
|
||||
*/
|
||||
@Component
|
||||
public class BasicIdGenerator {
|
||||
|
||||
@Autowired
|
||||
private CommonBizConfig config;
|
||||
|
||||
private Snowflake snowflake;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
snowflake = IdUtil.createSnowflake(config.getSnowflakeWorkNode(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取基于Snowflake算法的数值型Id。
|
||||
* 由于底层实现为synchronized方法,因此计算过程串行化,且线程安全。
|
||||
*
|
||||
* @return 计算后的全局唯一Id。
|
||||
*/
|
||||
public long nextLongId() {
|
||||
return this.snowflake.nextId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取基于Snowflake算法的字符串Id。
|
||||
* 由于底层实现为synchronized方法,因此计算过程串行化,且线程安全。
|
||||
*
|
||||
* @return 计算后的全局唯一Id。
|
||||
*/
|
||||
public String nextStringId() {
|
||||
return this.snowflake.nextIdStr();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user