Commit 54c10eb0 by 黄杰

整理springcloud脚手架

parent 25ee571e
...@@ -4,9 +4,45 @@ ...@@ -4,9 +4,45 @@
此项目采用java8作为底层环境开发 使用springcloud框架和它的各种脚手架功能。 此项目采用java8作为底层环境开发 使用springcloud框架和它的各种脚手架功能。
### 模块简介 ### 模块简介
```
ihooyah-hza-server ihooyah-hza-server
|
├──ihooyah-hza-common --通用包
|
├──ihooyah-hza-nacos --nacos注册中心
|
├──ihooyah-hza-sentinel --流量监控服务降级熔断
|
├──ihooyah-hza-auth --鉴权中心
|
├──ihooyah-hza-gateway --网关
|
├──ihooyah-hza-job --定时任务模块
| |
| ├──ihooyah-hza-job --定时任务模块
| |
├──ihooyah-hza-modules --微服务
| |
| ├──ihooyah-hza-system --系统业务
| |
| ├──ihooyah-hza-lg --旅馆业管控
| |
| ├──ihooyah-hza-generator --代码生成
| |
| ├──ihooyah-hza-cache -- 缓存
|
├──ihooyah-hza-springadmin --springboot 监控中心
|
```
### 启动顺序
1. ihooyah-hza-nacos
2. ihooyah-hza-auth
3. ihooyah-hza-gateway
4. ihooyah-hza-modules 下的任意模块
### 架构详情 ### 架构详情
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-server</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-auth</artifactId>
<dependencies>
<dependency>
<groupId>com.ihooyah</groupId>
<artifactId>ihooyah-hza-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.4.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.ihooyah.auth.config;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.http.HttpServletRequest;
public class UserAuthConfig {
@Value("${auth.user.token-header}")
private String tokenHeader;
private byte[] pubKeyByte;
public String getTokenHeader() {
return tokenHeader;
}
public void setTokenHeader(String tokenHeader) {
this.tokenHeader = tokenHeader;
}
public String getToken(HttpServletRequest request){
return request.getHeader(this.getTokenHeader());
}
public byte[] getPubKeyByte() {
return pubKeyByte;
}
public void setPubKeyByte(byte[] pubKeyByte) {
this.pubKeyByte = pubKeyByte;
}
}
package com.ihooyah.auth.configuration;
import com.ihooyah.auth.config.UserAuthConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"com.ihooyah.auth"})
public class AutoConfiguration {
@Bean
UserAuthConfig getUserAuthConfig(){
return new UserAuthConfig();
}
}
package com.ihooyah.auth.exception;
public class JwtTokenExpiredException extends Exception {
public JwtTokenExpiredException(String s) {
super(s);
}
}
package com.ihooyah.auth.interceptor;
import com.ihooyah.auth.annotation.IgnoreUserToken;
import com.ihooyah.auth.config.UserAuthConfig;
import com.ihooyah.auth.jwt.UserAuthUtil;
import com.ihooyah.common.context.BaseContextHandler;
import com.ihooyah.common.util.jwt.IJWTInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UserAuthRestInterceptor extends HandlerInterceptorAdapter {
@Autowired
private UserAuthUtil userAuthUtil;
@Autowired
private UserAuthConfig userAuthConfig;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 配置该注解,说明不进行用户拦截
IgnoreUserToken annotation = handlerMethod.getBeanType().getAnnotation(IgnoreUserToken.class);
if (annotation == null) {
annotation = handlerMethod.getMethodAnnotation(IgnoreUserToken.class);
}
if (annotation != null) {
return super.preHandle(request, response, handler);
}
String token = request.getHeader(userAuthConfig.getTokenHeader());
if (StringUtils.isEmpty(token)) {
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals(userAuthConfig.getTokenHeader())) {
token = cookie.getValue();
}
}
}
}
IJWTInfo infoFromToken = userAuthUtil.getInfoFromToken(token);
BaseContextHandler.setUsername(infoFromToken.getName());
BaseContextHandler.setUserAccount(infoFromToken.getUniqueName());
BaseContextHandler.setUserID(infoFromToken.getId());
BaseContextHandler.setToken(token);
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
BaseContextHandler.remove();
super.afterCompletion(request, response, handler, ex);
}
}
package com.ihooyah.auth.jwt;
import com.ihooyah.auth.config.UserAuthConfig;
import com.ihooyah.common.exception.UserTokenException;
import com.ihooyah.common.util.jwt.IJWTInfo;
import com.ihooyah.common.util.jwt.JWTHelper;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserAuthUtil {
@Autowired
private UserAuthConfig userAuthConfig;
public IJWTInfo getInfoFromToken(String token) throws Exception {
try {
return JWTHelper.getInfoFromToken(token, userAuthConfig.getPubKeyByte());
}catch (ExpiredJwtException ex){
throw new UserTokenException("User token expired!");
}catch (SignatureException ex){
throw new UserTokenException("User token signature error!");
}catch (IllegalArgumentException ex){
throw new UserTokenException("User token is null or empty!");
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-server</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-common</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.ihooyah.common.constant;
public class CommonConstants {
// 用户token异常
public static final Integer EX_TOKEN_ERROR_CODE = 40101;
public static final String CONTEXT_KEY_USER_ID = "currentUserId";
public static final String CONTEXT_KEY_USERNAME = "currentUserName";
public static final String CONTEXT_KEY_USER_NAME = "currentUser";
public static final String CONTEXT_KEY_USER_TOKEN = "currentUserToken";
public static final String CONTEXT_KEY_USER_ACCOUNT = "currentUserAccount";
public static final String JWT_KEY_USER_ID = "userId";
public static final String JWT_KEY_NAME = "name";
public static final String JWT_KEY_ACCOUNT = "account";
}
package com.ihooyah.common.context;
import com.ihooyah.common.constant.CommonConstants;
import com.ihooyah.common.util.jwt.JWTHelper;
import java.util.HashMap;
import java.util.Map;
public class BaseContextHandler {
public static ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<Map<String, Object>>();
public static void set(String key, Object value) {
Map<String, Object> map = threadLocal.get();
if (map == null) {
map = new HashMap<String, Object>();
threadLocal.set(map);
}
map.put(key, value);
}
public static Object get(String key){
Map<String, Object> map = threadLocal.get();
if (map == null) {
map = new HashMap<String, Object>();
threadLocal.set(map);
}
return map.get(key);
}
public static String getUserID(){
Object value = get(CommonConstants.CONTEXT_KEY_USER_ID);
return returnObjectValue(value);
}
public static String getUsername(){
Object value = get(CommonConstants.CONTEXT_KEY_USERNAME);
return returnObjectValue(value);
}
public static String getUserAccount(){
Object value = get(CommonConstants.CONTEXT_KEY_USER_ACCOUNT);
return JWTHelper.getObjectValue(value);
}
public static String getToken(){
Object value = get(CommonConstants.CONTEXT_KEY_USER_TOKEN);
return JWTHelper.getObjectValue(value);
}
public static void setToken(String token){set(CommonConstants.CONTEXT_KEY_USER_TOKEN,token);}
public static void setUserAccount(String name){set(CommonConstants.CONTEXT_KEY_USER_ACCOUNT,name);}
public static void setUserID(String userID){
set(CommonConstants.CONTEXT_KEY_USER_ID,userID);
}
public static void setUsername(String username){
set(CommonConstants.CONTEXT_KEY_USERNAME,username);
}
private static String returnObjectValue(Object value) {
return value==null?null:value.toString();
}
public static void remove(){
threadLocal.remove();
}
}
package com.ihooyah.common.exception;
public class BaseException extends RuntimeException {
private int status = 200;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public BaseException() {
}
public BaseException(String message,int status) {
super(message);
this.status = status;
}
public BaseException(String message) {
super(message);
}
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(Throwable cause) {
super(cause);
}
public BaseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
package com.ihooyah.common.exception;
import com.ihooyah.common.constant.CommonConstants;
public class UserTokenException extends BaseException {
public UserTokenException(String message) {
super(message, CommonConstants.EX_TOKEN_ERROR_CODE);
}
}
package com.ihooyah.common.handler;
import com.ihooyah.common.exception.BaseException;
import com.ihooyah.common.exception.UserTokenException;
import com.ihooyah.common.msg.RespEnum;
import com.ihooyah.common.msg.RespInfo;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
@ControllerAdvice("com.ihooyah")
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(BindException.class)
public RespInfo validateErrorHandler(HttpServletResponse response, BindException e) {
BindingResult bindingResult = e.getBindingResult();
if (bindingResult.hasErrors() && bindingResult.getFieldError() != null) {
return new RespInfo(RespEnum.ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage());
}else{
return new RespInfo(RespEnum.ERROR.getCode(),"Form validation error");
}
}
@ExceptionHandler(UserTokenException.class)
public RespInfo userTokenExceptionHandler(HttpServletResponse response, UserTokenException ex) {
return new RespInfo(ex.getStatus(),ex.getMessage());
}
@ExceptionHandler(BaseException.class)
public RespInfo baseExceptionHandler(HttpServletResponse response, BaseException ex) {
return new RespInfo(RespEnum.ERROR.getCode(), ex.getMessage());
}
@ExceptionHandler(Exception.class)
public RespInfo otherExceptionHandler(HttpServletResponse response, Exception ex) {
return new RespInfo(RespEnum.ERROR.getCode(), ex.getMessage());
}
}
package com.ihooyah.common.msg;
/**
* @author 王尧 【wangyao@ihooyah.com】
* @description
* @create 2018-03-30 下午8:05
**/
public enum RespEnum {
//基础请求
SUCCESS(200, "请求成功"),
ERROR(500, "请求失败"),
INVALID_PARAMS(400, ""),
//授权相关 11000
AUTH_NO_ACCESS(11001, "没有权限访问该资源"),
AUTH_ACCESSTOKEN_EXPIRED(11002, "ACCESS_TOKEN已失效"),
AUTH_ACCESSTOKEN_INEXISTENCE(11003, "ACCESS_TOKEN不存在"),
//用户相关 12000
USER_NOLOGIN(12001, "用户未登录"),
USER_INVALID_PWD(12002, "用户密码错误"),
USER_INVALID_LOGINNAME(12003, "用户不存在"),
//公安网证相关 13000
AUTHENTICATION_ERROR(13002, "查询失败,请重试");
private int code;
private String msg;
private RespEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
/**
* 通过code获取对应的内容
*
* @param
* @return
* @author 王尧 【wangyao@ihooyah.com】
* @date 2018/3/30 下午8:15
**/
public static String getMsgByCode(int code) {
for (RespEnum responseEnum : RespEnum.values()) {
if (responseEnum.getCode() == code) {
return responseEnum.msg;
}
}
return null;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.ihooyah.common.msg;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Http请求统一返回结构
*
* @param
* @author 王尧 【wangyao@ihooyah.com】
* @return
* @date 2018/3/30 下午7:59
**/
public class RespInfo {
private Integer code = -1;
private String msg = "";
private Object result = "";
private Object endpoint = "";
public RespInfo(Integer code, String msg, Object result) {
this.code = code;
this.msg = msg;
this.result = result;
}
public RespInfo(Integer code, String msg) {
this.code = code;
this.msg = msg;
this.result = result;
}
public RespInfo() {
}
public static RespInfo out(RespEnum respEnum) {
return new RespInfo(respEnum.getCode(), respEnum.getMsg());
}
public static RespInfo out(RespEnum respEnum, Object object) {
RespInfo respInfo = new RespInfo(respEnum.getCode(), respEnum.getMsg(), object);
respInfo.setEndpoint("web");
return respInfo;
}
public static RespInfo mobiSuccess(RespEnum respEnum, Object object) {
RespInfo respInfo = new RespInfo(respEnum.getCode(), respEnum.getMsg(), object);
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiSuccess() {
RespInfo respInfo = new RespInfo(RespEnum.SUCCESS.getCode(), "", "");
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiSuccess(Object obj) {
RespInfo respInfo = new RespInfo(RespEnum.SUCCESS.getCode(), "", obj);
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiSuccess(String msg, Object obj) {
RespInfo respInfo = new RespInfo(RespEnum.SUCCESS.getCode(), msg, obj);
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiSuccess(String msg) {
RespInfo respInfo = new RespInfo(RespEnum.SUCCESS.getCode(), msg);
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiError() {
RespInfo respInfo = new RespInfo(RespEnum.ERROR.getCode(), RespEnum.ERROR.getMsg());
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiError(String msg) {
RespInfo respInfo = new RespInfo(RespEnum.ERROR.getCode(), msg);
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiError(String msg, Object object) {
RespInfo respInfo = new RespInfo(RespEnum.ERROR.getCode(), msg, object);
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiError(RespEnum respEnum, String errorMsg) {
RespInfo respInfo = null;
respInfo = new RespInfo(respEnum.getCode(), errorMsg, "");
respInfo.setEndpoint("mobi");
return respInfo;
}
public static RespInfo mobiError(RespEnum respEnum) {
RespInfo respInfo = new RespInfo(respEnum.getCode(), respEnum.getMsg(), "");
respInfo.setEndpoint("mobi");
return respInfo;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public Object getEndpoint() {
return endpoint;
}
public void setEndpoint(Object endpoint) {
this.endpoint = endpoint;
}
public <T> T getResultObject(Class<T> clazz) {
if (RespEnum.SUCCESS.getCode() == this.getCode()) {
if (StringUtils.isBlank(this.getResult().toString())) {
return null;
}
JSONObject jsonObject = (JSONObject) getResult();
return jsonObject.toJavaObject(clazz);
}
return null;
}
public <T> List<T> getResultList(Class<T> clazz) {
if (RespEnum.SUCCESS.getCode() == this.getCode()) {
if (StringUtils.isBlank(this.getResult().toString())) {
return new ArrayList<>();
}
JSONArray jsonArray = (JSONArray) getResult();
return jsonArray.toJavaList(clazz);
}
return new ArrayList<>();
}
}
package com.ihooyah.common.util.jwt;
public interface IJWTInfo {
/**
* 获取用户名
* @return
*/
String getUniqueName();
/**
* 获取用户ID
* @return
*/
String getId();
/**
* 获取名称
* @return
*/
String getName();
}
package com.ihooyah.common.util.jwt;
import com.ihooyah.common.constant.CommonConstants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;
public class JWTHelper {
private static RsaKeyHelper rsaKeyHelper = new RsaKeyHelper();
/**
* 密钥加密token
*
* @param jwtInfo
* @param priKeyPath
* @param expire
* @return
* @throws Exception
*/
public static String generateToken(IJWTInfo jwtInfo, String priKeyPath, int expire) throws Exception {
String compactJws = Jwts.builder()
.setSubject(jwtInfo.getUniqueName())
.claim(CommonConstants.JWT_KEY_USER_ID, jwtInfo.getId())
.claim(CommonConstants.JWT_KEY_NAME, jwtInfo.getName())
.setExpiration(DateTime.now().plusSeconds(expire).toDate())
.signWith(SignatureAlgorithm.RS256, rsaKeyHelper.getPrivateKey(priKeyPath))
.compact();
return compactJws;
}
/**
* 密钥加密token
*
* @param jwtInfo
* @param priKey
* @param expire
* @return
* @throws Exception
*/
public static String generateToken(IJWTInfo jwtInfo, byte priKey[], int expire) throws Exception {
String compactJws = Jwts.builder()
.setSubject(jwtInfo.getUniqueName())
.claim(CommonConstants.JWT_KEY_USER_ID, jwtInfo.getId())
.claim(CommonConstants.JWT_KEY_NAME, jwtInfo.getName())
.setExpiration(DateTime.now().plusSeconds(expire).toDate())
.signWith(SignatureAlgorithm.RS256, rsaKeyHelper.getPrivateKey(priKey))
.compact();
return compactJws;
}
/**
* 公钥解析token
*
* @param token
* @return
* @throws Exception
*/
public static Jws<Claims> parserToken(String token, String pubKeyPath) throws Exception {
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(rsaKeyHelper.getPublicKey(pubKeyPath)).parseClaimsJws(token);
return claimsJws;
}
/**
* 公钥解析token
*
* @param token
* @return
* @throws Exception
*/
public static Jws<Claims> parserToken(String token, byte[] pubKey) throws Exception {
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(rsaKeyHelper.getPublicKey(pubKey)).parseClaimsJws(token);
return claimsJws;
}
/**
* 获取token中的用户信息
*
* @param token
* @param pubKeyPath
* @return
* @throws Exception
*/
public static IJWTInfo getInfoFromToken(String token, String pubKeyPath) throws Exception {
Jws<Claims> claimsJws = parserToken(token, pubKeyPath);
Claims body = claimsJws.getBody();
return new JWTInfo(body.getSubject(), getObjectValue(body.get(CommonConstants.JWT_KEY_USER_ID)),
getObjectValue(body.get(CommonConstants.JWT_KEY_NAME)));
}
/**
* 获取token中的用户信息
*
* @param token
* @param pubKey
* @return
* @throws Exception
*/
public static IJWTInfo getInfoFromToken(String token, byte[] pubKey) throws Exception {
Jws<Claims> claimsJws = parserToken(token, pubKey);
Claims body = claimsJws.getBody();
return new JWTInfo(body.getSubject(), getObjectValue(body.get(CommonConstants.JWT_KEY_USER_ID)),
getObjectValue(body.get(CommonConstants.JWT_KEY_NAME)));
}
public static String getObjectValue(Object obj){
return obj==null?"":obj.toString();
}
}
package com.ihooyah.common.util.jwt;
import java.io.Serializable;
public class JWTInfo implements Serializable,IJWTInfo {
private String account;
private String userId;
private String name;
public JWTInfo(String account, String userId, String name) {
this.account = account;
this.userId = userId;
this.name = name;
}
@Override
public String getUniqueName() {
return account;
}
public void setUniqueName(String account) {
this.account = account;
}
@Override
public String getId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
JWTInfo jwtInfo = (JWTInfo) o;
if (account != null ? !account.equals(jwtInfo.account) : jwtInfo.account != null) {
return false;
}
return userId != null ? userId.equals(jwtInfo.userId) : jwtInfo.userId == null;
}
@Override
public int hashCode() {
int result = account != null ? account.hashCode() : 0;
result = 31 * result + (userId != null ? userId.hashCode() : 0);
return result;
}
}
package com.ihooyah.common.util.jwt;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RsaKeyHelper {
/**
* 获取公钥
*
* @param filename
* @return
* @throws Exception
*/
public PublicKey getPublicKey(String filename) throws Exception {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename);
DataInputStream dis = new DataInputStream(resourceAsStream);
byte[] keyBytes = new byte[resourceAsStream.available()];
dis.readFully(keyBytes);
dis.close();
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
/**
* 获取密钥
*
* @param filename
* @return
* @throws Exception
*/
public PrivateKey getPrivateKey(String filename) throws Exception {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename);
DataInputStream dis = new DataInputStream(resourceAsStream);
byte[] keyBytes = new byte[resourceAsStream.available()];
dis.readFully(keyBytes);
dis.close();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
/**
* 获取公钥
*
* @param publicKey
* @return
* @throws Exception
*/
public PublicKey getPublicKey(byte[] publicKey) throws Exception {
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
/**
* 获取密钥
*
* @param privateKey
* @return
* @throws Exception
*/
public PrivateKey getPrivateKey(byte[] privateKey) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
/**
* 生存rsa公钥和密钥
*
* @param publicKeyFilename
* @param privateKeyFilename
* @param password
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public void generateKey(String publicKeyFilename, String privateKeyFilename, String password) throws IOException, NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(password.getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
FileOutputStream fos = new FileOutputStream(publicKeyFilename);
fos.write(publicKeyBytes);
fos.close();
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
fos = new FileOutputStream(privateKeyFilename);
fos.write(privateKeyBytes);
fos.close();
}
/**
* 生存rsa公钥
*
* @param password
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static byte[] generatePublicKey(String password) throws IOException, NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(password.getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
return keyPair.getPublic().getEncoded();
}
/**
* 生存rsa公钥
*
* @param password
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static byte[] generatePrivateKey(String password) throws IOException, NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(password.getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
return keyPair.getPrivate().getEncoded();
}
public static Map<String, byte[]> generateKey(String password) throws IOException, NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(password.getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
Map<String, byte[]> map = new HashMap<String, byte[]>();
map.put("pub", publicKeyBytes);
map.put("pri", privateKeyBytes);
return map;
}
public static String toHexString(byte[] b) {
return (new BASE64Encoder()).encodeBuffer(b);
}
public static final byte[] toBytes(String s) throws IOException {
return (new BASE64Decoder()).decodeBuffer(s);
}
public static void main(String[] args) throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom("123".getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
System.out.println(keyPair.getPublic().getEncoded());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-server</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-gateway</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8
</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<kotlin.version>1.3.0</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>com.ihooyah</groupId>
<artifactId>ihooyah-hza-auth</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.ihooyah</groupId>
<artifactId>ihooyah-hza-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.amqp</groupId>-->
<!--<artifactId>spring-rabbit</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>org.isomorphism</groupId>
<artifactId>token-bucket</artifactId>
<version>1.7</version>
</dependency>
<!-- swagger-ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${boot.admin.client}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<build>
<finalName>ihooyah-hza-gateway</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.ihooyah.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
package com.ihooyah.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.filter.reactive.HiddenHttpMethodFilter;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Configuration
public class RouteConfiguration {
//这里为支持的请求头,如果有自定义的header字段请自己添加(不知道为什么不能使用*)
private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential,username,client";
private static final String ALLOWED_METHODS = "*";
private static final String ALLOWED_ORIGIN = "*";
private static final String ALLOWED_Expose = "*";
private static final String MAX_AGE = "18000L";
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (CorsUtils.isCorsRequest(request)) {
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Expose-Headers", ALLOWED_Expose);
headers.add("Access-Control-Allow-Credentials", "true");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new HiddenHttpMethodFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange);
}
};
}
}
package com.ihooyah.gateway.filter;
import com.alibaba.fastjson.JSONObject;
import com.ihooyah.auth.config.UserAuthConfig;
import com.ihooyah.auth.jwt.UserAuthUtil;
import com.ihooyah.common.context.BaseContextHandler;
import com.ihooyah.common.msg.RespEnum;
import com.ihooyah.common.msg.RespInfo;
import com.ihooyah.common.util.jwt.IJWTInfo;
import com.ihooyah.gateway.handler.SwaggerProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Configuration
@Slf4j
public class AccessGatewayFilter implements GlobalFilter {
/**
* 不进行拦截的地址
*/
@Value("${gate.ignore.startWith}")
private String startWith;
@Autowired
private UserAuthUtil userAuthUtil;
@Autowired
private UserAuthConfig userAuthConfig;
private static final String HEADER_NAME = "X-Forwarded-Prefix";
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, GatewayFilterChain gatewayFilterChain) {
log.info("check token and user permission....");
ServerHttpRequest request = serverWebExchange.getRequest();
String requestUri = request.getPath().pathWithinApplication().value();
BaseContextHandler.setToken(null);
ServerHttpRequest.Builder mutate = request.mutate();
// 不进行拦截的地址
if (isStartWith(requestUri)) {
ServerHttpRequest build = mutate.build();
return gatewayFilterChain.filter(serverWebExchange.mutate().request(build).build());
} else if(StringUtils.endsWithIgnoreCase(requestUri, SwaggerProvider.API_URI)){
/**
* 对swagger-ui放开
*/
ServerHttpRequest build = mutate.build();
return gatewayFilterChain.filter(serverWebExchange.mutate().request(build).build());
}
IJWTInfo user;
try {
user = getJWTUser(request, mutate);
} catch (Exception e) {
log.error("用户Token过期异常", e);
return getVoidMono(serverWebExchange, new RespInfo(RespEnum.AUTH_ACCESSTOKEN_EXPIRED.getCode(),"User Token Forbidden or Expired!"));
}
return gatewayFilterChain.filter(serverWebExchange.mutate().build());
}
/**
* 网关抛异常
*
* @param body
*/
@NotNull
private Mono<Void> getVoidMono(ServerWebExchange serverWebExchange, RespInfo body) {
serverWebExchange.getResponse().setStatusCode(HttpStatus.OK);
byte[] bytes = JSONObject.toJSONString(body).getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = serverWebExchange.getResponse().bufferFactory().wrap(bytes);
return serverWebExchange.getResponse().writeWith(Flux.just(buffer));
}
/**
* 返回session中的用户信息
*
* @param request
* @param ctx
* @return
*/
private IJWTInfo getJWTUser(ServerHttpRequest request, ServerHttpRequest.Builder ctx) throws Exception {
List<String> strings = request.getHeaders().get(userAuthConfig.getTokenHeader());
String authToken = null;
if (strings != null) {
authToken = strings.get(0);
}
if (StringUtils.isBlank(authToken)) {
strings = request.getQueryParams().get("token");
if (strings != null) {
authToken = strings.get(0);
}
}
ctx.header(userAuthConfig.getTokenHeader(), authToken);
BaseContextHandler.setToken(authToken);
return userAuthUtil.getInfoFromToken(authToken);
}
/**
* URI是否以什么打头
*
* @param requestUri
* @return
*/
private boolean isStartWith(String requestUri) {
boolean flag = false;
for (String s : startWith.split(",")) {
if (requestUri.startsWith(s)) {
return true;
}
}
return flag;
}
}
package com.ihooyah.gateway.handler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;
import java.util.Optional;
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}
\ No newline at end of file
package com.ihooyah.gateway.handler;
import lombok.AllArgsConstructor;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.List;
@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider {
public static final String API_URI = "/v2/api-docs";
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
//取出gateway的route
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
//结合配置的route-路径(Path),和route过滤,只获取有效的route节点
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("/**", API_URI)))));
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("1.0.0.SNAPSHOT");
return swaggerResource;
}
}
spring:
application:
name: ihooyah-hza-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
profiles:
active: dev
main:
allow-bean-definition-overriding: true
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-server</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-job</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-cache</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.32</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.ihooyah.cache;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@ComponentScan({"com.ihooyah.cache"})
@EnableAspectJAutoProxy
public class AutoConfiguration {
}
package com.ihooyah.cache;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(AutoConfiguration.class)
@Documented
@Inherited
public @interface EnableIhooyahCache {
}
package com.ihooyah.cache.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ihooyah.cache.constants.CacheScope;
import com.ihooyah.cache.parser.ICacheResultParser;
import com.ihooyah.cache.parser.IKeyGenerator;
import com.ihooyah.cache.parser.impl.DefaultKeyGenerator;
import com.ihooyah.cache.parser.impl.DefaultResultParser;
/**
* 开启缓存
* <p/>
* 解决问题:
*
* @author Ace
* @version 1.0
* @date 2017年5月4日
* @since 1.7
*/
@Retention(RetentionPolicy.RUNTIME)
// 在运行时可以获取
@Target(value = {ElementType.METHOD, ElementType.TYPE})
// 作用到类,方法,接口上等
public @interface Cache {
/**
* 缓存key menu_{0.id}{1}_type
*
* @return
* @author Ace
* @date 2017年5月3日
*/
public String key() default "";
/**
* 作用域
*
* @return
* @author Ace
* @date 2017年5月3日
*/
public CacheScope scope() default CacheScope.application;
/**
* 过期时间
*
* @return
* @author Ace
* @date 2017年5月3日
*/
public int expire() default 720;
/**
* 描述
*
* @return
* @author Ace
* @date 2017年5月3日
*/
public String desc() default "";
/**
* 返回类型
*
* @return
* @author Ace
* @date 2017年5月4日
*/
public Class[] result() default Object.class;
/**
* 返回结果解析类
*
* @return
*/
public Class<? extends ICacheResultParser> parser() default DefaultResultParser.class;
/**
* 键值解析类
*
* @return
*/
public Class<? extends IKeyGenerator> generator() default DefaultKeyGenerator.class;
}
package com.ihooyah.cache.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ihooyah.cache.parser.IKeyGenerator;
import com.ihooyah.cache.parser.impl.DefaultKeyGenerator;
/**
* 解决问题:
*
* @author Ace
* @version 1.0
* @date 2017年5月4日
* @since 1.7
*/
@Retention(RetentionPolicy.RUNTIME)//在运行时可以获取
@Target(value = {ElementType.METHOD, ElementType.TYPE})//作用到类,方法,接口上等
public @interface CacheClear {
/**
* 缓存key的前缀
*
* @return
* @author Ace
* @date 2017年5月3日
*/
public String pre() default "";
/**
* 缓存key
*
* @return
* @author Ace
* @date 2017年5月3日
*/
public String key() default "";
/**
* 缓存keys
*
* @return
* @author Ace
* @date 2017年5月3日
*/
public String[] keys() default "";
/**
* 键值解析类
*
* @return
*/
public Class<? extends IKeyGenerator> generator() default DefaultKeyGenerator.class;
}
package com.ihooyah.cache.api;
import com.ihooyah.cache.entity.CacheBean;
import java.util.List;
public interface CacheAPI {
/**
* 传入key获取缓存json,需要用fastjson转换为对象
*
* @param key
* @return
* @author Ace
* @date 2017年5月12日
*/
public String get(String key);
/**
* 保存缓存
*
* @param key
* @param value
* @param expireMin
* @author Ace
* @date 2017年5月12日
*/
public void set(String key, Object value, int expireMin);
/**
* 保存缓存
*
* @param key
* @param value
* @param expireMin
* @param desc
* @author Ace
* @date 2017年5月12日
*/
public void set(String key, Object value, int expireMin, String desc);
/**
* 移除单个缓存
*
* @param key
* @return
* @author Ace
* @date 2017年5月12日
*/
public Long remove(String key);
/**
* 移除多个缓存
*
* @param keys
* @return
* @author Ace
* @date 2017年5月12日
*/
public Long remove(String... keys);
/**
* 按前缀移除缓存
*
* @param pre
* @return
* @author Ace
* @date 2017年5月12日
*/
public Long removeByPre(String pre);
/**
* 通过前缀获取缓存信息
*
* @param pre
* @return
* @author Ace
* @date 2017年5月12日
*/
public List<CacheBean> getCacheBeanByPre(String pre);
/**
* 获取所有缓存对象信息
*
* @return
* @author Ace
* @date 2017年5月12日
*/
public List<CacheBean> listAll();
/**
* 是否启用缓存
*
* @return
* @author Ace
* @date 2017年5月12日
*/
public boolean isEnabled();
/**
* 加入系统标志缓存
*
* @param key
* @return
* @author Ace
* @date 2017年5月12日
*/
public String addSys(String key);
}
package com.ihooyah.cache.api.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.ihooyah.cache.api.CacheAPI;
import com.ihooyah.cache.config.RedisConfig;
import com.ihooyah.cache.constants.CacheConstants;
import com.ihooyah.cache.entity.CacheBean;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.ihooyah.cache.service.IRedisService;
/**
* redis缓存
* <p/>
* 解决问题:
*
* @author Ace
* @version 1.0
* @date 2017年5月4日
* @since 1.7
*/
@Service
public class CacheRedis implements CacheAPI {
@Autowired
private RedisConfig redisConfig;
@Autowired
private IRedisService redisCacheService;
@Override
public String get(String key) {
if (!isEnabled())
return null;
if(StringUtils.isBlank(key)){
return null;
}
CacheBean cache = getCacheBean(key);
if (cache != null) {
if (cache.getExpireTime().getTime() > new Date().getTime()) {
return redisCacheService.get(cache.getKey());
} else {
redisCacheService.del(addSys(key));
redisCacheService.del(cache.getKey());
}
}
return null;
}
@Override
public void set(String key, Object value, int expireMin) {
set(key, value, expireMin, "");
}
@Override
public Long remove(String key) {
if (!isEnabled())
return 0L;
if(StringUtils.isBlank(key))
return 0L;
try {
CacheBean cache = getCacheBean(key);
if (cache != null) {
redisCacheService.del(addSys(key));
redisCacheService.del(cache.getKey());
}
} catch (Exception e) {
return 0L;
}
return 1L;
}
@Override
public Long remove(String... keys) {
if (!isEnabled())
return null;
try {
for (int i = 0; i < keys.length; i++) {
remove(keys[i]);
}
} catch (Exception e) {
return 0L;
}
return 1l;
}
@Override
public Long removeByPre(String pre) {
if (!isEnabled())
return 0L;
if(StringUtils.isBlank(pre))
return 0L;
try {
Set<String> result = redisCacheService.getByPre(addSys(pre));
List<String> list = new ArrayList<String>();
for (String key : result) {
CacheBean cache = getCacheBean(key);
list.add(cache.getKey());
}
redisCacheService.del(list.toArray(new String[]{}));
redisCacheService.delPre(addSys(pre));
} catch (Exception e) {
return 0L;
}
return 1L;
}
private CacheBean getCacheBean(String key) {
key = this.addSys(key);
CacheBean cache = null;
try {
cache = JSON.parseObject(redisCacheService.get(key),
CacheBean.class);
} catch (Exception e) {
cache = new CacheBean();
cache.setKey(key);
cache.setExpireTime(redisCacheService.getExpireDate(key));
}
return cache;
}
/**
* 加入系统前缀
*
* @param key
* @return
* @author Ace
* @date 2017年5月4日
*/
@Override
public String addSys(String key) {
String result = key;
String sys = redisConfig.getSysName();
if (key.startsWith(sys))
result = key;
else
result = sys + ":" + key;
return result;
}
@Override
public void set(String key, Object value, int expireMin, String desc) {
if (StringUtils.isBlank(key) || value == null
|| StringUtils.isBlank(value.toString()))
return;
if (!isEnabled())
return;
String realValue = "";
if (value instanceof String) {
realValue = value.toString();
} else {
realValue = JSON.toJSONString(value, false);
}
String realKey = CacheConstants.PRE + addSys(key);
Date time = new DateTime(redisCacheService.getExpireDate(realKey)).plusMinutes(expireMin).toDate();
CacheBean cache = new CacheBean(realKey, desc, time);
String result = JSON.toJSONString(cache, false);
redisCacheService.set(addSys(key), result, expireMin * 60);
redisCacheService.set(realKey, realValue, expireMin * 60);
}
@Override
public List<CacheBean> listAll() {
Set<String> result = redisCacheService.getByPre(addSys(""));
List<CacheBean> caches = new ArrayList<CacheBean>();
if (result == null)
return caches;
Iterator<String> it = result.iterator();
String key = "";
CacheBean cache = null;
while (it.hasNext()) {
cache = null;
key = it.next();
try {
cache = JSON.parseObject(redisCacheService.get(key),
CacheBean.class);
} catch (Exception e) {
cache = new CacheBean();
cache.setKey(key);
cache.setExpireTime(redisCacheService.getExpireDate(key));
}
if (cache == null)
continue;
cache.setKey(key);
caches.add(cache);
}
return caches;
}
@Override
public List<CacheBean> getCacheBeanByPre(String pre) {
if(StringUtils.isBlank(pre)){
return new ArrayList<CacheBean>();
}
Set<String> result = redisCacheService.getByPre(pre);
Iterator<String> it = result.iterator();
List<CacheBean> caches = new ArrayList<CacheBean>();
String key = "";
CacheBean cache = null;
while (it.hasNext()) {
key = it.next();
try {
cache = JSON.parseObject(redisCacheService.get(key),
CacheBean.class);
} catch (Exception e) {
cache = new CacheBean();
cache.setKey(key);
cache.setExpireTime(redisCacheService.getExpireDate(key));
}
cache.setKey(key);
caches.add(cache);
}
return caches;
}
@Override
public boolean isEnabled() {
return Boolean.parseBoolean(redisConfig.getEnable());
}
}
package com.ihooyah.cache.aspect;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;
import com.ihooyah.cache.api.CacheAPI;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ihooyah.cache.annotation.Cache;
import com.ihooyah.cache.parser.ICacheResultParser;
import com.ihooyah.cache.parser.IKeyGenerator;
import com.ihooyah.cache.parser.impl.DefaultKeyGenerator;
/**
* 缓存开启注解拦截
*
* @author wanghaobin
* @description
* @date 2017年5月18日
* @since 1.7
*/
@Aspect
@Service
public class CacheAspect {
@Autowired
private IKeyGenerator keyParser;
@Autowired
private CacheAPI cacheAPI;
private Logger logger = LoggerFactory.getLogger(this.getClass());
private ConcurrentHashMap<String, ICacheResultParser> parserMap = new ConcurrentHashMap<String, ICacheResultParser>();
private ConcurrentHashMap<String, IKeyGenerator> generatorMap = new ConcurrentHashMap<String, IKeyGenerator>();
@Pointcut("@annotation(com.ihooyah.cache.annotation.Cache)")
public void aspect() {
}
@Around("aspect()&&@annotation(anno)")
public Object interceptor(ProceedingJoinPoint invocation, Cache anno)
throws Throwable {
MethodSignature signature = (MethodSignature) invocation.getSignature();
Method method = signature.getMethod();
Object result = null;
Class<?>[] parameterTypes = method.getParameterTypes();
Object[] arguments = invocation.getArgs();
String key = "";
String value = "";
try {
key = getKey(anno, parameterTypes, arguments);
value = cacheAPI.get(key);
Type returnType = method.getGenericReturnType();
result = getResult(anno, result, value, returnType);
} catch (Exception e) {
logger.error("获取缓存失败:" + key, e);
} finally {
if (result == null) {
result = invocation.proceed();
if (StringUtils.isNotBlank(key)) {
cacheAPI.set(key, result, anno.expire());
}
}
}
return result;
}
/**
* 解析表达式
*
* @param anno
* @param parameterTypes
* @param arguments
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
private String getKey(Cache anno, Class<?>[] parameterTypes,
Object[] arguments) throws InstantiationException,
IllegalAccessException {
String key;
String generatorClsName = anno.generator().getName();
IKeyGenerator keyGenerator = null;
if (anno.generator().equals(DefaultKeyGenerator.class)) {
keyGenerator = keyParser;
} else {
if (generatorMap.contains(generatorClsName)) {
keyGenerator = generatorMap.get(generatorClsName);
} else {
keyGenerator = anno.generator().newInstance();
generatorMap.put(generatorClsName, keyGenerator);
}
}
key = keyGenerator.getKey(anno.key(), anno.scope(), parameterTypes,
arguments);
return key;
}
/**
* 解析结果
*
* @param anno
* @param result
* @param value
* @param returnType
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
private Object getResult(Cache anno, Object result, String value,
Type returnType) throws InstantiationException,
IllegalAccessException {
String parserClsName = anno.parser().getName();
ICacheResultParser parser = null;
if (parserMap.containsKey(parserClsName)) {
parser = parserMap.get(parserClsName);
} else {
parser = anno.parser().newInstance();
parserMap.put(parserClsName, parser);
}
if (parser != null) {
if (anno.result()[0].equals(Object.class)) {
result = parser.parse(value, returnType,
null);
} else {
result = parser.parse(value, returnType,
anno.result());
}
}
return result;
}
}
package com.ihooyah.cache.aspect;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import com.ihooyah.cache.annotation.CacheClear;
import com.ihooyah.cache.api.CacheAPI;
import com.ihooyah.cache.constants.CacheScope;
import com.ihooyah.cache.parser.IKeyGenerator;
import com.ihooyah.cache.parser.impl.DefaultKeyGenerator;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 清除缓存注解拦截
*
* @author wanghaobin
* @description
* @date 2017年5月18日
* @since 1.7
*/
@Aspect
@Service
public class CacheClearAspect {
@Autowired
private IKeyGenerator keyParser;
@Autowired
private CacheAPI cacheAPI;
private Logger logger = LoggerFactory.getLogger(this.getClass());
private ConcurrentHashMap<String, IKeyGenerator> generatorMap = new ConcurrentHashMap<String, IKeyGenerator>();
@Pointcut("@annotation(com.ihooyah.cache.annotation.CacheClear)")
public void aspect() {
}
@Around("aspect()&&@annotation(anno)")
public Object interceptor(ProceedingJoinPoint invocation, CacheClear anno)
throws Throwable {
MethodSignature signature = (MethodSignature) invocation.getSignature();
Method method = signature.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes();
Object[] arguments = invocation.getArgs();
String key = "";
if (StringUtils.isNotBlank(anno.key())) {
key = getKey(anno, anno.key(), CacheScope.application,
parameterTypes, arguments);
cacheAPI.remove(key);
} else if (StringUtils.isNotBlank(anno.pre())) {
key = getKey(anno, anno.pre(), CacheScope.application,
parameterTypes, arguments);
cacheAPI.removeByPre(key);
} else if (anno.keys().length > 1) {
for (String tmp : anno.keys()) {
tmp = getKey(anno, tmp, CacheScope.application, parameterTypes,
arguments);
cacheAPI.removeByPre(tmp);
}
}
return invocation.proceed();
}
/**
* 解析表达式
*
* @param anno
* @param parameterTypes
* @param arguments
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
private String getKey(CacheClear anno, String key, CacheScope scope,
Class<?>[] parameterTypes, Object[] arguments)
throws InstantiationException, IllegalAccessException {
String finalKey;
String generatorClsName = anno.generator().getName();
IKeyGenerator keyGenerator = null;
if (anno.generator().equals(DefaultKeyGenerator.class)) {
keyGenerator = keyParser;
} else {
if (generatorMap.containsKey(generatorClsName)) {
keyGenerator = generatorMap.get(generatorClsName);
} else {
keyGenerator = anno.generator().newInstance();
generatorMap.put(generatorClsName, keyGenerator);
}
}
finalKey = keyGenerator.getKey(key, scope, parameterTypes, arguments);
return finalKey;
}
}
package com.ihooyah.cache.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration("cacheWebConfig")
public class CacheWebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/META-INF/static/**","/static/**","/static/cache/**").addResourceLocations(
"classpath:/META-INF/static/");
}
}
package com.ihooyah.cache.config;
import com.ihooyah.cache.utils.PropertiesLoaderUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import javax.annotation.PostConstruct;
@Configuration
public class RedisConfig {
@Autowired
private Environment env;
private JedisPool pool;
private String maxActive;
private String maxIdle;
private String maxWait;
private String host;
private String password;
private String timeout;
private String database;
private String port;
private String enable;
private String sysName;
@PostConstruct
public void init(){
PropertiesLoaderUtils prop = new PropertiesLoaderUtils("application.properties");
host = prop.getProperty("redis.host");
if(StringUtils.isBlank(host)){
host = env.getProperty("redis.host");
maxActive = env.getProperty("redis.pool.maxActive");
maxIdle = env.getProperty("redis.pool.maxIdle");
maxWait = env.getProperty("redis.pool.maxWait");
password = env.getProperty("redis.password");
timeout = env.getProperty("redis.timeout");
database = env.getProperty("redis.database");
port = env.getProperty("redis.port");
sysName = env.getProperty("redis.sysName");
enable = env.getProperty("redis.enable");
} else{
maxActive = prop.getProperty("redis.pool.maxActive");
maxIdle = prop.getProperty("redis.pool.maxIdle");
maxWait = prop.getProperty("redis.pool.maxWait");
password = prop.getProperty("redis.password");
timeout = prop.getProperty("redis.timeout");
database = prop.getProperty("redis.database");
port = prop.getProperty("redis.port");
sysName = prop.getProperty("redis.sysName");
enable = prop.getProperty("redis.enable");
}
}
@Bean
public JedisPoolConfig constructJedisPoolConfig() {
JedisPoolConfig config = new JedisPoolConfig();
// 控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
// 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
config.setMaxTotal(Integer.parseInt(maxActive));
// 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
config.setMaxIdle(Integer.parseInt(maxIdle));
// 表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
config.setMaxWaitMillis(Integer.parseInt(maxWait));
config.setTestOnBorrow(true);
return config;
}
@Bean(name = "pool")
public JedisPool constructJedisPool() {
String ip = this.host;
int port = Integer.parseInt(this.port);
String password = this.password;
int timeout = Integer.parseInt(this.timeout);
int database = Integer.parseInt(this.database);
if (null == pool) {
if (StringUtils.isBlank(password)) {
pool = new JedisPool(constructJedisPoolConfig(), ip, port, timeout);
} else {
pool = new JedisPool(constructJedisPoolConfig(), ip, port, timeout, password, database);
}
}
return pool;
}
public String getMaxActive() {
return maxActive;
}
public void setMaxActive(String maxActive) {
this.maxActive = maxActive;
}
public String getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(String maxIdle) {
this.maxIdle = maxIdle;
}
public String getMaxWait() {
return maxWait;
}
public void setMaxWait(String maxWait) {
this.maxWait = maxWait;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTimeout() {
return timeout;
}
public void setTimeout(String timeout) {
this.timeout = timeout;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getSysName() {
return sysName;
}
public void setSysName(String sysName) {
this.sysName = sysName;
}
public String getEnable() {
return enable;
}
public void setEnable(String enable) {
this.enable = enable;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
}
package com.ihooyah.cache.constants;
public class CacheConstants {
public final static String PRE = "i_";
public final static String REDIS_SYS_NAME = "redis.sysName";
}
package com.ihooyah.cache.constants;
public enum CacheScope {
user, application
}
package com.ihooyah.cache.entity;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
public class CacheBean {
private String key = "";
private String desc = "";
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date expireTime;
public CacheBean(String key, String desc, Date expireTime) {
this.key = key;
this.desc = desc;
this.expireTime = expireTime;
}
public CacheBean(String key, Date expireTime) {
this.key = key;
this.expireTime = expireTime;
}
public CacheBean() {
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Date getExpireTime() {
return expireTime;
}
public void setExpireTime(Date expireTime) {
this.expireTime = expireTime;
}
}
package com.ihooyah.cache.parser;
import java.lang.reflect.Type;
/**
* cache结果解析
* <p/>
* 解决问题:
*
* @author Ace
* @version 1.0
* @date 2017年5月6日
* @since 1.7
*/
public interface ICacheResultParser {
/**
* 解析结果
*
* @param value
* @param returnType
* @param origins
* @return
*/
public Object parse(String value, Type returnType, Class<?>... origins);
}
package com.ihooyah.cache.parser;
import com.ihooyah.cache.constants.CacheScope;
public abstract class IKeyGenerator {
public static final String LINK = "_";
/**
* 获取动态key
*
* @param key
* @param scope
* @param parameterTypes
* @param arguments
* @return
*/
public String getKey(String key, CacheScope scope,
Class<?>[] parameterTypes, Object[] arguments) {
StringBuffer sb = new StringBuffer("");
key = buildKey(key, scope, parameterTypes, arguments);
sb.append(key);
if (CacheScope.user.equals(scope)) {
if (getUserKeyGenerator() != null)
sb.append(LINK)
.append(getUserKeyGenerator().getCurrentUserAccount());
}
return sb.toString();
}
/**
* 当前登陆人key
*
* @param userKeyGenerator
*/
public abstract IUserKeyGenerator getUserKeyGenerator();
/**
* 生成动态key
*
* @param key
* @param scope
* @param parameterTypes
* @param arguments
* @return
*/
public abstract String buildKey(String key, CacheScope scope,
Class<?>[] parameterTypes, Object[] arguments);
}
package com.ihooyah.cache.parser;
public interface IUserKeyGenerator {
public String getCurrentUserAccount();
}
package com.ihooyah.cache.parser.impl;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.ihooyah.cache.constants.CacheScope;
import com.ihooyah.cache.parser.IKeyGenerator;
import com.ihooyah.cache.parser.IUserKeyGenerator;
import com.ihooyah.cache.utils.ReflectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DefaultKeyGenerator extends IKeyGenerator {
@Autowired(required = false)
private IUserKeyGenerator userKeyGenerator;
@Override
public String buildKey(String key, CacheScope scope, Class<?>[] parameterTypes, Object[] arguments) {
boolean isFirst = true;
if (key.indexOf("{") > 0) {
key = key.replace("{", ":{");
Pattern pattern = Pattern.compile("\\d+\\.?[\\w]*");
Matcher matcher = pattern.matcher(key);
while (matcher.find()) {
String tmp = matcher.group();
String express[] = matcher.group().split("\\.");
String i = express[0];
int index = Integer.parseInt(i) - 1;
Object value = arguments[index];
if (parameterTypes[index].isAssignableFrom(List.class)) {
List result = (List) arguments[index];
value = result.get(0);
}
if (value == null || value.equals("null"))
value = "";
if (express.length > 1) {
String field = express[1];
value = ReflectionUtils.getFieldValue(value, field);
}
if (isFirst) {
key = key.replace("{" + tmp + "}", value.toString());
} else {
key = key.replace("{" + tmp + "}", LINK + value.toString());
}
}
}
return key;
}
@Override
public IUserKeyGenerator getUserKeyGenerator() {
return userKeyGenerator;
}
}
package com.ihooyah.cache.parser.impl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.ihooyah.cache.parser.ICacheResultParser;
public class DefaultResultParser implements ICacheResultParser {
@Override
public Object parse(String value, Type type, Class<?>... origins) {
Object result = null;
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
if (((Class) rawType).isAssignableFrom(List.class)) {
result = JSON.parseArray(value, (Class) parameterizedType.getActualTypeArguments()[0]);
}
} else if (origins == null) {
result = JSON.parseObject(value, (Class) type);
} else {
result = JSON.parseObject(value, origins[0]);
}
return result;
}
}
package com.ihooyah.cache.rest;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.ihooyah.cache.service.ICacheManager;
import com.ihooyah.cache.utils.TreeUtils;
import com.ihooyah.cache.vo.CacheTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("cache")
public class CacheRest {
@Autowired
private ICacheManager cacheManager;
@RequestMapping("/list")
@ResponseBody
public List<CacheTree> listAll() {
return TreeUtils.buildTree(cacheManager.getAll());
}
@RequestMapping(path = "/pre/{pre:.*}", method = RequestMethod.GET)
@ResponseBody
public List<CacheTree> listPre(@PathVariable("pre") String pre) {
return TreeUtils.buildTree(cacheManager.getByPre(pre));
}
@RequestMapping(path = "/{key:.*}", method = RequestMethod.GET)
@ResponseBody
public String get(@PathVariable("key") String key) {
return cacheManager.get(key);
}
@RequestMapping(path = "/remove", method = {RequestMethod.DELETE})
@ResponseBody
public void removeAll() {
cacheManager.removeAll();
}
@RequestMapping(path = "/pre/{pre:.*}", method = {RequestMethod.DELETE})
@ResponseBody
public void removePre(@PathVariable("pre") String pre) {
cacheManager.removeByPre(pre);
}
@RequestMapping(path = "/{key:.*}", method = RequestMethod.DELETE)
@ResponseBody
public void removeKey(@PathVariable("key") String key) {
cacheManager.remove(key);
}
@RequestMapping(path = "/{key:.*}", method = RequestMethod.PUT)
@ResponseBody
public void updateTime(@PathVariable("key") String key, int hour) {
cacheManager.update(key, hour);
}
@RequestMapping("")
public String index() {
return "/static/cache/index.html";
}
}
/**
*
*/
package com.ihooyah.cache.service;
import com.ihooyah.cache.entity.CacheBean;
import com.ihooyah.cache.vo.CacheTree;
import java.util.List;
public interface ICacheManager {
public void removeAll();
public void remove(String key);
public void remove(List<CacheBean> caches);
public void removeByPre(String pre);
public List<CacheTree> getAll();
public List<CacheTree> getByPre(String pre);
public void update(String key, int hour);
public void update(List<CacheBean> caches, int hour);
public String get(String key);
}
/**
*
*/
package com.ihooyah.cache.service.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.ihooyah.cache.api.CacheAPI;
import com.ihooyah.cache.config.RedisConfig;
import com.ihooyah.cache.entity.CacheBean;
import com.ihooyah.cache.service.ICacheManager;
import com.ihooyah.cache.vo.CacheTree;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Service
public class CacheManagerImpl implements ICacheManager {
@Autowired
private Environment env;
@Autowired
private CacheAPI cacheAPI;
@Autowired
private RedisConfig redisConfig;
/**
*
*/
public CacheManagerImpl() {
}
@Override
public void removeAll() {
cacheAPI.removeByPre(redisConfig.getSysName());
}
@Override
public void remove(String key) {
cacheAPI.remove(key);
}
@Override
public void remove(List<CacheBean> caches) {
String[] keys = new String[caches.size()];
int i = 0;
for (CacheBean cache : caches) {
keys[i] = cache.getKey();
i++;
}
cacheAPI.remove(keys);
}
@Override
public void removeByPre(String pre) {
if (!pre.contains(redisConfig.getSysName())) {
pre = redisConfig.getSysName()+ ":" + pre+"*";
}
cacheAPI.removeByPre(pre);
}
@Override
public List<CacheTree> getAll() {
List<CacheBean> caches = cacheAPI.listAll();
List<CacheTree> cts = toTree(caches);
return cts;
}
/**
* @param caches
* @return
* @author Ace
* @date 2017年5月11日
*/
private List<CacheTree> toTree(List<CacheBean> caches) {
List<CacheTree> result = new ArrayList<CacheTree>();
Set<CacheTree> cts = new HashSet<CacheTree>();
CacheTree ct = new CacheTree();
for (CacheBean cache : caches) {
String[] split = cache.getKey().split(":");
for (int i = split.length - 1; i > 0; i--) {
if (i == split.length - 1) {
ct = new CacheTree(cache);
} else {
ct = new CacheTree();
}
if (i - 1 >= 0) {
ct.setId(split[i]);
ct.setParentId(split[i - 1].endsWith(redisConfig.getSysName()) ? "-1" : split[i - 1]);
}
if (split.length == 2) {
cts.remove(ct);
}
cts.add(ct);
}
}
result.addAll(cts);
return result;
}
@Override
public List<CacheTree> getByPre(String pre) {
if (StringUtils.isBlank(pre)) {
return getAll();
}
if (!pre.contains(redisConfig.getSysName())) {
pre = redisConfig.getSysName() + "*" + pre;
}
return toTree(cacheAPI.getCacheBeanByPre(pre));
}
public CacheAPI getCacheAPI() {
return cacheAPI;
}
public void setCacheAPI(CacheAPI cacheAPI) {
this.cacheAPI = cacheAPI;
}
@Override
public void update(String key, int hour) {
String value = cacheAPI.get(key);
cacheAPI.set(key, value, hour * 60);
}
@Override
public void update(List<CacheBean> caches, int hour) {
for (CacheBean cache : caches) {
String value = cacheAPI.get(cache.getKey());
cacheAPI.set(cache.getKey(), value, hour);
}
}
@Override
public String get(String key) {
return cacheAPI.get(key);
}
}
package com.ihooyah.cache.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.NoSuchElementException;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
/**
* Properties文件载入工具类. 可载入多个properties文件, 相同的属性在最后载入的文件中的值将会覆盖之前的值,但以System的Property优先.
* @author calvin
* @version 2013-05-15
*/
public class PropertiesLoaderUtils {
private static Logger logger = LoggerFactory.getLogger(PropertiesLoaderUtils.class);
private static ResourceLoader resourceLoader = new DefaultResourceLoader();
private final Properties properties;
public PropertiesLoaderUtils(String... resourcesPaths) {
properties = loadProperties(resourcesPaths);
}
public Properties getProperties() {
return properties;
}
/**
* 取出Property,但以System的Property优先,取不到返回空字符串.
*/
private String getValue(String key) {
String systemProperty = System.getProperty(key);
if (systemProperty != null) {
return systemProperty;
}
if (properties.containsKey(key)) {
return properties.getProperty(key);
}
return "";
}
/**
* 取出String类型的Property,但以System的Property优先,如果都为Null则抛出异常.
*/
public String getProperty(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return value;
}
/**
* 取出String类型的Property,但以System的Property优先.如果都为Null则返回Default值.
*/
public String getProperty(String key, String defaultValue) {
String value = getValue(key);
return value != null ? value : defaultValue;
}
/**
* 取出Integer类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常.
*/
public Integer getInteger(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return Integer.valueOf(value);
}
/**
* 取出Integer类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常
*/
public Integer getInteger(String key, Integer defaultValue) {
String value = getValue(key);
return value != null ? Integer.valueOf(value) : defaultValue;
}
/**
* 取出Double类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常.
*/
public Double getDouble(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return Double.valueOf(value);
}
/**
* 取出Double类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常
*/
public Double getDouble(String key, Integer defaultValue) {
String value = getValue(key);
return value != null ? Double.valueOf(value) : defaultValue;
}
/**
* 取出Boolean类型的Property,但以System的Property优先.如果都为Null抛出异常,如果内容不是true/false则返回false.
*/
public Boolean getBoolean(String key) {
String value = getValue(key);
if (value == null) {
throw new NoSuchElementException();
}
return Boolean.valueOf(value);
}
/**
* 取出Boolean类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容不为true/false则返回false.
*/
public Boolean getBoolean(String key, boolean defaultValue) {
String value = getValue(key);
return value != null ? Boolean.valueOf(value) : defaultValue;
}
/**
* 载入多个文件, 文件路径使用Spring Resource格式.
*/
private Properties loadProperties(String... resourcesPaths) {
Properties props = new Properties();
for (String location : resourcesPaths) {
//logger.debug("Loading properties file from:" + location);
InputStream is = null;
try {
Resource resource = resourceLoader.getResource(location);
is = resource.getInputStream();
props.load(is);
} catch (IOException ex) {
logger.info("Could not load properties from path:" + location + ", " + ex.getMessage());
} finally {
if(is!=null){
try {
is.close();
} catch (IOException e) {
}
}
}
}
return props;
}
}
package com.ihooyah.cache.utils;
import com.ihooyah.cache.vo.CacheTree;
import java.util.ArrayList;
import java.util.List;
public class TreeUtils {
public static List<CacheTree> buildTree(List<CacheTree> trees) {
List<CacheTree> list = new ArrayList<CacheTree>();
for (CacheTree tree : trees) {
if (tree.getParentId().equals("-1")) {
list.add(tree);
}
for (CacheTree t : trees) {
if (t.getParentId().equals(tree.getId())) {
if (tree.getNodes() == null) {
List<CacheTree> myChildrens = new ArrayList<CacheTree>();
myChildrens.add(t);
tree.setNodes(myChildrens);
} else {
tree.getNodes().add(t);
}
}
}
}
return list;
}
}
package com.ihooyah.cache.vo;
import com.ihooyah.cache.entity.CacheBean;
import java.util.ArrayList;
import java.util.List;
public class CacheTree extends CacheBean {
private String id;
private String parentId;
private String text = null;
private List<CacheTree> nodes = new ArrayList<CacheTree>();
public CacheTree(CacheBean cache) {
this.setKey(cache.getKey());
this.setDesc(cache.getDesc());
this.setExpireTime(cache.getExpireTime());
}
public CacheTree() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.text = id;
this.id = id;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((parentId == null) ? 0 : parentId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CacheTree other = (CacheTree) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (parentId == null) {
if (other.parentId != null){
return false;
}
} else if (!parentId.equals(other.parentId)){
return false;
}
return true;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public List<CacheTree> getNodes() {
return nodes;
}
public void setNodes(List<CacheTree> nodes) {
this.nodes = nodes;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
.treeview .list-group-item {
cursor: pointer
}
.treeview span.indent {
margin-left: 10px;
margin-right: 10px
}
.treeview span.icon {
width: 12px;
margin-right: 5px
}
.treeview .node-disabled {
color: silver;
cursor: not-allowed
}
\ No newline at end of file
@charset "UTF-8";
.jsonview {
font-family: monospace;
font-size: 1.1em;
white-space: pre-wrap
}
.jsonview .prop {
font-weight: 700;
text-decoration: none;
color: #000
}
.jsonview .null, .jsonview .undefined {
color: red
}
.jsonview .bool, .jsonview .num {
color: #00f
}
.jsonview .string {
color: green;
white-space: pre-wrap
}
.jsonview .string.multiline {
display: inline-block;
vertical-align: text-top
}
.jsonview .collapser {
position: absolute;
left: -1em;
cursor: pointer
}
.jsonview .collapsible {
transition: height 1.2s;
transition: width 1.2s
}
.jsonview .collapsible.collapsed {
height: .8em;
width: 1em;
display: inline-block;
overflow: hidden;
margin: 0
}
.jsonview .collapsible.collapsed:before {
content: "…";
width: 1em;
margin-left: .2em
}
.jsonview .collapser.collapsed {
transform: rotate(0)
}
.jsonview .q {
display: inline-block;
width: 0;
color: transparent
}
.jsonview li {
position: relative
}
.jsonview ul {
list-style: none;
margin: 0 0 0 2em;
padding: 0
}
.jsonview h1 {
font-size: 1.2em
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Ace Cache Manager</title>
<link href="/static/css/bootstrap-3.1.0.css" rel="stylesheet">
<link href="/static/css/jquery.jsonview.min.css" rel="stylesheet">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div class="container">
<h1>Ace Cache Manager</h1>
<br>
<div id="alert" class="alert alert-success" style="display: none">
<a href="#" class="close" onclick="$('#alert').hide();">&times;</a> <strong>success!</strong>
</div>
<div class="row">
<hr>
<div class="col-sm-4">
<h2>Keys</h2>
<div class="form-group">
<label for="input-check-node" class="sr-only">Search Tree:</label>
<input type="input" class="form-control" id="input-check-node"
placeholder="Identify node...">
</div>
<div id="treeview-checkable"></div>
</div>
<div class="col-sm-4">
<h2>Desc</h2>
<div class="form-group">
<button type="button" class="btn btn-danger expand-node"
id="btn-removeAll">removeAll
</button>
<button type="button" class="btn btn-primary expand-node"
id="btn-remove">remove
</button>
<button type="button" class="btn btn-success expand-node"
id="btn-update" data-toggle="modal" data-target="#updateModal">delay
</button>
</div>
<strong>key: </strong>
<div id="key" style="display: inline-block;"></div>
<br/> <strong>expire: </strong>
<div id="expireTime" style="display: inline-block;"></div>
<br/> <strong>desc: </strong>
<div id="desc" style="display: inline-block;"></div>
<br/>
</div>
<div class="col-sm-4">
<h2>Preview</h2>
<div id="privew"></div>
</div>
</div>
</div>
<!-- 模态框(Modal) -->
<div class="modal fade" id="updateModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×
</button>
<h4 class="modal-title" id="myModalLabel">Delay Cache Expired
Time</h4>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="expireHour">Expire Hour: </label> <input
type="number" class="form-control" id="expireHour" value="1"
placeholder="input the expire hour">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
close
</button>
<button type="button" id="btn-delay" class="btn btn-primary">delay</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<script src="/static/js/jquery-2.1.1.min.js"></script>
<script src="/static/js/bootstrap-3.1.0.js"></script>
<script src="/static/js/bootstrap-treeview.min.js"></script>
<script src="/static/js/jquery.jsonview.min.js"></script>
<script src="/static/js/cache.js"></script>
</body>
</html>
$(function () {
$('#btn-removeAll').on('click', function (e) {
$.ajax({
type: "DELETE",
url: "/cache/remove",
success: function (data) {
show();
init();
}
});
});
$('#btn-remove').on('click', function (e) {
$.ajax({
type: "DELETE",
url: "/cache/pre/" + $('#key').text(),
success: function (data) {
show();
init();
}
});
});
$('#btn-delay').on('click', function (e) {
if ($('#expireHour').val() == "") {
alert("Please input the number!");
}
if($('#expireTime').text()==""){
$('#updateModal').modal('hide');
return;
}
$.ajax({
type: 'PUT',
url: "/cache/" + $('#key').text(),
data: "hour=" + $('#expireHour').val(),
success: function (data) {
show();
init();
$('#updateModal').modal('hide');
}
});
});
init();
});
function clear() {
$('#key').empty();
$('#expireTime').empty();
$('#desc').empty();
$('#privew').empty();
}
function show() {
$('#alert').show();
setTimeout(function () {
$("#alert").hide()
}, 1000);
}
function init() {
clear();
$.ajax({
type: "GET",
url: "/cache/list",
success: function (defaultData) {
var $checkableTree = $('#treeview-checkable').treeview({
data: defaultData,
levels: 1,
showIcon: false,
onNodeSelected: function (event, node) {
clear();
if (node.key == "") {
$('#key').prepend('<p>' + node.text + '</p>');
return;
}
$('#key').prepend('<p>' + node.key + '</p>');
$('#expireTime').prepend('<p>' + node.expireTime + '</p>');
$('#desc').prepend('<p>' + node.desc + '</p>');
$.ajax({
type: "GET",
url: "/cache/" + node.key,
success: function (data) {
var text;
try {
text = eval("(" + data + ")");
} catch (e) {
$('#privew').empty();
$('#privew').prepend('<p>' + data
+ '</p>');
return;
}
if (text instanceof Array) {
if (text.length > 300) {
$('#privew').empty();
$('#privew')
.prepend('<p>Too huge to preivew</p>');
} else {
$("#privew").JSONView(text);
}
} else if (typeof(text) == "object"
&& Object.prototype.toString
.call(text).toLowerCase() == "[object object]"
&& !text.length) {
$("#privew").JSONView(text);
} else {
$('#privew').empty();
$('#privew').prepend('<p>' + data
+ '</p>');
}
}
});
}
});
var findCheckableNodess = function () {
return $checkableTree.treeview('search', [
$('#input-check-node').val(), {
ignoreCase: false,
exactMatch: false
}]);
};
var checkableNodes = findCheckableNodess();
$('#input-check-node').on('keyup', function (e) {
checkableNodes = findCheckableNodess();
$('.check-node')
.prop('disabled', !(checkableNodes.length >= 1));
});
}
});
}
\ No newline at end of file
!function (e) {
var t, n, r, l, o;
return o = ["object", "array", "number", "string", "boolean", "null"], r = function () {
function t(e) {
null == e && (e = {}), this.options = e
}
return t.prototype.htmlEncode = function (e) {
return null !== e ? e.toString().replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : ""
}, t.prototype.jsString = function (e) {
return e = JSON.stringify(e).slice(1, -1), this.htmlEncode(e)
}, t.prototype.decorateWithSpan = function (e, t) {
return '<span class="' + t + '">' + this.htmlEncode(e) + "</span>"
}, t.prototype.valueToHTML = function (t, n) {
var r;
if (null == n && (n = 0), r = Object.prototype.toString.call(t).match(/\s(.+)]/)[1].toLowerCase(), this.options.strict && !e.inArray(r, o))throw new Error("" + r + " is not a valid JSON value type");
return this["" + r + "ToHTML"].call(this, t, n)
}, t.prototype.nullToHTML = function (e) {
return this.decorateWithSpan("null", "null")
}, t.prototype.undefinedToHTML = function () {
return this.decorateWithSpan("undefined", "undefined")
}, t.prototype.numberToHTML = function (e) {
return this.decorateWithSpan(e, "num")
}, t.prototype.stringToHTML = function (e) {
var t, n;
return /^(http|https|file):\/\/[^\s]+$/i.test(e) ? '<a href="' + this.htmlEncode(e) + '"><span class="q">"</span>' + this.jsString(e) + '<span class="q">"</span></a>' : (t = "", e = this.jsString(e), this.options.nl2br && (n = /([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g, n.test(e) && (t = " multiline", e = (e + "").replace(n, "$1<br />"))), '<span class="string' + t + '">"' + e + '"</span>')
}, t.prototype.booleanToHTML = function (e) {
return this.decorateWithSpan(e, "bool")
}, t.prototype.arrayToHTML = function (e, t) {
var n, r, l, o, i, s, a, p;
for (null == t && (t = 0), r = !1, i = "", o = e.length, l = a = 0, p = e.length; p > a; l = ++a)s = e[l], r = !0, i += "<li>" + this.valueToHTML(s, t + 1), o > 1 && (i += ","), i += "</li>", o--;
return r ? (n = 0 === t ? "" : " collapsible", '[<ul class="array level' + t + n + '">' + i + "</ul>]") : "[ ]"
}, t.prototype.objectToHTML = function (e, t) {
var n, r, l, o, i, s, a;
null == t && (t = 0), r = !1, i = "", o = 0;
for (s in e)o++;
for (s in e)a = e[s], r = !0, l = this.options.escape ? this.jsString(s) : s, i += '<li><a class="prop" href="javascript:;"><span class="q">"</span>' + l + '<span class="q">"</span></a>: ' + this.valueToHTML(a, t + 1), o > 1 && (i += ","), i += "</li>", o--;
return r ? (n = 0 === t ? "" : " collapsible", '{<ul class="obj level' + t + n + '">' + i + "</ul>}") : "{ }"
}, t.prototype.jsonToHTML = function (e) {
return '<div class="jsonview">' + this.valueToHTML(e) + "</div>"
}, t
}(), "undefined" != typeof module && null !== module && (module.exports = r), n = function () {
function e() {
}
return e.bindEvent = function (e, t) {
var n;
return e.firstChild.addEventListener("click", function (e) {
return function (n) {
return e.toggle(n.target.parentNode.firstChild, t)
}
}(this)), n = document.createElement("div"), n.className = "collapser", n.innerHTML = t.collapsed ? "+" : "-", n.addEventListener("click", function (e) {
return function (n) {
return e.toggle(n.target, t)
}
}(this)), e.insertBefore(n, e.firstChild), t.collapsed ? this.collapse(n) : void 0
}, e.expand = function (e) {
var t, n;
return n = this.collapseTarget(e), "" !== n.style.display ? (t = n.parentNode.getElementsByClassName("ellipsis")[0], n.parentNode.removeChild(t), n.style.display = "", e.innerHTML = "-") : void 0
}, e.collapse = function (e) {
var t, n;
return n = this.collapseTarget(e), "none" !== n.style.display ? (n.style.display = "none", t = document.createElement("span"), t.className = "ellipsis", t.innerHTML = " &hellip; ", n.parentNode.insertBefore(t, n), e.innerHTML = "+") : void 0
}, e.toggle = function (e, t) {
var n, r, l, o, i, s;
if (null == t && (t = {}), l = this.collapseTarget(e), n = "none" === l.style.display ? "expand" : "collapse", t.recursive_collapser) {
for (r = e.parentNode.getElementsByClassName("collapser"), s = [], o = 0, i = r.length; i > o; o++)e = r[o], s.push(this[n](e));
return s
}
return this[n](e)
}, e.collapseTarget = function (e) {
var t, n;
return n = e.parentNode.getElementsByClassName("collapsible"), n.length ? t = n[0] : void 0
}, e
}(), t = e, l = {
collapse: function (e) {
return "-" === e.innerHTML ? n.collapse(e) : void 0
}, expand: function (e) {
return "+" === e.innerHTML ? n.expand(e) : void 0
}, toggle: function (e) {
return n.toggle(e)
}
}, t.fn.JSONView = function () {
var e, o, i, s, a, p, c;
return e = arguments, null != l[e[0]] ? (a = e[0], this.each(function () {
var n, r;
return n = t(this), null != e[1] ? (r = e[1], n.find(".jsonview .collapsible.level" + r).siblings(".collapser").each(function () {
return l[a](this)
})) : n.find(".jsonview > ul > li .collapsible").siblings(".collapser").each(function () {
return l[a](this)
})
})) : (s = e[0], p = e[1] || {}, o = {
collapsed: !1,
nl2br: !1,
recursive_collapser: !1,
escape: !0,
strict: !1
}, p = t.extend(o, p), i = new r(p), "[object String]" === Object.prototype.toString.call(s) && (s = JSON.parse(s)), c = i.jsonToHTML(s), this.each(function () {
var e, r, l, o, i, s;
for (e = t(this), e.html(c), l = e[0].getElementsByClassName("collapsible"), s = [], o = 0, i = l.length; i > o; o++)r = l[o], "LI" === r.parentNode.nodeName ? s.push(n.bindEvent(r.parentNode, p)) : s.push(void 0);
return s
}))
}
}(jQuery);
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-dd</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-generator</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-inteface</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-jdwl</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-lg</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-system</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-wgyq</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-modules</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-ys</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-server</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-modules</artifactId>
<packaging>pom</packaging>
<modules>
<module>ihooyah-hza-cache</module>
<module>ihooyah-hza-inteface</module>
<module>ihooyah-hza-lg</module>
<module>ihooyah-hza-generator</module>
<module>ihooyah-hza-dd</module>
<module>ihooyah-hza-jdwl</module>
<module>ihooyah-hza-wgyq</module>
<module>ihooyah-hza-ys</module>
<module>ihooyah-hza-system</module>
</modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ihooyah-hza-server</artifactId>
<groupId>com.ihooyah</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ihooyah-hza-springadmin</artifactId>
<properties>
<boot.admin.version>2.1.2</boot.admin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-mail</artifactId>-->
<!--</dependency>-->
<!--增加eureka-server的依赖-->
<!--<dependency>-->
<!--<groupId>org.springframework.cloud</groupId>-->
<!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!--</dependency>-->
<!--对nacos依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${boot.admin.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
</dependencies>
<build>
<finalName>ihooyah-hza-springadmin</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.ihooyah.springadmin;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 描述
*
* @author fatiaojie
* @date 2020/3/30 19:13
*/
@SpringBootApplication
@EnableAdminServer
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
}
spring:
application:
name: ihooyah-hza-springadmin
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 9511 #启动端口
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: '*'
\ No newline at end of file
...@@ -9,5 +9,113 @@ ...@@ -9,5 +9,113 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<repositories>
<repository>
<id>central</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<layout>default</layout>
<!-- 是否开启发布版构件下载 -->
<releases>
<enabled>true</enabled>
</releases>
<!-- 是否开启快照版构件下载 -->
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
</parent>
<properties>
<mapper.version>3.4.0</mapper.version>
<maven.compile.source>1.8</maven.compile.source>
<maven.compile.target>1.8</maven.compile.target>
<boot.admin.client>2.1.2</boot.admin.client>
</properties>
<modules>
<module>ihooyah-hza-auth</module>
<module>ihooyah-hza-common</module>
<module>ihooyah-hza-gateway</module>
<module>ihooyah-hza-job</module>
<module>ihooyah-hza-modules</module>
<module>ihooyah-hza-springadmin</module>
</modules>
<developers>
<developer>
<name>fatiaojie</name>
<email>7854033@qq.com</email>
</developer>
</developers>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.14</version>
<scope>provided</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.33</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.9.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compile.source}</source>
<target>${maven.compile.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</build>
</project> </project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment