Przeglądaj źródła

网关服务器增加访问应用服务器方法和全局过滤器

郭志波 6 lat temu
rodzic
commit
69810042c7

+ 19 - 0
pom.xml

@@ -18,9 +18,16 @@
 		<h2.version>2.5.0-b60</h2.version>
 		<java.version>1.8</java.version>
 		<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
+		<java.jwt.version>3.7.0</java.jwt.version>
 	</properties>
 
 	<dependencies>
+		<!--jwt 权限验证 -->
+		<dependency>
+			<groupId>com.auth0</groupId>
+			<artifactId>java-jwt</artifactId>
+			<version>${java.jwt.version}</version>
+		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter</artifactId>
@@ -52,6 +59,18 @@
 			<artifactId>spring-boot-starter-test</artifactId>
 			<scope>test</scope>
 		</dependency>
+		
+		<!-- Eureka服务发现注册 -->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
+		</dependency>
+
+		<!-- Feign 声明式服务 -->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-openfeign</artifactId>
+		</dependency>
 
 	</dependencies>
 

+ 4 - 1
src/main/java/com/leanwo/gateway/GatewayApp.java

@@ -5,12 +5,15 @@ import org.slf4j.LoggerFactory;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.ImportResource;
 
 import com.leanwo.gateway.util.ProgramStopUtil;
 
-
+@EnableFeignClients // 启动Feign客户端
 @SpringBootApplication
 @EnableDiscoveryClient//开启Eureka的客户端发现
+@ImportResource(locations={"classpath:applicationContext.xml"})
 public class GatewayApp {
 	
 	private static Logger logger = LoggerFactory.getLogger(GatewayApp.class);

+ 69 - 0
src/main/java/com/leanwo/gateway/MyGlobalFilter.java

@@ -0,0 +1,69 @@
+package com.leanwo.gateway;
+
+import java.util.List;
+
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+
+import com.leanwo.gateway.dto.AccountManagementDto;
+import com.leanwo.gateway.service.GatewayService;
+import com.leanwo.gateway.util.SpringUtil;
+
+import reactor.core.publisher.Mono;
+
+/**
+ * 全局过滤器
+ * @author GuoZhiBo 20200617
+ *
+ */
+@Component//注入Spring容器
+public class MyGlobalFilter implements GlobalFilter, Ordered{
+
+	/**
+     * 当前过滤器的执行顺序:
+     * 数字越小,越早执行
+     * @return
+     */
+	@Override
+	public int getOrder() {
+		return 0;
+	}
+
+	@Override
+	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+		/**
+         * 目标:拦截所有请求,如果请求参数中,
+         *  包含token。放行,
+         *  如果没有,给用户提示未授权401,未授权
+         */
+        //获取请求参数
+        ServerHttpRequest request = exchange.getRequest();
+        String url = request.getURI().toString();
+        String path = request.getPath().toString();
+        int endIndex = url.length() - path.length();
+        //获取域名
+        String domainName = url.substring(0, endIndex);
+        GatewayService gatewayService = (GatewayService)SpringUtil.getSingleBean(GatewayService.class);
+    	List<AccountManagementDto> accountManagementDtos = gatewayService.getAccountManagementDtoCache();
+    	if(accountManagementDtos != null && accountManagementDtos.size() > 0) {
+    		Long accountId = null;
+    		for(AccountManagementDto accountManagementDto : accountManagementDtos) {
+    			if(accountManagementDto != null) {
+    				if(accountManagementDto.getDomainName().equals(domainName)) {
+    					accountId = accountManagementDto.getAccount();
+    				}
+    			}
+    		}
+    		if(accountId != null) {
+    			request.mutate().header("account", accountId.toString()).build();
+    		}
+    	}
+        //放行
+        return chain.filter(exchange);//代表放行请求
+	}
+
+}

+ 253 - 0
src/main/java/com/leanwo/gateway/dto/AccountManagementDto.java

@@ -0,0 +1,253 @@
+package com.leanwo.gateway.dto;
+
+// TODO: Auto-generated Javadoc
+/**
+ * 账套管理Dto.
+ *
+ * @author GuoZhiBo 20200618
+ */
+public class AccountManagementDto {
+
+    /** ID. */
+    private Long id;
+
+    /** 账套id. */
+    private Long account;
+
+    /** 账套名称. */
+    private String accountName;
+
+    /** 域名. */
+    private String domainName;
+
+    /** 用户名. */
+    private String userName;
+
+    /** 密码. */
+    private String password;
+
+    /** 数据库字符串. */
+    private String url;
+
+    /** Http任务自动执行引擎是否启动. */
+    private Boolean httpTaskEngineImplValue;
+
+    /** 流程报表自动执行引擎是否启动. */
+    private Boolean processreportengineimplValue;
+
+    /** 是否成功. */
+    private Boolean success;
+
+    /** 返回信息. */
+    private String message;
+
+    /**
+     * Gets the iD.
+     *
+     * @return the iD
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * Sets the iD.
+     *
+     * @param id
+     *            the new iD
+     */
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    /**
+     * Gets the 账套id.
+     *
+     * @return the 账套id
+     */
+    public Long getAccount() {
+        return account;
+    }
+
+    /**
+     * Sets the 账套id.
+     *
+     * @param account
+     *            the new 账套id
+     */
+    public void setAccount(Long account) {
+        this.account = account;
+    }
+
+    /**
+     * Gets the 账套名称.
+     *
+     * @return the 账套名称
+     */
+    public String getAccountName() {
+        return accountName;
+    }
+
+    /**
+     * Sets the 账套名称.
+     *
+     * @param accountName
+     *            the new 账套名称
+     */
+    public void setAccountName(String accountName) {
+        this.accountName = accountName;
+    }
+
+    /**
+     * Gets the 域名.
+     *
+     * @return the 域名
+     */
+    public String getDomainName() {
+        return domainName;
+    }
+
+    /**
+     * Sets the 域名.
+     *
+     * @param domainName
+     *            the new 域名
+     */
+    public void setDomainName(String domainName) {
+        this.domainName = domainName;
+    }
+
+    /**
+     * Gets the 用户名.
+     *
+     * @return the 用户名
+     */
+    public String getUserName() {
+        return userName;
+    }
+
+    /**
+     * Sets the 用户名.
+     *
+     * @param userName
+     *            the new 用户名
+     */
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    /**
+     * Gets the 密码.
+     *
+     * @return the 密码
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets the 密码.
+     *
+     * @param password
+     *            the new 密码
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
+     * Gets the 数据库字符串.
+     *
+     * @return the 数据库字符串
+     */
+    public String getUrl() {
+        return url;
+    }
+
+    /**
+     * Sets the 数据库字符串.
+     *
+     * @param url
+     *            the new 数据库字符串
+     */
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    /**
+     * Gets the http任务自动执行引擎是否启动.
+     *
+     * @return the http任务自动执行引擎是否启动
+     */
+    public Boolean getHttpTaskEngineImplValue() {
+        return httpTaskEngineImplValue;
+    }
+
+    /**
+     * Sets the http任务自动执行引擎是否启动.
+     *
+     * @param httpTaskEngineImplValue
+     *            the new http任务自动执行引擎是否启动
+     */
+    public void setHttpTaskEngineImplValue(Boolean httpTaskEngineImplValue) {
+        this.httpTaskEngineImplValue = httpTaskEngineImplValue;
+    }
+
+    /**
+     * Gets the 流程报表自动执行引擎是否启动.
+     *
+     * @return the 流程报表自动执行引擎是否启动
+     */
+    public Boolean getProcessreportengineimplValue() {
+        return processreportengineimplValue;
+    }
+
+    /**
+     * Sets the 流程报表自动执行引擎是否启动.
+     *
+     * @param processreportengineimplValue
+     *            the new 流程报表自动执行引擎是否启动
+     */
+    public void setProcessreportengineimplValue(Boolean processreportengineimplValue) {
+        this.processreportengineimplValue = processreportengineimplValue;
+    }
+
+    /**
+     * Gets the success.
+     *
+     * @return the success
+     */
+    public Boolean getSuccess() {
+        return success;
+    }
+
+    /**
+     * Sets the success.
+     *
+     * @param success
+     *            the new success
+     */
+    public void setSuccess(Boolean success) {
+        this.success = success;
+    }
+
+    /**
+     * Gets the message.
+     *
+     * @return the message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * Sets the message.
+     *
+     * @param message
+     *            the new message
+     */
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 13 - 0
src/main/java/com/leanwo/gateway/exception/BeanNotInjectException.java

@@ -0,0 +1,13 @@
+package com.leanwo.gateway.exception;
+
+public class BeanNotInjectException extends RuntimeException {
+
+	public BeanNotInjectException() {
+		super();
+	}
+
+	public BeanNotInjectException(String message) {
+		super(message);
+	}
+	
+}

+ 14 - 0
src/main/java/com/leanwo/gateway/exception/TokenException.java

@@ -0,0 +1,14 @@
+package com.leanwo.gateway.exception;
+
+/**
+ * Token异常
+ * @author YangZhiJie
+ *
+ */
+public class TokenException extends RuntimeException {
+	
+	public TokenException(String message){
+		super(message);
+	}
+	
+}

+ 52 - 0
src/main/java/com/leanwo/gateway/imp/GatewayServiceImpl.java

@@ -0,0 +1,52 @@
+package com.leanwo.gateway.imp;
+
+
+import java.rmi.ServerException;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.InvalidClaimException;
+import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.auth0.jwt.interfaces.Claim;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.leanwo.gateway.dto.AccountManagementDto;
+import com.leanwo.gateway.server.ProdogServer;
+import com.leanwo.gateway.service.GatewayService;
+
+// TODO: Auto-generated Javadoc
+/**
+ * The Class TokenServiceImpl.
+ */
+@Service
+public class GatewayServiceImpl implements GatewayService {
+
+	/** The Constant logger. */
+	private final static Logger logger = LoggerFactory.getLogger(GatewayServiceImpl.class.getName());
+
+	@Autowired
+	private ProdogServer prodogServer;
+	
+	@Override
+	public List<AccountManagementDto> getAccountManagementDtoCache() {
+		List<AccountManagementDto> accountManagementDtos = null;
+		try {
+			accountManagementDtos = prodogServer.getAccountManagementDtoCache();
+		} catch (ServerException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return accountManagementDtos;
+	}
+    
+}

+ 31 - 0
src/main/java/com/leanwo/gateway/imp/ProdogServerImpl.java

@@ -0,0 +1,31 @@
+package com.leanwo.gateway.imp;
+
+import java.rmi.ServerException;
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+import com.leanwo.gateway.dto.AccountManagementDto;
+import com.leanwo.gateway.server.ProdogServer;
+
+
+@Component
+public class ProdogServerImpl implements ProdogServer {
+
+	private static final String ERROR_MSG = "应用服务器异常";
+
+	/**
+	 * 获取默认的异常
+	 * @return
+	 * @throws ServerException 
+	 */
+	public ServerException getDefaultException() throws ServerException {
+		throw new ServerException(ERROR_MSG);
+	}
+	
+	@Override
+	public List<AccountManagementDto> getAccountManagementDtoCache() throws ServerException {
+		throw getDefaultException();
+	}
+	
+}

+ 33 - 0
src/main/java/com/leanwo/gateway/server/ProdogServer.java

@@ -0,0 +1,33 @@
+package com.leanwo.gateway.server;
+
+
+import java.rmi.ServerException;
+import java.util.List;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.leanwo.gateway.dto.AccountManagementDto;
+import com.leanwo.gateway.imp.ProdogServerImpl;
+
+
+/**
+ * 调用应用服务器.
+ * @author GuoZhiBo
+ * @Date 20200616
+ */
+
+@Service
+@FeignClient(value = "prodog-server", fallback = ProdogServerImpl.class)
+public interface ProdogServer {
+	
+	/**
+	 * 获取所有账套信息
+	 * @return
+	 * @author GuoZhiBo 20200616
+	 */
+	@RequestMapping(value = "/api/AccountManagementResource/getAccountManagementDtoCache", method = RequestMethod.GET, produces = "application/json")
+	List<AccountManagementDto> getAccountManagementDtoCache()  throws ServerException;
+}

+ 16 - 0
src/main/java/com/leanwo/gateway/service/GatewayService.java

@@ -0,0 +1,16 @@
+package com.leanwo.gateway.service;
+
+import java.util.List;
+
+import com.leanwo.gateway.dto.AccountManagementDto;
+
+public interface GatewayService {
+	
+	/**
+	 * 查询账套
+	 * @return
+	 * @author GuoZhiBo 20200618
+	 */
+	List<AccountManagementDto> getAccountManagementDtoCache();
+
+}

+ 121 - 0
src/main/java/com/leanwo/gateway/util/FeignConfig.java

@@ -0,0 +1,121 @@
+package com.leanwo.gateway.util;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
+import org.springframework.cloud.openfeign.support.SpringDecoder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTCreationException;
+import com.leanwo.gateway.exception.TokenException;
+
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import feign.codec.Decoder;
+
+
+/**
+ * Feign配置 使用FeignClient进行服务间调用,传递headers信息
+ */
+@Configuration
+public class FeignConfig implements RequestInterceptor {
+
+    private final static Logger logger = LoggerFactory.getLogger(FeignConfig.class.getName());
+
+    /** The regist overtime ms. */
+    // 注册超时时间
+    private static long REGIST_OVERTIME_MS = (long)(1 * 60 * 60 * 1000);
+
+    /** The token secret. */
+    // 密钥
+    @Value("${server.token.secret}")
+    private String tokenSecret;
+
+    /** The token issuer. */
+    // 密钥
+    @Value("${server.token.issuer}")
+    private String tokenIssuer;
+    
+    @Override
+    public void apply(RequestTemplate requestTemplate) {
+        LoginContext loginContext = LoginContextUtil.getLoginContext();
+
+        if (loginContext == null) {
+        	// 临时的解决办法,后面前端会加token验证
+        	String token = generateRegisterToken();
+            loginContext = new LoginContext();
+            loginContext.setToken(token);
+            loginContext.setAccountId(2L);            
+//            throw new AuthorizeException("您没有权限调用业务服务器。");
+        }
+        String token = loginContext.getToken();
+        logger.info("jwtToken:" + token);
+        if (StringUtil.isNotEmpty(token)) {
+            // header里面添加jwt-token
+            requestTemplate.header("token", loginContext.getToken());
+            requestTemplate.header("account", loginContext.getAccountId().toString());
+            logger.info("header:" + requestTemplate.headers());
+        }
+        if(loginContext.getAccountId() != null) {
+        	requestTemplate.header("account", loginContext.getAccountId().toString());
+        	logger.info("account:" + loginContext.getAccountId());
+        }
+    }
+    
+    public String generateRegisterToken() {
+        long currentMs = new Date().getTime();
+        Date expireDate = new Date(currentMs + REGIST_OVERTIME_MS);
+        Date notBeforeDate = new Date(currentMs + 3 * 1000);
+        String tokenString = null;
+        // Create and Sign a Token
+        try {
+            Algorithm algorithm = Algorithm.HMAC256(tokenSecret);
+            tokenString = JWT.create().withIssuer(tokenIssuer) // 签发者
+                .withExpiresAt(expireDate) // 过期时间
+                .withIssuedAt(new Date()) // 签发时间
+                // .withNotBefore(notBeforeDate) // 下次可访问的时间
+                .withClaim("uuid", UUID.randomUUID().toString()).sign(algorithm);
+        } catch (JWTCreationException exception) {
+            logger.error("JWT Token生成失败.", exception);
+            throw new TokenException("JWT Token生成失败.");
+        }
+        return tokenString;
+    }
+    
+    @Bean
+    public Decoder feignDecoder() {
+        return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
+    }
+
+    public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
+        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new GateWayMappingJackson2HttpMessageConverter());
+        return new ObjectFactory<HttpMessageConverters>() {
+            @Override
+            public HttpMessageConverters getObject() throws BeansException {
+                return httpMessageConverters;
+            }
+        };
+    }
+
+    public class GateWayMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
+        GateWayMappingJackson2HttpMessageConverter(){
+            List<MediaType> mediaTypes = new ArrayList<>();
+            mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8")); 
+            setSupportedMediaTypes(mediaTypes);
+        }
+    }
+}

+ 286 - 0
src/main/java/com/leanwo/gateway/util/LoginContext.java

@@ -0,0 +1,286 @@
+package com.leanwo.gateway.util;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class LoginContext {
+
+	/** 账套ID. */
+	private Long accountId;
+
+	/** 账套日期. */
+	private Date accountDate;
+	
+	/** 登陆人员ID. */
+	private Long userId;
+
+	/** 登陆角色. */
+	private Long roleId;
+
+	/** 登陆公司. */
+	private Long clientId;
+
+	/** 登陆部门. */
+	private Long orgId;
+
+	/** 可查询的所有公司. */
+	private List<Long> clientIds = new ArrayList<Long>();
+
+	/** 可查询公司对应的部门. */
+	private List<Long> orgnizationIds = new ArrayList<Long>();
+	
+	/** 集团公司 + 本公司的上...上级公司 + 本公司的上级公司 + 本公司 */
+	private List<Long> parentClientIds = new ArrayList<Long>();
+
+	/**  集团公司 + 所有的子公司 + 所有的子子公司. */
+	private List<Long> rootSubClientIds = new ArrayList<Long>();
+	
+	/** 语言Id. */
+	private Long languageId;
+
+	/** 集团公司ID. */
+	private Long topClientId;
+
+	/** 登录Token. */
+	private String token;
+	
+	
+	
+	/**
+	 * Gets the 集团公司 + 本公司的上..上级公司 + 本公司的上级公司 + 本公司.
+	 *
+	 * @return the 集团公司 + 本公司的上
+	 */
+	public List<Long> getParentClientIds() {
+		return parentClientIds;
+	}
+
+	/**
+	 * Sets the 集团公司 + 本公司的上..上级公司 + 本公司的上级公司 + 本公司.
+	 *
+	 * @param parentClientIds the new 集团公司 + 本公司的上
+	 */
+	public void setParentClientIds(List<Long> parentClientIds) {
+		this.parentClientIds = parentClientIds;
+	}
+
+	/**
+	 * Gets the 集团公司ID.
+	 *
+	 * @return the 集团公司ID
+	 */
+	public Long getTopClientId() {
+		return topClientId;
+	}
+
+	/**
+	 * Sets the 集团公司ID.
+	 *
+	 * @param topClientId the new 集团公司ID
+	 */
+	public void setTopClientId(Long topClientId) {
+		this.topClientId = topClientId;
+	}
+
+	/**
+	 * Gets the 登陆人员ID.
+	 *
+	 * @return the 登陆人员ID
+	 */
+	public Long getUserId() {
+		return userId;
+	}
+
+	/**
+	 * Sets the 登陆人员ID.
+	 *
+	 * @param userId the new 登陆人员ID
+	 */
+	public void setUserId(Long userId) {
+		this.userId = userId;
+	}
+
+	/**
+	 * Gets the 登陆角色.
+	 *
+	 * @return the 登陆角色
+	 */
+	public Long getRoleId() {
+		return roleId;
+	}
+
+	/**
+	 * Sets the 登陆角色.
+	 *
+	 * @param roleId the new 登陆角色
+	 */
+	public void setRoleId(Long roleId) {
+		this.roleId = roleId;
+	}
+
+	/**
+	 * Gets the 登陆公司.
+	 *
+	 * @return the 登陆公司
+	 */
+	public Long getClientId() {
+		return clientId;
+	}
+
+	/**
+	 * Sets the 登陆公司.
+	 *
+	 * @param clientId the new 登陆公司
+	 */
+	public void setClientId(Long clientId) {
+		this.clientId = clientId;
+	}
+
+	/**
+	 * Gets the 登陆部门.
+	 *
+	 * @return the 登陆部门
+	 */
+	public Long getOrgId() {
+		return orgId;
+	}
+
+	/**
+	 * Sets the 登陆部门.
+	 *
+	 * @param orgId the new 登陆部门
+	 */
+	public void setOrgId(Long orgId) {
+		this.orgId = orgId;
+	}
+
+	/**
+	 * Gets the 可查询公司对应的部门.
+	 *
+	 * @return the 可查询公司对应的部门
+	 */
+	public List<Long> getOrgnizationIds() {
+		return orgnizationIds;
+	}
+
+	/**
+	 * Sets the 可查询公司对应的部门.
+	 *
+	 * @param orgnizationIds the new 可查询公司对应的部门
+	 */
+	public void setOrgnizationIds(List<Long> orgnizationIds) {
+		this.orgnizationIds = orgnizationIds;
+	}
+
+	/**
+	 * Gets the 可查询的所有公司.
+	 *
+	 * @return the 可查询的所有公司
+	 */
+	public List<Long> getClientIds() {
+		return clientIds;
+	}
+
+	/**
+	 * Sets the 可查询的所有公司.
+	 *
+	 * @param clientIds the new 可查询的所有公司
+	 */
+	public void setClientIds(List<Long> clientIds) {
+		this.clientIds = clientIds;
+	}
+
+	/**
+	 * Gets the 集团公司 + 所有的子公司 + 所有的子子公司.
+	 *
+	 * @return the 集团公司 + 所有的子公司 + 所有的子子公司
+	 */
+	public List<Long> getRootSubClientIds() {
+		return rootSubClientIds;
+	}
+
+	/**
+	 * Sets the 集团公司 + 所有的子公司 + 所有的子子公司.
+	 *
+	 * @param rootSubClientIds the new 集团公司 + 所有的子公司 + 所有的子子公司
+	 */
+	public void setRootSubClientIds(List<Long> rootSubClientIds) {
+		this.rootSubClientIds = rootSubClientIds;
+	}
+
+	/**
+	 * Gets the 账套ID.
+	 *
+	 * @return the 账套ID
+	 */
+	public Long getAccountId() {
+		return accountId;
+	}
+
+	/**
+	 * Sets the 账套ID.
+	 *
+	 * @param accountId the new 账套ID
+	 */
+	public void setAccountId(Long accountId) {
+		this.accountId = accountId;
+	}
+
+	/**
+	 * Gets the 语言Id.
+	 *
+	 * @return the 语言Id
+	 */
+	public Long getLanguageId() {
+		return languageId;
+	}
+
+	/**
+	 * Sets the 语言Id.
+	 *
+	 * @param languageId the new 语言Id
+	 */
+	public void setLanguageId(Long languageId) {
+		this.languageId = languageId;
+	}
+
+	/**
+	 * Gets the 账套日期.
+	 *
+	 * @return the 账套日期
+	 */
+	public Date getAccountDate() {
+		return accountDate;
+	}
+
+	/**
+	 * Sets the 账套日期.
+	 *
+	 * @param accountDate the new 账套日期
+	 */
+	public void setAccountDate(Date accountDate) {
+		this.accountDate = accountDate;
+	}
+
+	/**
+	 * Gets the 登录Token.
+	 *
+	 * @return the 登录Token
+	 */
+	public String getToken() {
+		return token;
+	}
+
+	/**
+	 * Sets the 登录Token.
+	 *
+	 * @param token the new 登录Token
+	 */
+	public void setToken(String token) {
+		this.token = token;
+	}
+
+
+
+}

+ 163 - 0
src/main/java/com/leanwo/gateway/util/LoginContextUtil.java

@@ -0,0 +1,163 @@
+package com.leanwo.gateway.util;
+
+/**
+ * 线程变量
+ * @author YangZhiJie
+ *
+ */
+public class LoginContextUtil {
+	
+private static ThreadLocal<LoginContext> loginContextHolder = new ThreadLocal<LoginContext>();
+	
+	private static ThreadLocal<String> uuidHolder = new ThreadLocal<String>();
+	
+	/**
+	 * 从线程获取LoginContext
+	 * @return
+	 */
+	public static LoginContext getLoginContext(){
+		LoginContext loginContext = loginContextHolder.get();
+		return loginContext;
+	}
+	
+	/**
+	 * 设置线程的LoginContext
+	 * @param loginContext
+	 */
+	public static void setLoginContext(LoginContext loginContext){
+		loginContextHolder.set(loginContext);
+	}
+	
+	/**
+	 * 从线程获取UUID
+	 * @return
+	 */
+	public static String getUuid(){
+		String uuid = uuidHolder.get();
+		return uuid;
+	}
+	
+	/**
+	 * 设置线程的UUID
+	 * @param loginContext
+	 */
+	public static void setUuid(String uuid){
+		uuidHolder.set(uuid);
+	}
+	
+	
+	/**
+	 * 设置使用测试账户
+	 * Add by jack 20151010
+	 */
+	public static void setUseApplicationAccount(){
+		LoginContext loginContext = new LoginContext();
+		loginContext.setClientId(1L);
+		loginContext.setOrgId(1L);
+		loginContext.setUserId(1L);
+		loginContext.setAccountId(2L);
+		LoginContextUtil.setLoginContext(loginContext);
+	}
+	
+	/**
+	 * 设置使用系统账户
+	 * Add by jack 20160918
+	 */
+	public static void setUseDictionaryAccount(){
+		LoginContext loginContext = new LoginContext();
+		loginContext.setClientId(1L);
+		loginContext.setOrgId(1L);
+		loginContext.setUserId(1L);
+		loginContext.setAccountId(1L);
+		LoginContextUtil.setLoginContext(loginContext);
+	}
+	
+	
+	/**
+	 * 设置当前环境为测试环境
+	 * Add by jack 20151010
+	 */
+	public static void setTestEnvironment(){
+		LoginContext loginContext = new LoginContext();
+		loginContext.setClientId(1L);
+		loginContext.setOrgId(1L);
+		loginContext.setRoleId(2L);
+		loginContext.setUserId(1L);
+		loginContext.setAccountId(2L);
+		LoginContextUtil.setLoginContext(loginContext);
+	}
+	
+	
+	/**
+	 * 设置当前环境为Dic数据库测试环境
+	 * Add by jack 20151010
+	 */
+	public static void setTestDicEnvironment(){
+		LoginContext loginContext = new LoginContext();
+		loginContext.setClientId(1L);
+		loginContext.setOrgId(2L);
+		loginContext.setUserId(1L);
+		loginContext.setAccountId(1L);
+		loginContext.setLanguageId(283020L);
+		LoginContextUtil.setLoginContext(loginContext);
+	}
+	
+	/**
+	 * 设置线程的环境变量
+	 * @param clientId
+	 * @param orgnizationId
+	 * @param userId
+	 * @param accountId
+	 */
+	public static void setLoginContext(Long clientId, Long orgnizationId, Long userId, Long accountId){
+		LoginContext loginContext = getLoginContext();
+		if(loginContext == null){
+			loginContext = new LoginContext();
+			LoginContextUtil.setLoginContext(loginContext);
+		}
+		loginContext.setClientId(clientId);
+		loginContext.setOrgId(orgnizationId);
+		loginContext.setUserId(userId);
+		loginContext.setAccountId(accountId);
+	}
+
+	/**
+	 * 设置线程的环境变量
+	 * @param clientId
+	 * @param orgnizationId
+	 * @param userId
+	 * @param accountId
+	 */
+	public static void setLoginContext(Long clientId, Long orgnizationId){
+		LoginContext loginContext = getLoginContext();
+		if(loginContext == null){
+			loginContext = new LoginContext();
+			LoginContextUtil.setLoginContext(loginContext);
+		}
+		loginContext.setClientId(clientId);
+		loginContext.setOrgId(orgnizationId);
+	}
+	
+	/**
+	 * 设置使用 accoutId 账户<br>
+	 * 一般用在工作流中
+	 * Add by jack 20151010
+	 */
+	public static void setUseApplicationAccount(Long accountId){
+		LoginContext loginContext = getLoginContext();
+		if(loginContext == null){
+			loginContext = new LoginContext();
+			LoginContextUtil.setLoginContext(loginContext);
+		}
+		loginContext.setAccountId(accountId);
+	}
+
+	
+	
+	/**
+	 * 清空LoginContext
+	 */
+	public static void clear(){
+		loginContextHolder.set(null);
+	}
+}

+ 117 - 0
src/main/java/com/leanwo/gateway/util/SpringUtil.java

@@ -0,0 +1,117 @@
+package com.leanwo.gateway.util;
+
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import com.leanwo.gateway.exception.BeanNotInjectException;
+
+
+public class SpringUtil implements ApplicationContextAware {
+	private static Log logger = LogFactory.getLog(SpringUtil.class);
+	private static ApplicationContext applicationContext;
+
+	@Override
+	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
+		applicationContext = arg0;
+		String[] names = beanNames();
+		logger.info("IOC容器共管理:" + names.length + "个对象。");
+		logger.info("Spring容器初始化成功。");
+	}
+
+	public static ApplicationContext getApplicationContext() {
+		checkApplicationContext();
+		return applicationContext;
+	}
+
+	/**
+	 * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T getBean(String name) {
+		checkApplicationContext();
+		return (T) applicationContext.getBean(name);
+	}
+
+	/**
+	 * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 */
+	public static <T> T getBean(Class<T> clazz) {
+		checkApplicationContext();
+		return (T) applicationContext.getBeansOfType(clazz);
+	}
+
+	/**
+	 * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 */
+	public static Object getSingleBean(Class clazz) {
+		checkApplicationContext();
+		Map<String, Object> map = applicationContext.getBeansOfType(clazz);
+		if (map == null || map.size() == 0) {
+			throw new BeanNotInjectException(clazz.getName() + "未注入。");
+		} else if (map.size() > 1) {
+			throw new IllegalStateException(clazz.getName() + "存在" + map.size() + "个对象。");
+		} else {
+			Iterator iterator = map.entrySet().iterator();
+			Map.Entry entry = (Map.Entry) iterator.next();
+			return entry.getValue();
+		}
+	}
+
+	/**
+	 * 从当前IOC获取标识了annotation注释的对象
+	 * 
+	 * @param annotation
+	 * @return
+	 */
+	public static Collection<Object> beansByAnnotation(Class<? extends Annotation> annotation) {
+		checkApplicationContext();
+		return applicationContext.getBeansWithAnnotation(annotation).values();
+	}
+
+	/**
+	 * 获取当前IOC所有Bean的名称
+	 * 
+	 * @return
+	 */
+	public static String[] beanNames() {
+		checkApplicationContext();
+		return applicationContext.getBeanDefinitionNames();
+
+	}
+
+	/**
+	 * 获取当前IOC中beanName对应的类
+	 * 
+	 * @param beanName
+	 * @return
+	 */
+	public static Class getType(String beanName) {
+		checkApplicationContext();
+		return applicationContext.getType(beanName);
+	}
+
+	/**
+	 * 从当前IOC获取标识了annotation注释的对象
+	 * 
+	 * @param id
+	 * @return
+	 */
+	public static Object getObject(String id) {
+		checkApplicationContext();
+		return applicationContext.getBean(id);
+	}
+
+	private static void checkApplicationContext() {
+		if (applicationContext == null) {
+			throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
+		}
+	}
+}

+ 217 - 0
src/main/java/com/leanwo/gateway/util/StringUtil.java

@@ -0,0 +1,217 @@
+package com.leanwo.gateway.util;
+
+import java.math.BigDecimal;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class StringUtil {
+    /**
+     * 判断字符串是否为空
+     * 
+     * @param content
+     * @return
+     */
+    public static boolean isEmpty(String content) {
+        return (content == null) || (content.length() == 0);
+    }
+
+    /**
+     * 判断字符串是否不为空
+     * 
+     * @param content
+     * @return
+     */
+    public static boolean isNotEmpty(String content) {
+        return !isEmpty(content);
+    }
+
+    /**
+     * 获取不为空的字符串,如果content为空,则返回"",否则返回content
+     * 
+     * @param content
+     * @return
+     */
+    public static String getNotNullString(String content) {
+        if (content == null)
+            return "";
+        return content;
+    }
+
+    /**
+     * 返回拼接字符串
+     * 
+     * @param items
+     * @return
+     */
+    public static String join(String... items) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (String item : items) {
+            if (item != null) {
+                stringBuilder.append(item);
+            }
+        }
+        return stringBuilder.toString();
+    }
+
+    /**
+     * 返回拼接字符串
+     * 
+     * @param items
+     * @return
+     */
+    public static String join(Object... items) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (Object item : items) {
+            if (item != null) {
+                stringBuilder.append(item);
+            }
+        }
+        return stringBuilder.toString();
+    }
+
+    /**
+     * byte数组转换成16进制字符串
+     * 
+     * @param src
+     * @return
+     */
+    public static String bytesToHexString(byte[] src) {
+        StringBuilder stringBuilder = new StringBuilder();
+        if (src == null || src.length <= 0) {
+            return null;
+        }
+        for (int i = 0; i < src.length; i++) {
+            int v = src[i] & 0xFF;
+            String hv = Integer.toHexString(v);
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    /**
+     * byte数组转换成16进制字符串
+     * 
+     * @param src
+     * @return
+     */
+    public static String bytesToHexString(Byte[] src) {
+        StringBuilder stringBuilder = new StringBuilder();
+        if (src == null || src.length <= 0) {
+            return null;
+        }
+        for (int i = 0; i < src.length; i++) {
+            int v = src[i] & 0xFF;
+            String hv = Integer.toHexString(v);
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    /**
+     * 把16进制字符串转换成字节数组
+     * 
+     * @param hexString
+     * @return byte[]
+     */
+    public static byte[] hexStringToBytes(String hex) {
+        int len = (hex.length() / 2);
+        byte[] result = new byte[len];
+        char[] achar = hex.toCharArray();
+        for (int i = 0; i < len; i++) {
+            int pos = i * 2;
+            result[i] = (byte)(toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
+        }
+        return result;
+    }
+
+    public static int toByte(char c) {
+        byte b = (byte)"0123456789ABCDEF".indexOf(c);
+        return b;
+    }
+
+    /**
+     * 判断字符串是否是数字
+     * 
+     * @param str
+     * @return
+     */
+    public static boolean isNumeric(String str) {
+        Pattern pattern = Pattern.compile("[0-9]*");
+        Matcher isNum = pattern.matcher(str);
+        if (!isNum.matches()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 获取字符出现的次数
+     * 
+     * @param text
+     * @param character
+     * @return
+     */
+    public static int countOfChar(String text, char character) {
+        int num = 0;
+        for (int i = 0; i < text.length(); i++) {
+            if (text.charAt(i) == character) {
+                num++;
+            }
+        }
+        return num;
+    }
+
+    /**
+     * 将数据中的中文符号转成英文符号,将中文空格转为英文空格,去掉前后空格
+     * 
+     * @param str
+     * @return
+     * @author GuoZhiBo 20180601
+     */
+    public static String cleanDirtyData(String str) {
+        String str1 = str.trim();
+        String str2 = "";
+        String[] regs = {"!", ",", "。", ";", " ", "?", "!", ",", ".", ";", " ", "?"};
+        for (int i = 0; i < regs.length / 2; i++) {
+            str2 = str1.replaceAll(regs[i], regs[i + regs.length / 2]);
+        }
+        return str2;
+    }
+
+    /**
+     * 获取BigDecimal的数据
+     * 
+     * @param data
+     * @param scale
+     * @return
+     */
+    public static String getString(BigDecimal data, int scale) {
+        if (data == null) {
+            return "";
+        } else {
+            return data.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
+        }
+    }
+    
+    /**
+     * 替换字符串
+     * @param content
+     * @param replacedStr
+     * @param replaceStr
+     * @return
+     */
+    public static String formmateimage(String content,String replacedStr,String replaceStr) {
+    	if(content!=null && replacedStr!=null && replaceStr!=null) {
+    		if(content.indexOf(replacedStr)!=-1) {
+    			content=content.replace(replacedStr, replaceStr);
+    		}
+    	}
+		return content;
+	}
+}

+ 3 - 0
src/main/resources/Application.yml

@@ -1,6 +1,9 @@
 #端口号
 server:
   port: 80
+  token:
+    issuer: leanwo
+    secret: leanwo123123
   #port: 443
   #ssl证书相关配置
   #ssl:

+ 21 - 0
src/main/resources/applicationContext.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
+	xmlns:mvc="http://www.springframework.org/schema/mvc"
+	xsi:schemaLocation="
+	http://www.springframework.org/schema/mvc  http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
+	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
+	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
+	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
+	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
+
+    <!-- 自动扫描 -->
+	<context:component-scan base-package="com.leanwo" />
+	
+	
+	<bean id="springUtil" class="com.leanwo.gateway.util.SpringUtil" />
+	
+	<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"></bean>
+	
+</beans>