├── .gitignore ├── README.MD ├── admin-metrics-service ├── .gitignore ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ └── AdminMetricApplication.java │ └── resources │ └── bootstrap.properties ├── api-gateway ├── .gitignore ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── CustomZuulFilterConfiguration.java │ │ ├── DemoController.java │ │ ├── ZuulClientApplication.java │ │ ├── api │ │ ├── AuthApi.java │ │ ├── OrderApi.java │ │ ├── UserApi.java │ │ ├── fallback │ │ │ └── UserApiFallback.java │ │ └── filter │ │ │ ├── AbstractZuulFilter.java │ │ │ ├── AccessTokenFilter.java │ │ │ ├── AuthResponseFilter.java │ │ │ ├── ErrorFilter.java │ │ │ ├── GetRequestAccessTokenFilter.java │ │ │ ├── ResponseFilter.java │ │ │ ├── ResponseHandler.java │ │ │ └── offical │ │ │ ├── AddResponseHeaderFilter.java │ │ │ ├── ModifyResponseBodyFilter.java │ │ │ ├── ModifyResponseDataStreamFilter.java │ │ │ ├── PrefixRequestEntityFilter.java │ │ │ ├── QueryParamPortPreFilter.java │ │ │ ├── QueryParamServiceIdPreFilter.java │ │ │ └── UppercaseRequestEntityFilter.java │ │ ├── model │ │ └── result │ │ │ └── ZuulResult.java │ │ └── service │ │ ├── HystrixTestService.java │ │ └── RetryableService.java │ └── resources │ ├── application.yaml │ ├── bootstrap.yaml │ └── logback.xml ├── api-getway └── src │ └── main │ └── resources │ └── bootstrap.properties ├── apollo-service ├── .classpath ├── .gitignore ├── .project ├── README.MD ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── UserClientApplication.java │ │ ├── api │ │ └── OrderApi.java │ │ └── controller │ │ ├── DemoController.java │ │ └── UserController.java │ └── resources │ └── bootstrap.properties ├── auth-service ├── .classpath ├── .gitignore ├── .project ├── README.MD ├── auth-service.iml ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── AuthCenterApplication.java │ │ ├── auth │ │ └── AccessTokenAuthManager.java │ │ └── controller │ │ └── AuthController.java │ └── resources │ ├── application.properties │ ├── bootstrap.properties │ └── logback.xml ├── common ├── .gitignore ├── README.MD ├── pom.xml └── src │ └── main │ ├── java │ ├── META-INF │ │ └── MANIFEST.MF │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── README.MD │ │ ├── constant │ │ └── ApiServiceContanst.java │ │ ├── feign │ │ ├── CustomFeignLoggerFactoryConfiguration.java │ │ └── DefaultFeignLogger.java │ │ ├── filter │ │ ├── BaseWebFilter.java │ │ ├── DefaultRequestWrapper.java │ │ └── DefaultResponseWrapper.java │ │ ├── interceptor │ │ └── RemoteLogInterceptor.java │ │ ├── log │ │ ├── KafkaLog.java │ │ ├── LogPointer.java │ │ └── RequestLog.java │ │ ├── model │ │ ├── request │ │ │ ├── AuthRequest.java │ │ │ └── LoginVO.java │ │ └── result │ │ │ ├── AuthResult.java │ │ │ ├── BaseResult.java │ │ │ ├── LoginResult.java │ │ │ └── UserResult.java │ │ └── util │ │ └── ApplicationUtil.java │ └── resources │ └── application.properties ├── config-server ├── .gitignore ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ └── ConfigServerApplication.java │ └── resources │ ├── application.properties │ ├── config │ ├── admin-metrics-service-dev.properties │ ├── api-gateway-dev.properties │ ├── auth-service-dev.properties │ ├── eureka-server-dev.properties │ ├── order-service-dev.properties │ ├── token-service-dev.properties │ ├── user-service-dev.properties │ ├── user-service-mq-dev.properties │ └── user-service-pro.properties │ └── logback.xml ├── config ├── .classpath ├── .gitignore ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── config │ ├── api-getway-dev.properties │ ├── auth-service-dev.properties │ ├── eureka-server-dev.properties │ ├── order-service-dev.properties │ └── user-service-dev.properties ├── deploy │ ├── deploy-config.bat │ ├── deploy-eureka-server.bat │ ├── deploy-order.bat │ ├── deploy-user-service.bat │ └── deploy-zuul.bat └── pom.xml ├── eureka-server ├── .gitignore ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── EurakeServerApplication.java │ │ └── ServerTest.java │ └── resources │ ├── application.properties │ └── bootstrap.properties ├── mq-service ├── .classpath ├── .gitignore ├── .project ├── README.MD ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── KafkaApplication.java │ │ ├── domain │ │ └── Person.java │ │ └── kafka │ │ └── Stream.java │ └── resources │ └── bootstrap.properties ├── order-service ├── .gitignore ├── .project ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── DemoController.java │ │ ├── OrderServiceApplication.java │ │ └── api │ │ └── UserApi.java │ └── resources │ └── bootstrap.properties ├── pom.xml ├── springcloud-gateway ├── pom.xml ├── readme.MD └── src │ └── main │ ├── java │ └── com │ │ └── cml │ │ └── learn │ │ └── springcloud │ │ └── gateway │ │ ├── CustomFilter.java │ │ ├── ErrorHandler.java │ │ ├── SpringCloudGatewayApplication.java │ │ └── controller │ │ └── CustomRouteController.java │ └── resources │ └── application.yaml ├── token-service ├── .gitignore ├── .project ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── TokenServiceApplication.java │ │ ├── configuration │ │ ├── RedissonAutoConfiguration.java │ │ └── RedissonProperties.java │ │ ├── controller │ │ └── TokenController.java │ │ ├── quarz │ │ └── TokenSentinelQuarz.java │ │ ├── service │ │ ├── TokenGeneratorService.java │ │ ├── TokenGeneratorServiceImpl.java │ │ ├── TokenService.java │ │ └── TokenServiceImpl.java │ │ └── util │ │ └── SnowflakeIdWorker.java │ └── resources │ └── bootstrap.properties ├── user-service-mq ├── .gitignore ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── UserMQClientApplication.java │ │ ├── api │ │ └── OrderApi.java │ │ ├── controller │ │ ├── DemoController.java │ │ └── UserController.java │ │ ├── filter │ │ └── ElkFilter.java │ │ ├── kafka │ │ └── Stream.java │ │ ├── log │ │ └── ElkRemoteLogInterceptor.java │ │ └── ribbon │ │ ├── DefaultRibbonLoadBalanceRetryFactory.java │ │ ├── RibbonConfiguration.java │ │ └── listener │ │ └── RibbonRetryListener.java │ └── resources │ ├── application.properties │ ├── bootstrap.properties │ └── logback.xml ├── user-service ├── .gitignore ├── README.MD ├── pom.xml └── src │ └── main │ ├── docker │ └── Dockerfile │ ├── java │ └── com │ │ └── cml │ │ └── springcloud │ │ ├── UserClientApplication.java │ │ ├── api │ │ └── OrderApi.java │ │ ├── controller │ │ ├── DemoController.java │ │ ├── UserController.java │ │ └── UserGatewayController.java │ │ └── ribbon │ │ ├── DefaultRibbonLoadBalanceRetryFactory.java │ │ ├── RibbonConfiguration.java │ │ └── listener │ │ └── RibbonRetryListener.java │ └── resources │ ├── application.properties │ ├── bootstrap.properties │ └── logback.xml └── wiki └── img ├── eureka-server.png ├── login.png ├── login2.png ├── springcloud-strut.png └── zuul1.png /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /logs/ 3 | /*/logs/* 4 | .idea 5 | /**/.idea 6 | /**/target 7 | target 8 | /**/.settings 9 | *.iml 10 | /**/*.iml -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | 2 | ## 工程说明 ## 3 | 4 | SpringCloud 研究与学习,内包含Zuul,Eureka,Config,Feign,Ribbon等框架的使用 5 | 6 | # 博客资源 # 7 | 8 | 9 | - [SpringCloud 项目基础搭建与使用](http://blog.csdn.net/cml_blog/article/details/78343323 "SpringCloud 项目基础搭建与使用") 10 | - [SpringCloud Zuul过滤器返回值拦截](http://blog.csdn.net/cml_blog/article/details/78349703 "SpringCloud Zuul过滤器返回值拦截") 11 | - [SpringCloud 详解配置刷新的原理](http://blog.csdn.net/cml_blog/article/details/78411312 "SpringCloud 详解配置刷新的原理") 12 | - [SpringCloud Zuul修改请求参数信息](http://blog.csdn.net/cml_blog/article/details/78361373 " SpringCloud Zuul修改请求参数信息") 13 | 14 | ## 项目内各工程说明 ## 15 | - common 各服务共通代码 16 | - config-server 配置中心,作为configserver,端口:9000 17 | - eureka-server eureka服务工程,端口:8761 18 | - user-service 用户服务工程 19 | - auth-service 授权认证服务,用于用户权限校验 20 | - order-service 订单服务 21 | - api-getway 网关服务工程,使用Zuul对服务进行分发和权限校验,端口:7000 22 | - user-service-mq GitChat课程使用的代码,使用基于kafka的日志埋点收集系统 23 | 24 | # 项目结构 # 25 | 服务内部调用是互相信任的,可以直接调用。外部访问要通过网关服务进行转发处理。 26 | ![](wiki/img/springcloud-strut.png) 27 | 28 | 29 | ## 使用说明 ## 30 | 31 | 启动前先安装common工程,进入common工程执行命令:mvn install 32 | 33 | 1. 启动配置中心:进入config-server目录执行命令:mvn spring-boot:run 34 | 2. 启动服务中心:eureka-server目录执行命令:mvn spring-boot:run 35 | 3. 启动用户服务:user-service目录执行命令:mvn spring-boot:run 36 | 4. 启动订单服务:order-service目录执行命令:mvn spring-boot:run 37 | 5. 启动授权服务:auth-service目录执行命令:mvn spring-boot:run 38 | 6. 启动网关服务:api-gateway目录执行命令:mvn spring-boot:run 39 | 40 | 步骤1,2需要严格按照顺序启动,步骤1启动成功后才可以继续启动步骤2。步骤2启动成功后,3-6的服务可以同时启动 41 | 42 | 步骤2启动成功后,访问http://localhost:8761/ 即可查看到启动的服务,全都启动成功后即可以进行后续的测试。 43 | 44 | ## Api网关说明 ## 45 | 46 | - 页面启动后访问:http://localhost:8761/ 即可查看eureka服务有多少个已经注册成功 47 | ![](wiki/img/eureka-server.png) 48 | 49 | - 网关直接调用用户和订单服务,访问地址:http://192.168.1.183:7000/biz/zuul 50 | ![](wiki/img/zuul1.png) 51 | - 用户登录,转发到用户登录接口,返回状态码和token信息,由于token信息是在用户服务中使用的。所以对外使用时在网关层使用JWT加密,防止信息篡改和权限校验。直接调用登录接口: 52 | ![](wiki/img/login.png) 53 | 通过网关调用登录接口,返回的token是通过JWT加密的 54 | ![](wiki/img/login2.png) 55 | 56 | 57 | # 使用docker部署 58 | 先配置好docker环境,从cmd进入执行docker images 命令运行正常, 59 | 到工程中,执行;mvn package docker:build,执行docker images可以看到生成的镜像, 60 | 运行:docker run -p 8081:8081 -t springcloud/${工程名字} 61 | 62 | 63 | ## 概论 ## 64 | 通常来说,微服务之间的通信是通过内网来的,与外部连接是通过网关来转发的。 65 | 所以基本上对外开放的工程都集成在api-getway工程上。通过网关服务,对其他服务调用前可以进行基本的权限校验和数据拦截 66 | 67 | ## TODO 68 | - 整合阿波罗配置中心 69 | - 添加hystrix dashboard 70 | - 添加网关流量监控,ip限定,QPS输出 71 | -------------------------------------------------------------------------------- /admin-metrics-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /admin-metrics-service/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ -------------------------------------------------------------------------------- /admin-metrics-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | admin-metrics-service 6 | 1.0 7 | 8 | admin-metrics-service 9 | 健康监控中心 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-commons 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-security 26 | 27 | 28 | de.codecentric 29 | spring-boot-admin-starter-server 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter 34 | 35 | 36 | 37 | 38 | org.jolokia 39 | jolokia-core 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-web 44 | 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-netflix-eureka-client 49 | 50 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-starter-config 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-actuator 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-test 65 | test 66 | 67 | 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-maven-plugin 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /admin-metrics-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD admin-metrics-service-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /admin-metrics-service/src/main/java/com/cml/springcloud/AdminMetricApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import de.codecentric.boot.admin.server.config.EnableAdminServer; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.boot.builder.SpringApplicationBuilder; 8 | import org.springframework.cloud.client.discovery.DiscoveryClient; 9 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 14 | 15 | //@EnableFeignClients 16 | @EnableEurekaClient 17 | @SpringBootApplication 18 | @EnableAdminServer 19 | public class AdminMetricApplication { 20 | public static void main(String[] args) { 21 | new SpringApplicationBuilder(AdminMetricApplication.class).web(true).run(args); 22 | } 23 | 24 | @Autowired 25 | private DiscoveryClient client; 26 | 27 | @Bean 28 | public ApplicationRunner test9() { 29 | return args -> { 30 | Thread.sleep(20000); 31 | System.out.println("====================" + client.getServices()); 32 | }; 33 | } 34 | 35 | @Configuration 36 | public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { 37 | @Override 38 | protected void configure(HttpSecurity http) throws Exception { 39 | http.authorizeRequests().anyRequest().permitAll() 40 | .and().csrf().disable(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /admin-metrics-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=admin-metrics-service 3 | #eureka\u914d\u7f6e 4 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 5 | server.port=8600 6 | management.security.enabled=false 7 | #eureka.instance.leaseRenewalIntervalInSeconds=10 8 | #eureka.client.registryFetchIntervalSeconds=5 9 | #config center 10 | #spring.cloud.config.label=master 11 | #spring.cloud.config.profile=dev 12 | #spring.cloud.config.uri=http://localhost:9000/ 13 | management.endpoints.web.exposure.include="*" 14 | management.endpoints.health.show-details=ALWAYS 15 | spring.boot.admin.routes.endpoints=env,metrics,trace,dump,jolokia,info,configprops,trace,logfile,refresh,flyway,liquibase,heapdump,hystrix.stream 16 | management.endpoint.heapdump.enabled=false 17 | management.endpoint.threaddump.enabled=false 18 | management.health.db.enabled=false 19 | 20 | eureka.instance.leaseRenewalIntervalInSeconds=5 21 | eureka.client.registryFetchIntervalSeconds=5 22 | eureka.instance.health-check-url-path=/actuator/health 23 | eureka.instance.hostname=localhost 24 | eureka.instance.preferIpAddress=true 25 | #spring.boot.admin.url=http://localhost:8600 -------------------------------------------------------------------------------- /api-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /api-gateway/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ 3 | 默认端口:7000 4 | retry测试接口:/biz/retryTest?type type<0 抛出异常重试 -------------------------------------------------------------------------------- /api-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | api-gateway 6 | 1.0 7 | 8 | api-gateway 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-web 21 | 22 | 23 | de.codecentric 24 | spring-boot-admin-starter-client 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-actuator 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-security 33 | 34 | 35 | org.springframework.cloud 36 | spring-cloud-starter-netflix-eureka-client 37 | 38 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-openfeign 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-config 49 | 50 | 51 | org.springframework.cloud 52 | spring-cloud-starter-netflix-zuul 53 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-starter-netflix-hystrix 57 | 58 | 59 | 60 | 61 | io.jsonwebtoken 62 | jjwt 63 | 0.9.0 64 | 65 | 66 | 67 | org.springframework.retry 68 | spring-retry 69 | 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-starter-test 74 | test 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.springframework.boot 82 | spring-boot-maven-plugin 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /api-gateway/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD api-gateway-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/CustomZuulFilterConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.stereotype.Component; 12 | 13 | import com.cml.springcloud.api.filter.AccessTokenFilter; 14 | import com.cml.springcloud.api.filter.AuthResponseFilter; 15 | import com.cml.springcloud.api.filter.ErrorFilter; 16 | import com.cml.springcloud.api.filter.GetRequestAccessTokenFilter; 17 | import com.cml.springcloud.api.filter.ResponseHandler; 18 | import com.google.gson.Gson; 19 | 20 | @Configuration 21 | public class CustomZuulFilterConfiguration { 22 | 23 | @Bean 24 | public AccessTokenFilter accessTokenFilter(AccessTokenResponseHandler handler) { 25 | AccessTokenFilter accessTokenFilter = new AccessTokenFilter(); 26 | accessTokenFilter.setResponseHandler(handler); 27 | return accessTokenFilter; 28 | } 29 | 30 | @Bean 31 | public ErrorFilter errorFilter(CustomErrorHandler errorHandler) { 32 | ErrorFilter errorFilter = new ErrorFilter(); 33 | errorFilter.setErrorHandler(errorHandler); 34 | return errorFilter; 35 | } 36 | 37 | @Bean 38 | public GetRequestAccessTokenFilter getRequestAccessTokenFilter() { 39 | return new GetRequestAccessTokenFilter(); 40 | } 41 | 42 | @Bean 43 | public AuthResponseFilter responseFilter() { 44 | return new AuthResponseFilter(); 45 | } 46 | 47 | @Component 48 | public class AccessTokenResponseHandler implements ResponseHandler { 49 | 50 | @Value("${system.config.error.invalidToken}") 51 | private String invalidTokenMessage; 52 | 53 | @Override 54 | public int getResponseCode() { 55 | return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 56 | } 57 | 58 | @Override 59 | public String getResponseBody(String originMessage, Throwable e) { 60 | Gson gson = new Gson(); 61 | Map result = new HashMap(); 62 | result.put("status", HttpServletResponse.SC_BAD_REQUEST); 63 | result.put("message", invalidTokenMessage); 64 | return gson.toJson(result); 65 | } 66 | } 67 | 68 | /** 69 | * zuul 错误处理 70 | * 71 | * @author cml 72 | * 73 | */ 74 | @Component 75 | public class CustomErrorHandler implements ResponseHandler { 76 | 77 | @Value("${system.config.error.message}") 78 | private String errorMessage; 79 | 80 | @Override 81 | public int getResponseCode() { 82 | return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 83 | } 84 | 85 | @Override 86 | public String getResponseBody(String originMessage, Throwable e) { 87 | Gson gson = new Gson(); 88 | Map result = new HashMap(); 89 | result.put("status", HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 90 | result.put("message", errorMessage); 91 | return gson.toJson(result); 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/DemoController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import com.cml.springcloud.service.HystrixTestService; 4 | import com.netflix.ribbon.proxy.annotation.Hystrix; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.cloud.client.discovery.DiscoveryClient; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import com.cml.springcloud.api.OrderApi; 14 | import com.cml.springcloud.api.UserApi; 15 | import com.cml.springcloud.model.result.ZuulResult; 16 | import com.cml.springcloud.service.RetryableService; 17 | 18 | @Controller 19 | @RequestMapping("/biz") 20 | public class DemoController { 21 | 22 | @Value("${server.port}") 23 | private String port; 24 | 25 | @Value("${spring.application.name}") 26 | private String sererName; 27 | 28 | @Autowired 29 | private DiscoveryClient client; 30 | 31 | @Autowired 32 | private UserApi userApi; 33 | @Autowired 34 | private OrderApi orderApi; 35 | 36 | @Autowired 37 | private RetryableService retryService; 38 | 39 | @Autowired 40 | private HystrixTestService hystrixTestService; 41 | 42 | @ResponseBody 43 | @RequestMapping("/retryTest") 44 | public String retryTest(int type) { 45 | return retryService.testRetry(type); 46 | } 47 | 48 | @ResponseBody 49 | @RequestMapping("/info") 50 | public Object info() { 51 | return client.getServices(); 52 | } 53 | 54 | @ResponseBody 55 | @RequestMapping("/errorController") 56 | public String error() { 57 | return "error"; 58 | } 59 | 60 | @Hystrix 61 | @RequestMapping("/zuul") 62 | @ResponseBody() 63 | public ZuulResult testFeign(@RequestParam(defaultValue = "defaultUser", required = false) String user) throws Exception { 64 | ZuulResult model = new ZuulResult(); 65 | model.setUserInfo(userApi.getUser(user)); 66 | model.setOrderInfo(orderApi.getOrder(user)); 67 | model.setSystemMsg("port:" + port + ",serverName:" + sererName); 68 | model.setErrMsg(hystrixTestService.getTestValue("===")); 69 | model.setExtra(userApi.getUser1("extra")); 70 | return model; 71 | } 72 | // @RequestMapping("/zuul") 73 | // @ResponseBody() 74 | // public JSONObject testFeign(@RequestParam(defaultValue = "defaultUser", 75 | // required = false) String user) 76 | // throws Exception { 77 | // JSONObject result = new JSONObject(); 78 | // result.put("userInfo", userApi.getUser(user)); 79 | // result.put("orderInfo", orderApi.getOrder(user)); 80 | // result.put("zuulServerInfo", "port:" + port + ",serverName:" + 81 | // sererName); 82 | // return result; 83 | // } 84 | } 85 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/ZuulClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 8 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 9 | import org.springframework.cloud.openfeign.EnableFeignClients; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.retry.annotation.EnableRetry; 12 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 14 | 15 | @SpringBootApplication 16 | @EnableRetry 17 | @EnableZuulProxy 18 | @EnableFeignClients 19 | @EnableDiscoveryClient 20 | @EnableHystrix 21 | @EnableCircuitBreaker 22 | public class ZuulClientApplication { 23 | public static void main(String[] args) { 24 | new SpringApplicationBuilder(ZuulClientApplication.class).web(true).run(args); 25 | } 26 | @Configuration 27 | public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { 28 | @Override 29 | protected void configure(HttpSecurity http) throws Exception { 30 | http.authorizeRequests().anyRequest().permitAll() 31 | .and().csrf().disable(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/AuthApi.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | 7 | import com.cml.springcloud.model.result.AuthResult; 8 | 9 | @FeignClient("AUTH-SERVICE") 10 | public interface AuthApi { 11 | 12 | @RequestMapping(value = "/auth/encodeToken") 13 | AuthResult encodeToken(@RequestParam("token") String token); 14 | 15 | @RequestMapping(value = "/auth/decodeToken") 16 | AuthResult parseToken(@RequestParam("token") String token); 17 | } 18 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/OrderApi.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | 7 | @FeignClient("ORDER-SERVICE") 8 | public interface OrderApi { 9 | 10 | @RequestMapping(value = "/order") 11 | String getOrder(@RequestParam("user") String user); 12 | } 13 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/UserApi.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api; 2 | 3 | import com.cml.springcloud.api.fallback.UserApiFallback; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | @FeignClient(value = "USER-SERVICE", fallback = UserApiFallback.class) 9 | public interface UserApi { 10 | 11 | @RequestMapping(value = "/getUser") 12 | String getUser(@RequestParam("user") String user); 13 | 14 | @RequestMapping(value = "/getUser1") 15 | String getUser1(@RequestParam("user") String user); 16 | } 17 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/fallback/UserApiFallback.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.fallback; 2 | 3 | import com.cml.springcloud.api.UserApi; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class UserApiFallback implements UserApi { 8 | @Override 9 | public String getUser(String user) { 10 | return null; 11 | } 12 | 13 | @Override 14 | public String getUser1(String user) { 15 | return "fallback=>" + user; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/AbstractZuulFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.netflix.zuul.ZuulFilter; 7 | 8 | public abstract class AbstractZuulFilter extends ZuulFilter { 9 | protected static Logger logger = LoggerFactory.getLogger(AbstractZuulFilter.class); 10 | } 11 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/AuthResponseFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter; 2 | 3 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 4 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.nio.charset.Charset; 9 | import java.util.Map; 10 | 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 15 | import org.springframework.util.StreamUtils; 16 | 17 | import com.cml.springcloud.api.AuthApi; 18 | import com.cml.springcloud.model.result.AuthResult; 19 | import com.google.gson.Gson; 20 | import com.netflix.zuul.context.RequestContext; 21 | 22 | /** 23 | * 登录验证后数据加密处理 24 | * 25 | * @author cml 26 | * 27 | */ 28 | public class AuthResponseFilter extends AbstractZuulFilter { 29 | 30 | private static final String RESPONSE_KEY_TOKEN = "token"; 31 | @Value("${system.config.authFilter.authUrl}") 32 | private String authUrl; 33 | @Value("${system.config.authFilter.tokenKey}") 34 | private String tokenKey = RESPONSE_KEY_TOKEN; 35 | 36 | @Autowired 37 | private AuthApi authApi; 38 | 39 | @Override 40 | public boolean shouldFilter() { 41 | RequestContext context = getCurrentContext(); 42 | return StringUtils.equals(context.getRequest().getRequestURI().toString(), authUrl); 43 | } 44 | 45 | @Override 46 | public Object run() { 47 | 48 | try { 49 | RequestContext context = getCurrentContext(); 50 | 51 | InputStream stream = context.getResponseDataStream(); 52 | String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8")); 53 | 54 | if (StringUtils.isNotBlank(body)) { 55 | Gson gson = new Gson(); 56 | @SuppressWarnings("unchecked") 57 | Map result = gson.fromJson(body, Map.class); 58 | if (StringUtils.isNotBlank(result.get(tokenKey))) { 59 | AuthResult authResult = authApi.encodeToken(result.get(tokenKey)); 60 | if (!authResult.isSuccess()) { 61 | throw new IllegalArgumentException(authResult.getErrMsg()); 62 | } 63 | String accessToken = authResult.getToken(); 64 | result.put(tokenKey, accessToken); 65 | } 66 | body = gson.toJson(result); 67 | } 68 | context.setResponseBody(body); 69 | } catch (IOException e) { 70 | rethrowRuntimeException(e); 71 | } 72 | return null; 73 | } 74 | 75 | @Override 76 | public String filterType() { 77 | return FilterConstants.POST_TYPE; 78 | } 79 | 80 | @Override 81 | public int filterOrder() { 82 | return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 2; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/ErrorFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter; 2 | 3 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 4 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 5 | 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 9 | 10 | import com.netflix.zuul.context.RequestContext; 11 | 12 | /** 13 | * zuul 错误处理,可以通过设置ErrorHandler自定义返回错误信息和错误码 14 | * 15 | * @author cml 16 | * 17 | */ 18 | public class ErrorFilter extends AbstractZuulFilter { 19 | 20 | public static final String KEY_ERROR = "hasError"; 21 | 22 | private ResponseHandler errorHandler; 23 | 24 | @Override 25 | public boolean shouldFilter() { 26 | return true; 27 | } 28 | 29 | @Override 30 | public Object run() { 31 | 32 | try { 33 | RequestContext context = getCurrentContext(); 34 | context.getResponse().setCharacterEncoding("UTF-8"); 35 | 36 | logger.error("error", context.getThrowable()); 37 | 38 | if (null != errorHandler) { 39 | context.setResponseStatusCode(errorHandler.getResponseCode()); 40 | String body = errorHandler.getResponseBody(null, context.getThrowable()); 41 | context.setResponseBody(body); 42 | // context.setResponseDataStream(new 43 | // ByteArrayInputStream(errorHandler.getResponseBody(context.getThrowable()).getBytes("UTF-8"))); 44 | } else { 45 | context.setResponseStatusCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 46 | context.setResponseBody(context.getThrowable().getMessage()); 47 | } 48 | context.remove("throwable"); 49 | context.put(KEY_ERROR, true); 50 | } catch (Exception e) { 51 | rethrowRuntimeException(e); 52 | } 53 | return null; 54 | } 55 | 56 | @Override 57 | public String filterType() { 58 | return "error"; 59 | } 60 | 61 | @Override 62 | public int filterOrder() { 63 | return FilterConstants.SEND_ERROR_FILTER_ORDER - 1; 64 | } 65 | 66 | public ResponseHandler getErrorHandler() { 67 | return errorHandler; 68 | } 69 | 70 | public void setErrorHandler(ResponseHandler errorHandler) { 71 | this.errorHandler = errorHandler; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/GetRequestAccessTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter; 2 | 3 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 4 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 5 | 6 | import java.io.IOException; 7 | import java.net.URISyntaxException; 8 | import java.net.URL; 9 | 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 12 | import org.springframework.stereotype.Component; 13 | import org.springframework.web.util.UriComponentsBuilder; 14 | 15 | import com.netflix.zuul.context.RequestContext; 16 | 17 | /** 18 | * GET方式拦截器,未登录的用户直接返回未登录数据 19 | * 20 | * @author cml 21 | * 22 | */ 23 | public class GetRequestAccessTokenFilter extends AbstractZuulFilter { 24 | 25 | @Override 26 | public Object run() { 27 | logger.info("GetRequestAccessTokenFilter==>run"); 28 | RequestContext context = getCurrentContext(); 29 | logger.info("====requestMethod:" + context.getRequest().getMethod()); 30 | logger.info("====header:" + context.getRequest().getHeaderNames()); 31 | 32 | String url = (String) context.get(FilterConstants.REQUEST_URI_KEY); 33 | 34 | logger.info("ori url:" + url + ",serviceId:" + context.get("serviceId")); 35 | 36 | // if (true) { 37 | // rethrowRuntimeException(new RuntimeException("主动跑错")); 38 | // } 39 | // URL url = 40 | // UriComponentsBuilder.fromUriString(context.getRequest().getRequestURL().toString()).queryParam("user", 41 | // "modifydUser").build() 42 | // context.set(FilterConstants.REQUEST_URI_KEY, url + "?user=test"); 43 | return null; 44 | } 45 | 46 | @Override 47 | public boolean shouldFilter() { 48 | logger.info("GetRequestAccessTokenFilter==>shouldFilter"); 49 | return StringUtils.equalsIgnoreCase(RequestContext.getCurrentContext().getRequest().getMethod(), "get"); 50 | } 51 | 52 | @Override 53 | public int filterOrder() { 54 | logger.info("GetRequestAccessTokenFilter==>filterOrder"); 55 | return FilterConstants.RIBBON_ROUTING_FILTER_ORDER - 1; 56 | } 57 | 58 | @Override 59 | public String filterType() { 60 | logger.info("AccessTokenFilter==>filterType"); 61 | return FilterConstants.ROUTE_TYPE; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/ResponseFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter; 2 | 3 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 4 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.nio.charset.Charset; 9 | 10 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 11 | import org.springframework.util.StreamUtils; 12 | 13 | import com.netflix.zuul.context.RequestContext; 14 | 15 | /** 16 | * 返回数据处理,添加自定义返回信息 17 | * 18 | * @author cml 19 | * 20 | */ 21 | public class ResponseFilter extends AbstractZuulFilter { 22 | 23 | @Override 24 | public boolean shouldFilter() { 25 | RequestContext context = getCurrentContext(); 26 | // 有错误的返回不处理,其他请求都处理 27 | return null == context.get(ErrorFilter.KEY_ERROR); 28 | } 29 | 30 | @Override 31 | public Object run() { 32 | 33 | try { 34 | RequestContext context = getCurrentContext(); 35 | 36 | InputStream stream = context.getResponseDataStream(); 37 | String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8")); 38 | context.setResponseBody("Modified via setResponseBody(): " + body); 39 | context.setResponseStatusCode(200); 40 | } catch (IOException e) { 41 | logger.error("response", e); 42 | rethrowRuntimeException(e); 43 | } 44 | return null; 45 | } 46 | 47 | @Override 48 | public String filterType() { 49 | logger.info("ResponseFilter==>filterType"); 50 | return "post"; 51 | } 52 | 53 | @Override 54 | public int filterOrder() { 55 | logger.info("ResponseFilter==>filterOrder"); 56 | return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/ResponseHandler.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter; 2 | 3 | /** 4 | * API返回数据处理接口,提供返回状态码和返回的内容 5 | * 6 | * @author cml 7 | * 8 | */ 9 | public interface ResponseHandler { 10 | /** 11 | * 获取返回的http状态码 12 | * 13 | * @return 14 | */ 15 | int getResponseCode(); 16 | 17 | /** 18 | * 获取返回的内容 19 | * 20 | * @param originMessage 21 | * 默认返回的消息 22 | * @param e 23 | * 错误信息 24 | * @return 处理后返回的信息 25 | */ 26 | String getResponseBody(String originMessage, Throwable e); 27 | } 28 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/offical/AddResponseHeaderFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter.offical; 2 | 3 | import java.util.UUID; 4 | 5 | import javax.servlet.http.HttpServletResponse; 6 | 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.netflix.zuul.ZuulFilter; 10 | import com.netflix.zuul.context.RequestContext; 11 | 12 | /** 13 | * @author Spencer Gibb 14 | */ 15 | public class AddResponseHeaderFilter extends ZuulFilter { 16 | public String filterType() { 17 | return "post"; 18 | } 19 | 20 | public int filterOrder() { 21 | return 999; 22 | } 23 | 24 | public boolean shouldFilter() { 25 | return true; 26 | } 27 | 28 | public Object run() { 29 | RequestContext context = RequestContext.getCurrentContext(); 30 | HttpServletResponse servletResponse = context.getResponse(); 31 | servletResponse.addHeader("X-Foo", 32 | UUID.randomUUID().toString()); 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/offical/ModifyResponseBodyFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter.offical; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.nio.charset.Charset; 6 | 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.util.StreamUtils; 9 | 10 | import com.netflix.zuul.ZuulFilter; 11 | import com.netflix.zuul.context.RequestContext; 12 | 13 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 14 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 15 | 16 | /** 17 | * @author Spencer Gibb 18 | */ 19 | public class ModifyResponseBodyFilter extends ZuulFilter { 20 | public String filterType() { 21 | return "post"; 22 | } 23 | 24 | public int filterOrder() { 25 | return 999; 26 | } 27 | 28 | public boolean shouldFilter() { 29 | RequestContext context = getCurrentContext(); 30 | return context.getRequest().getParameter("service") == null; 31 | } 32 | 33 | public Object run() { 34 | try { 35 | RequestContext context = getCurrentContext(); 36 | InputStream stream = context.getResponseDataStream(); 37 | String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8")); 38 | context.setResponseBody("Modified via setResponseBody(): "+body); 39 | } 40 | catch (IOException e) { 41 | rethrowRuntimeException(e); 42 | } 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/offical/ModifyResponseDataStreamFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter.offical; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.nio.charset.Charset; 7 | 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.util.StreamUtils; 10 | 11 | import com.netflix.zuul.ZuulFilter; 12 | import com.netflix.zuul.context.RequestContext; 13 | 14 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 15 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 16 | 17 | /** 18 | * @author Spencer Gibb 19 | */ 20 | public class ModifyResponseDataStreamFilter extends ZuulFilter { 21 | public String filterType() { 22 | return "post"; 23 | } 24 | 25 | public int filterOrder() { 26 | return 999; 27 | } 28 | 29 | public boolean shouldFilter() { 30 | RequestContext context = getCurrentContext(); 31 | return context.getRequest().getParameter("service") != null; 32 | } 33 | 34 | public Object run() { 35 | try { 36 | RequestContext context = getCurrentContext(); 37 | InputStream stream = context.getResponseDataStream(); 38 | String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8")); 39 | body = "Modified via setResponseDataStream(): " + body; 40 | context.setResponseDataStream(new ByteArrayInputStream(body.getBytes("UTF-8"))); 41 | } 42 | catch (IOException e) { 43 | rethrowRuntimeException(e); 44 | } 45 | return null; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/offical/PrefixRequestEntityFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter.offical; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.nio.charset.Charset; 6 | 7 | import javax.servlet.ServletInputStream; 8 | import javax.servlet.http.HttpServletRequestWrapper; 9 | 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.StreamUtils; 12 | 13 | import com.netflix.zuul.ZuulFilter; 14 | import com.netflix.zuul.context.RequestContext; 15 | import com.netflix.zuul.http.ServletInputStreamWrapper; 16 | 17 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 18 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 19 | 20 | /** 21 | * @author Spencer Gibb 22 | */ 23 | public class PrefixRequestEntityFilter extends ZuulFilter { 24 | public String filterType() { 25 | return "pre"; 26 | } 27 | 28 | public int filterOrder() { 29 | return 6; 30 | } 31 | 32 | public boolean shouldFilter() { 33 | RequestContext context = getCurrentContext(); 34 | return context.getRequest().getParameter("service") != null; 35 | } 36 | 37 | public Object run() { 38 | try { 39 | RequestContext context = getCurrentContext(); 40 | InputStream in = (InputStream) context.get("requestEntity"); 41 | if (in == null) { 42 | in = context.getRequest().getInputStream(); 43 | } 44 | String body = StreamUtils.copyToString(in, Charset.forName("UTF-8")); 45 | body = "request body modified via request wrapper: "+ body; 46 | byte[] bytes = body.getBytes("UTF-8"); 47 | context.setRequest(new HttpServletRequestWrapper(getCurrentContext().getRequest()) { 48 | @Override 49 | public ServletInputStream getInputStream() throws IOException { 50 | return new ServletInputStreamWrapper(bytes); 51 | } 52 | 53 | @Override 54 | public int getContentLength() { 55 | return bytes.length; 56 | } 57 | 58 | @Override 59 | public long getContentLengthLong() { 60 | return bytes.length; 61 | } 62 | }); 63 | } 64 | catch (IOException e) { 65 | rethrowRuntimeException(e); 66 | } 67 | return null; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/offical/QueryParamPortPreFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter.offical; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import com.netflix.zuul.ZuulFilter; 6 | import com.netflix.zuul.context.RequestContext; 7 | 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.util.ReflectionUtils; 10 | import org.springframework.web.util.UriComponentsBuilder; 11 | 12 | import java.net.MalformedURLException; 13 | import java.net.URISyntaxException; 14 | import java.net.URL; 15 | 16 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 17 | 18 | /** 19 | * @author Spencer Gibb 20 | */ 21 | public class QueryParamPortPreFilter extends ZuulFilter { 22 | 23 | public int filterOrder() { 24 | // run after PreDecorationFilter 25 | return 5 + 1; 26 | } 27 | 28 | public String filterType() { 29 | return "pre"; 30 | } 31 | 32 | @Override 33 | public boolean shouldFilter() { 34 | RequestContext ctx = getCurrentContext(); 35 | return ctx.getRequest().getParameter("port") != null; 36 | } 37 | 38 | public Object run() { 39 | RequestContext ctx = getCurrentContext(); 40 | HttpServletRequest request = ctx.getRequest(); 41 | // put the serviceId in `RequestContext` 42 | String port = request.getParameter("port"); 43 | try { 44 | URL url = UriComponentsBuilder.fromUri(ctx.getRouteHost().toURI()) 45 | .port(new Integer(port)) 46 | .build().toUri().toURL(); 47 | ctx.setRouteHost(url); 48 | } catch (Exception e) { 49 | ReflectionUtils.rethrowRuntimeException(e); 50 | } 51 | return null; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/offical/QueryParamServiceIdPreFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter.offical; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.netflix.zuul.ZuulFilter; 8 | import com.netflix.zuul.context.RequestContext; 9 | 10 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 11 | 12 | /** 13 | * @author Spencer Gibb 14 | */ 15 | public class QueryParamServiceIdPreFilter extends ZuulFilter { 16 | 17 | public int filterOrder() { 18 | // run before PreDecorationFilter 19 | return 5 - 1; 20 | } 21 | 22 | public String filterType() { 23 | return "pre"; 24 | } 25 | 26 | @Override 27 | public boolean shouldFilter() { 28 | RequestContext ctx = getCurrentContext(); 29 | return ctx.getRequest().getParameter("service") != null; 30 | } 31 | 32 | public Object run() { 33 | RequestContext ctx = getCurrentContext(); 34 | HttpServletRequest request = ctx.getRequest(); 35 | // put the serviceId in `RequestContext` 36 | ctx.put("serviceId", request.getParameter("service")); 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/api/filter/offical/UppercaseRequestEntityFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api.filter.offical; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.nio.charset.Charset; 7 | 8 | import com.netflix.zuul.ZuulFilter; 9 | 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.StreamUtils; 12 | 13 | import com.netflix.zuul.context.RequestContext; 14 | 15 | import static com.netflix.zuul.context.RequestContext.getCurrentContext; 16 | import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; 17 | 18 | /** 19 | * @author Spencer Gibb 20 | */ 21 | public class UppercaseRequestEntityFilter extends ZuulFilter { 22 | public String filterType() { 23 | return "pre"; 24 | } 25 | 26 | public int filterOrder() { 27 | return 6; 28 | } 29 | 30 | public boolean shouldFilter() { 31 | RequestContext context = getCurrentContext(); 32 | return context.getRequest().getParameter("service") == null; 33 | } 34 | 35 | public Object run() { 36 | try { 37 | RequestContext context = getCurrentContext(); 38 | InputStream in = (InputStream) context.get("requestEntity"); 39 | if (in == null) { 40 | in = context.getRequest().getInputStream(); 41 | } 42 | String body = StreamUtils.copyToString(in, Charset.forName("UTF-8")); 43 | // body = "request body modified via set('requestEntity'): "+ body; 44 | body = body.toUpperCase(); 45 | context.set("requestEntity", new ByteArrayInputStream(body.getBytes("UTF-8"))); 46 | } 47 | catch (IOException e) { 48 | rethrowRuntimeException(e); 49 | } 50 | return null; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/model/result/ZuulResult.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.model.result; 2 | 3 | public class ZuulResult extends BaseResult { 4 | private String userInfo; 5 | private String orderInfo; 6 | private String systemMsg; 7 | private String extra; 8 | 9 | public String getExtra() { 10 | return extra; 11 | } 12 | 13 | public void setExtra(String extra) { 14 | this.extra = extra; 15 | } 16 | 17 | public String getUserInfo() { 18 | return userInfo; 19 | } 20 | 21 | public void setUserInfo(String userInfo) { 22 | this.userInfo = userInfo; 23 | } 24 | 25 | public String getOrderInfo() { 26 | return orderInfo; 27 | } 28 | 29 | public void setOrderInfo(String orderInfo) { 30 | this.orderInfo = orderInfo; 31 | } 32 | 33 | public String getSystemMsg() { 34 | return systemMsg; 35 | } 36 | 37 | public void setSystemMsg(String systemMsg) { 38 | this.systemMsg = systemMsg; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/service/HystrixTestService.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.service; 2 | 3 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class HystrixTestService { 8 | public String defaultValue(String key) { 9 | return "defaultValue:" + key; 10 | } 11 | 12 | @HystrixCommand(fallbackMethod = "defaultValue") 13 | public String getTestValue(String key) { 14 | throw new IllegalArgumentException("key:" + key); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/cml/springcloud/service/RetryableService.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.retry.annotation.Recover; 6 | import org.springframework.retry.annotation.Retryable; 7 | import org.springframework.stereotype.Service; 8 | 9 | @Service 10 | public class RetryableService { 11 | private Logger log = LoggerFactory.getLogger(RetryableService.class); 12 | 13 | @Retryable(include = Exception.class, maxAttempts = 3) 14 | public String testRetry(int type) { 15 | if (type < 0) { 16 | log.warn("do smthing fail!!!! retry !!!!!!!!"); 17 | throw new IllegalArgumentException("invalid type [" + type + "]"); 18 | } 19 | return "valid type :" + type; 20 | } 21 | 22 | @Recover 23 | public String recover() { 24 | return "default Value!!!"; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /api-gateway/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | system: 3 | auth: 4 | validTime: 3600000 5 | jwtKey: d1465f91-8bf1-42c1-9e58-4d3e01fd7d2c 6 | config: 7 | accessTokenFilter: 8 | ignore: /user/login 9 | authFilter: 10 | authUrl: /user/login 11 | tokenKey: token 12 | error: 13 | message: connect error 14 | invalidToken: invalid token 15 | logging: 16 | level: 17 | project: 18 | user: 19 | UserClient: DEBUG 20 | feign: 21 | hystrix: 22 | enabled: true 23 | -------------------------------------------------------------------------------- /api-gateway/src/main/resources/bootstrap.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | cloud: 3 | config: 4 | profile: dev 5 | label: master 6 | uri: http://localhost:9000/ 7 | application: 8 | name: api-gateway 9 | boot: 10 | admin: 11 | client: 12 | url: http://localhost:8600 13 | server: 14 | port: 7000 15 | hystrix: 16 | command: 17 | default: 18 | execution: 19 | isolation: 20 | thread: 21 | timeoutInMilliseconds: 5000 22 | management: 23 | endpoints: 24 | web: 25 | exposure: 26 | include: '*' 27 | health: 28 | show-details: ALWAYS 29 | security: 30 | enabled: false 31 | endpoint: 32 | threaddump: 33 | enabled: false 34 | heapdump: 35 | enabled: false 36 | health: 37 | db: 38 | enabled: false 39 | eureka: 40 | instance: 41 | prefer-ip-address: true 42 | lease-expiration-duration-in-seconds: 5 43 | leaseRenewalIntervalInSeconds: 5 44 | lease-renewal-interval-in-seconds: 5 45 | client: 46 | registryFetchIntervalSeconds: 5 47 | zuul: 48 | SendErrorFilter: 49 | error: 50 | disable: true 51 | ignoredPatterns: /biz/* 52 | -------------------------------------------------------------------------------- /api-gateway/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | ${APP_NAME} 11 | 12 | 13 | 14 | 15 | ${ENCODER_PATTERN} 16 | 17 | 18 | 19 | 20 | 22 | 23 | ${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.log 24 | 25 | 26 | 27 | ${ENCODER_PATTERN} 28 | 29 | 30 | 31 | 32 | 34 | 35 | ${LOG_HOME}/${APP_NAME}-error.%d{yyyy-MM-dd}.log 36 | 37 | 38 | 39 | ${ENCODER_PATTERN} 40 | 41 | 42 | ERROR 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /api-getway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=api-getway 3 | server.port=7000 4 | 5 | eureka.instance.leaseRenewalIntervalInSeconds=5 6 | eureka.client.registryFetchIntervalSeconds=5 7 | eureka.instance.lease-expiration-duration-in-seconds=5 8 | eureka.instance.prefer-ip-address=true 9 | eureka.instance.lease-renewal-interval-in-seconds=5 10 | 11 | #config center 12 | spring.cloud.config.label=master 13 | spring.cloud.config.profile=dev 14 | spring.cloud.config.uri=http://localhost:9000/ 15 | 16 | 17 | zuul.ignoredPatterns=/biz/* 18 | #error.path=/biz/errorController 19 | #disable sendErrorfilter format: zuul...disable=true 20 | zuul.SendErrorFilter.error.disable=true 21 | 22 | hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000 23 | 24 | 25 | spring.boot.admin.client.url=http://localhost:8600 26 | management.security.enabled=false 27 | management.endpoints.web.exposure.include=* 28 | management.endpoints.health.show-details=ALWAYS 29 | management.endpoint.heapdump.enabled=false 30 | management.endpoint.threaddump.enabled=false 31 | management.health.db.enabled=false 32 | 33 | #eureka.instance.leaseRenewalIntervalInSeconds=10 34 | #eureka.client.registryFetchIntervalSeconds=10 35 | #eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /apollo-service/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /apollo-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /apollo-service/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | user-service 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /apollo-service/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ -------------------------------------------------------------------------------- /apollo-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | apollo-service 6 | 1.0 7 | 8 | apollo-service 9 | Demo project for Spring Boot 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 1.5.8.RELEASE 15 | 16 | 17 | 18 | 19 | UTF-8 20 | UTF-8 21 | 1.8 22 | Dalston.SR4 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-eureka 34 | 35 | 36 | 37 | org.springframework.cloud 38 | spring-cloud-starter-feign 39 | 40 | 41 | org.springframework.cloud 42 | spring-cloud-starter-config 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-test 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-dependencies 57 | ${spring-cloud.version} 58 | pom 59 | import 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-maven-plugin 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /apollo-service/src/main/java/com/cml/springcloud/UserClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.netflix.feign.EnableFeignClients; 7 | 8 | @EnableFeignClients 9 | @EnableDiscoveryClient 10 | @SpringBootApplication 11 | public class UserClientApplication { 12 | public static void main(String[] args) { 13 | new SpringApplicationBuilder(UserClientApplication.class).web(true).run(args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apollo-service/src/main/java/com/cml/springcloud/api/OrderApi.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api; 2 | 3 | import org.springframework.cloud.netflix.feign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | 7 | @FeignClient("ORDER-SERVICE") 8 | public interface OrderApi { 9 | 10 | @RequestMapping(value = "/order") 11 | String getOrder(@RequestParam("user") String user); 12 | } 13 | -------------------------------------------------------------------------------- /apollo-service/src/main/java/com/cml/springcloud/controller/DemoController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.cloud.client.discovery.DiscoveryClient; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | 10 | import com.cml.springcloud.api.OrderApi; 11 | 12 | @Controller 13 | @RequestMapping("/") 14 | public class DemoController { 15 | 16 | @Value("${spring.application.name}") 17 | private String port; 18 | @Value("${server.port}") 19 | private String sererName; 20 | 21 | @Autowired 22 | private DiscoveryClient client; 23 | 24 | @Autowired 25 | private OrderApi orderApi; 26 | 27 | @ResponseBody 28 | @RequestMapping("/info") 29 | public Object info() { 30 | return client.getServices(); 31 | } 32 | 33 | @ResponseBody 34 | @RequestMapping("/getUser") 35 | public String getUser(String user) { 36 | return "get userInfo user:[" + user + "],from : port:" + port + ",serverName:" + sererName; 37 | } 38 | 39 | @RequestMapping("/test") 40 | @ResponseBody 41 | public String test(String user) { 42 | return "Get userInfo[ " + user + "] from port:" + port + ",serverName:" + sererName + "\n has order:" 43 | + orderApi.getOrder("u" + user); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /apollo-service/src/main/java/com/cml/springcloud/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import java.util.UUID; 4 | 5 | import org.apache.commons.lang.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import com.cml.springcloud.constant.ApiServiceContanst; 14 | import com.cml.springcloud.model.request.LoginVO; 15 | import com.cml.springcloud.model.result.LoginResult; 16 | import com.cml.springcloud.model.result.UserResult; 17 | 18 | @Controller 19 | @RequestMapping("/") 20 | public class UserController { 21 | protected static Logger logger = LoggerFactory.getLogger(UserController.class); 22 | 23 | /** 24 | * 用户登录接口,只需要用户名和密码相同即可 25 | * 26 | * @param user 27 | * @return 28 | */ 29 | @ResponseBody 30 | @PostMapping("/login") 31 | public LoginResult login(LoginVO user) { 32 | logger.info("用户登录:username:" + user.getUsername()); 33 | LoginResult result = new LoginResult(); 34 | if (StringUtils.isNotBlank(user.getUsername()) && StringUtils.equals(user.getUsername(), user.getPassword())) { 35 | String token = UUID.randomUUID().toString(); 36 | result.setToken(token); 37 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_OK); 38 | } else { 39 | result.setErrMsg("用户名或密码错误"); 40 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_FAIL); 41 | } 42 | return result; 43 | } 44 | 45 | @ResponseBody 46 | @PostMapping("/getUserInfoByToken") 47 | public UserResult getUserInfoByToken(String token) { 48 | logger.info("获取用户信息:token:" + token); 49 | UserResult result = new UserResult(); 50 | if (StringUtils.isNotBlank(token)) { 51 | // 查询数据库获取用户信息 52 | result.setUsername("username"); 53 | result.setNickname("nickname"); 54 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_OK); 55 | } else { 56 | result.setErrMsg("invalid token!"); 57 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_FAIL); 58 | } 59 | return result; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /apollo-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=apllo-service 3 | 4 | #eureka\u914d\u7f6e 5 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 6 | 7 | #config center 8 | spring.cloud.config.label=master 9 | spring.cloud.config.profile=dev 10 | spring.cloud.config.uri=http://localhost:9000/ 11 | -------------------------------------------------------------------------------- /auth-service/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /auth-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /auth-service/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | auth-service 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /auth-service/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ -------------------------------------------------------------------------------- /auth-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | auth-service 6 | 1.0 7 | 8 | auth-service 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-security 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-actuator 25 | 26 | 27 | de.codecentric 28 | spring-boot-admin-starter-client 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | org.springframework.cloud 36 | spring-cloud-starter-netflix-eureka-client 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-config 41 | 42 | 52 | 53 | 54 | 55 | io.jsonwebtoken 56 | jjwt 57 | 0.9.0 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-test 63 | test 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-maven-plugin 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /auth-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD auth-service-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /auth-service/src/main/java/com/cml/springcloud/AuthCenterApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | 13 | @EnableEurekaClient 14 | @EnableDiscoveryClient 15 | @SpringBootApplication 16 | public class AuthCenterApplication { 17 | public static void main(String[] args) { 18 | new SpringApplicationBuilder(AuthCenterApplication.class).web(true).run(args); 19 | } 20 | 21 | @Configuration 22 | public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { 23 | @Override 24 | protected void configure(HttpSecurity http) throws Exception { 25 | http.authorizeRequests().anyRequest().permitAll() 26 | .and().csrf().disable(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/cml/springcloud/auth/AccessTokenAuthManager.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.auth; 2 | 3 | import java.security.Key; 4 | import java.text.ParseException; 5 | import java.util.Base64; 6 | import java.util.Date; 7 | import java.util.UUID; 8 | 9 | import javax.annotation.PostConstruct; 10 | import javax.crypto.spec.SecretKeySpec; 11 | 12 | import org.springframework.boot.context.properties.ConfigurationProperties; 13 | import org.springframework.stereotype.Component; 14 | 15 | import com.google.gson.Gson; 16 | 17 | import io.jsonwebtoken.Claims; 18 | import io.jsonwebtoken.Jwts; 19 | import io.jsonwebtoken.SignatureAlgorithm; 20 | 21 | @ConfigurationProperties(prefix = "system.auth") 22 | @Component 23 | public class AccessTokenAuthManager { 24 | private String jwtKey; 25 | private long validTime; 26 | /** 27 | * 加密key,jws使用时会复制一份,不会发生并发问题 28 | */ 29 | private Key key; 30 | 31 | @PostConstruct 32 | public void init() { 33 | key = generateKey(jwtKey); 34 | } 35 | 36 | /** 37 | * 生成token 38 | * 39 | * @param target 40 | * 需要保存到token的对象信息,一般为User对象或map对象 41 | * @return token 42 | * @throws ParseException 43 | */ 44 | public String generateToken(Object target) { 45 | return Jwts.builder().setSubject(new Gson().toJson(target)).setIssuedAt(new Date(System.currentTimeMillis())) 46 | .setExpiration(new Date(System.currentTimeMillis() + validTime)).signWith(SignatureAlgorithm.HS512, key).compact(); 47 | } 48 | 49 | public String getJwtKey() { 50 | return jwtKey; 51 | } 52 | 53 | public void setJwtKey(String jwtKey) { 54 | this.jwtKey = jwtKey; 55 | } 56 | 57 | public long getValidTime() { 58 | return validTime; 59 | } 60 | 61 | public void setValidTime(long validTime) { 62 | this.validTime = validTime; 63 | } 64 | 65 | /** 66 | * 获取token上记录的信息 67 | * 68 | * @param token 69 | * @return token上记录的信息 70 | */ 71 | public String parseToken(String token) { 72 | Claims claim = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody(); 73 | return claim.getSubject(); 74 | } 75 | 76 | /** 77 | * 随机生成字符串key 78 | * 79 | * @return 生成的字符串key 80 | */ 81 | public String generateKeyValue() { 82 | return new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes())); 83 | } 84 | 85 | /** 86 | * 根据字符串key获取Key对象 87 | * 88 | * @param key 89 | * @return 90 | */ 91 | public Key generateKey(String key) { 92 | Key signingKey = new SecretKeySpec(key.getBytes(), SignatureAlgorithm.HS512.getJcaName()); 93 | return signingKey; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/cml/springcloud/controller/AuthController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import javax.servlet.http.HttpServletResponse; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.cloud.client.discovery.DiscoveryClient; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import com.cml.springcloud.auth.AccessTokenAuthManager; 14 | import com.cml.springcloud.model.result.AuthResult; 15 | 16 | @Controller 17 | @RequestMapping("/auth") 18 | public class AuthController { 19 | 20 | protected static Logger logger = LoggerFactory.getLogger(AuthController.class); 21 | 22 | @Autowired 23 | private AccessTokenAuthManager authTokenManager; 24 | 25 | @Autowired 26 | private DiscoveryClient client; 27 | 28 | @ResponseBody 29 | @RequestMapping("/info") 30 | public Object info() { 31 | return client.getServices(); 32 | } 33 | 34 | /** 35 | * 解密信息 36 | * 37 | * @param token 38 | * @return 39 | */ 40 | @RequestMapping("/decodeToken") 41 | @ResponseBody 42 | public AuthResult decodeToken(String token) { 43 | AuthResult authModel = new AuthResult(); 44 | authModel.setStatus(HttpServletResponse.SC_OK); 45 | try { 46 | authModel.setToken(authTokenManager.parseToken(token)); 47 | } catch (Exception e) { 48 | logger.warn("decodeTokenFail", e); 49 | authModel.setErrMsg("invalid token!!!"); 50 | authModel.setStatus(HttpServletResponse.SC_BAD_REQUEST); 51 | } 52 | return authModel; 53 | } 54 | 55 | /** 56 | * 生成加密信息 57 | * 58 | * @param token 59 | * @return 60 | * @throws Exception 61 | */ 62 | @RequestMapping("/encodeToken") 63 | @ResponseBody() 64 | public AuthResult encodeToken(String token) throws Exception { 65 | AuthResult authModel = new AuthResult(); 66 | authModel.setStatus(HttpServletResponse.SC_OK); 67 | authModel.setToken(authTokenManager.generateToken(token)); 68 | return authModel; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/auth-service/src/main/resources/application.properties -------------------------------------------------------------------------------- /auth-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=auth-service 3 | 4 | #config center 5 | spring.cloud.config.label=master 6 | spring.cloud.config.profile=dev 7 | spring.cloud.config.uri=http://localhost:9000/ 8 | 9 | #about auth 10 | system.auth.jwtKey=d1465f91-8bf1-42c1-9e58-4d3e01fd7d2c 11 | system.auth.validTime=3600000 12 | 13 | feign.hystrix.enabled=true 14 | 15 | spring.boot.admin.client.url=http://localhost:8600 16 | management.security.enabled=false 17 | management.endpoints.web.exposure.include=* 18 | management.endpoints.health.show-details=ALWAYS 19 | management.endpoint.heapdump.enabled=false 20 | management.endpoint.threaddump.enabled=false 21 | management.health.db.enabled=false 22 | 23 | eureka.instance.leaseRenewalIntervalInSeconds=10 24 | eureka.client.registryFetchIntervalSeconds=10 25 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /auth-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | ${APP_NAME} 11 | 12 | 13 | 14 | 15 | ${ENCODER_PATTERN} 16 | 17 | 18 | 19 | 20 | 22 | 23 | ${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.log 24 | 25 | 26 | 27 | ${ENCODER_PATTERN} 28 | 29 | 30 | 31 | 32 | 34 | 35 | ${LOG_HOME}/${APP_NAME}-error.%d{yyyy-MM-dd}.log 36 | 37 | 38 | 39 | ${ENCODER_PATTERN} 40 | 41 | 42 | ERROR 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /common/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /common/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ -------------------------------------------------------------------------------- /common/src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/README.MD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/common/src/main/java/com/cml/springcloud/README.MD -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/constant/ApiServiceContanst.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.constant; 2 | 3 | public interface ApiServiceContanst { 4 | interface ResultCode { 5 | int RESULT_OK = 200; 6 | int RESULT_FAIL = 400; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/feign/CustomFeignLoggerFactoryConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.feign; 2 | 3 | import com.cml.springcloud.interceptor.RemoteLogInterceptor; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 7 | import org.springframework.cloud.openfeign.FeignLoggerFactory; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | /** 12 | * @Auther: cml 13 | * @Date: 2018-10-12 14:00 14 | * @Description: 15 | */ 16 | @Configuration 17 | public class CustomFeignLoggerFactoryConfiguration { 18 | 19 | private Logger logger = LoggerFactory.getLogger(getClass()); 20 | 21 | @Bean 22 | public feign.Logger.Level feignLoggerLevel() { 23 | return feign.Logger.Level.FULL; 24 | } 25 | 26 | @Bean 27 | @ConditionalOnMissingBean 28 | public RemoteLogInterceptor feignLogInterceptor() { 29 | return (String name, String url, String requestBody, Integer status, String body, long interval) -> { 30 | logger.debug(String.format("name:%s,url:%s,requestBody:%s,Response:%s,Interval:%s", name, url, requestBody, body, interval)); 31 | }; 32 | } 33 | 34 | @Bean 35 | public DefaultFeignLogger defaultFeignLogger(RemoteLogInterceptor remoteLogInterceptor) { 36 | return new DefaultFeignLogger(remoteLogInterceptor); 37 | } 38 | 39 | @Bean 40 | public FeignLoggerFactory feignLoggerFactory(DefaultFeignLogger defaultFeignLogger) { 41 | return new org.springframework.cloud.openfeign.DefaultFeignLoggerFactory(defaultFeignLogger); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/feign/DefaultFeignLogger.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.feign; 2 | 3 | import com.cml.springcloud.interceptor.RemoteLogInterceptor; 4 | import feign.Logger; 5 | import feign.Request; 6 | import feign.Response; 7 | import feign.Util; 8 | 9 | import java.io.IOException; 10 | 11 | import static feign.Util.UTF_8; 12 | import static feign.Util.decodeOrDefault; 13 | 14 | /** 15 | * @Auther: cml 16 | * @Date: 2018-09-29 11:10 17 | * @Description: 18 | */ 19 | public class DefaultFeignLogger extends Logger { 20 | 21 | private RemoteLogInterceptor logInterceptor; 22 | 23 | public DefaultFeignLogger(RemoteLogInterceptor canaryLogInterceptor) { 24 | this.logInterceptor = canaryLogInterceptor; 25 | } 26 | 27 | @Override 28 | protected void logRequest(String configKey, Level logLevel, Request request) { 29 | } 30 | 31 | @Override 32 | protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime) throws IOException { 33 | 34 | String body = ""; 35 | 36 | int status = response.status(); 37 | if (response.body() != null && !(status == 204 || status == 205)) { 38 | // HTTP 204 No Content "...response MUST NOT include a message-body" 39 | // HTTP 205 Reset Content "...response MUST NOT include an entity" 40 | byte[] bodyData = Util.toByteArray(response.body().asInputStream()); 41 | body = decodeOrDefault(bodyData, UTF_8, "Binary data"); 42 | response = response.toBuilder().body(bodyData).build(); 43 | } 44 | String requestBody = response.request().charset() != null ? new String(response.request().body(), response.request().charset()) : null; 45 | logInterceptor.onResponse(configKey.split("#")[0], response.request().url(), requestBody, response.status(), body, elapsedTime); 46 | return response; 47 | } 48 | 49 | @Override 50 | protected void log(String configKey, String format, Object... args) { 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/filter/BaseWebFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.filter; 2 | 3 | import com.cml.springcloud.log.LogPointer; 4 | import com.cml.springcloud.log.RequestLog; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.servlet.*; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | public abstract class BaseWebFilter implements Filter { 15 | protected Logger logger = LoggerFactory.getLogger(getClass()); 16 | 17 | @Override 18 | public void init(FilterConfig filterConfig) throws ServletException { 19 | 20 | } 21 | 22 | @Override 23 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 24 | DefaultRequestWrapper defaultRequestWrapper = new DefaultRequestWrapper((HttpServletRequest) request); 25 | DefaultResponseWrapper defaultResponseWrapper = new DefaultResponseWrapper((HttpServletResponse) response); 26 | 27 | long startTime = System.currentTimeMillis(); 28 | LogPointer.init(); 29 | 30 | RequestLog requestLog = new RequestLog(); 31 | requestLog.setRemoteIp(getIpAddress((HttpServletRequest) request)); 32 | try { 33 | chain.doFilter(defaultRequestWrapper, defaultResponseWrapper); 34 | requestLog.setSuccessful(true); 35 | } catch (Exception e) { 36 | requestLog.setSuccessful(false); 37 | requestLog.setError(e); 38 | } finally { 39 | requestLog.setRequestBody(defaultRequestWrapper.getRequestBody()); 40 | requestLog.setRequestBodyLength(defaultRequestWrapper.getContentLength()); 41 | requestLog.setUrl(defaultRequestWrapper.getRequestURL().toString()); 42 | requestLog.setName(defaultRequestWrapper.getRequestURI()); 43 | requestLog.setInterval(System.currentTimeMillis() - startTime); 44 | 45 | String responseBody = defaultResponseWrapper.getResponseBody(); 46 | requestLog.setResponse(responseBody); 47 | requestLog.setRequestBodyLength(StringUtils.length(responseBody)); 48 | 49 | onRequestFinished(requestLog); 50 | 51 | LogPointer.clear(); 52 | } 53 | 54 | } 55 | 56 | protected abstract void onRequestFinished(RequestLog requestLog); 57 | 58 | public static String getIpAddress(HttpServletRequest request) { 59 | String ip = request.getHeader("x-forwarded-for"); 60 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 61 | ip = request.getHeader("Proxy-Client-IP"); 62 | } 63 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 64 | ip = request.getHeader("WL-Proxy-Client-IP"); 65 | } 66 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 67 | ip = request.getRemoteAddr(); 68 | } 69 | if (ip.contains(",")) { 70 | return ip.split(",")[0]; 71 | } else { 72 | return ip; 73 | } 74 | } 75 | 76 | @Override 77 | public void destroy() { 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/filter/DefaultRequestWrapper.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.filter; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import javax.servlet.ReadListener; 7 | import javax.servlet.ServletInputStream; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletRequestWrapper; 11 | import java.io.*; 12 | 13 | public class DefaultRequestWrapper extends HttpServletRequestWrapper { 14 | 15 | private String requestBody; 16 | private byte[] requestBodyByte; 17 | private ServletRequest request; 18 | 19 | /** 20 | * Constructs a request object wrapping the given request. 21 | * 22 | * @param request The request to wrap 23 | * @throws IllegalArgumentException if the request is null 24 | */ 25 | public DefaultRequestWrapper(HttpServletRequest request) throws IOException { 26 | super(request); 27 | this.request = request; 28 | requestBodyByte = IOUtils.toByteArray(request.getInputStream()); 29 | this.requestBody = new String(requestBodyByte, request.getCharacterEncoding()); 30 | } 31 | 32 | 33 | public String getRequestBody() throws IOException { 34 | return requestBody; 35 | } 36 | 37 | @Override 38 | public ServletInputStream getInputStream() throws IOException { 39 | final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.requestBodyByte); 40 | return new ServletInputStream() { 41 | public boolean isFinished() { 42 | return byteArrayInputStream.available() == 0; 43 | } 44 | 45 | public boolean isReady() { 46 | return byteArrayInputStream.available() > 0; 47 | } 48 | 49 | public void setReadListener(ReadListener readListener) { 50 | } 51 | 52 | public int read() throws IOException { 53 | return byteArrayInputStream.read(); 54 | } 55 | }; 56 | } 57 | 58 | @Override 59 | public int getContentLength() { 60 | return StringUtils.length(requestBody); 61 | } 62 | 63 | @Override 64 | public long getContentLengthLong() { 65 | return StringUtils.length(requestBody); 66 | } 67 | 68 | @Override 69 | public ServletRequest getRequest() { 70 | return super.getRequest(); 71 | } 72 | 73 | @Override 74 | public BufferedReader getReader() throws IOException { 75 | return IOUtils.toBufferedReader(new StringReader(requestBody)); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/filter/DefaultResponseWrapper.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.filter; 2 | 3 | import javax.servlet.ServletOutputStream; 4 | import javax.servlet.WriteListener; 5 | import javax.servlet.http.HttpServletResponse; 6 | import javax.servlet.http.HttpServletResponseWrapper; 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.IOException; 9 | import java.io.PrintWriter; 10 | import java.io.UnsupportedEncodingException; 11 | 12 | public class DefaultResponseWrapper extends HttpServletResponseWrapper { 13 | private ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 14 | 15 | public DefaultResponseWrapper(HttpServletResponse response) { 16 | super(response); 17 | } 18 | 19 | @Override 20 | public ServletOutputStream getOutputStream() throws IOException { 21 | return new MyServletOutputStream(super.getOutputStream()); // 将数据写到 byte 中 22 | } 23 | 24 | public String getResponseBody() throws UnsupportedEncodingException { 25 | return bytes.toString("UTF-8"); 26 | } 27 | 28 | class MyServletOutputStream extends ServletOutputStream { 29 | private ServletOutputStream ostream; 30 | 31 | public MyServletOutputStream(ServletOutputStream ostream) { 32 | this.ostream = ostream; 33 | } 34 | 35 | @Override 36 | public void write(int b) throws IOException { 37 | ostream.write(b); // 将数据写到 stream 中 38 | bytes.write(b);//复制输出的消息 39 | } 40 | 41 | @Override 42 | public boolean isReady() { 43 | return true; 44 | } 45 | 46 | @Override 47 | public void setWriteListener(WriteListener listener) { 48 | 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/interceptor/RemoteLogInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.interceptor; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * @Auther: cml 7 | * @Date: 2018-09-29 11:09 8 | * @Description: 9 | */ 10 | public interface RemoteLogInterceptor { 11 | void onResponse(String apiName, String url, String requestBody, Integer status, String responseBody, long interval) throws IOException; 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/log/KafkaLog.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.log; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | import java.util.Map; 6 | 7 | public class KafkaLog { 8 | private T data; 9 | private String index; 10 | private String type; 11 | private String serviceName; 12 | private String env; 13 | private Map extra; 14 | private String ip; 15 | private String hostName; 16 | private String traceId; 17 | 18 | public String getHostName() { 19 | try { 20 | return InetAddress.getLocalHost().getHostName(); 21 | } catch (UnknownHostException e) { 22 | e.printStackTrace(); 23 | } 24 | return hostName; 25 | } 26 | 27 | public void setHostName(String hostName) { 28 | this.hostName = hostName; 29 | } 30 | 31 | public String getTraceId() { 32 | return traceId; 33 | } 34 | 35 | public void setTraceId(String traceId) { 36 | this.traceId = traceId; 37 | } 38 | 39 | public String getIp() { 40 | return ip; 41 | } 42 | 43 | public void setIp(String ip) { 44 | this.ip = ip; 45 | } 46 | 47 | public String getServiceName() { 48 | return serviceName; 49 | } 50 | 51 | public void setServiceName(String serviceName) { 52 | this.serviceName = serviceName; 53 | } 54 | 55 | public String getEnv() { 56 | return env; 57 | } 58 | 59 | public void setEnv(String env) { 60 | this.env = env; 61 | } 62 | 63 | public Map getExtra() { 64 | return extra; 65 | } 66 | 67 | public void setExtra(Map extra) { 68 | this.extra = extra; 69 | } 70 | 71 | public T getData() { 72 | return data; 73 | } 74 | 75 | public void setData(T data) { 76 | this.data = data; 77 | } 78 | 79 | public String getIndex() { 80 | return index; 81 | } 82 | 83 | public void setIndex(String index) { 84 | this.index = index; 85 | } 86 | 87 | public String getType() { 88 | return type; 89 | } 90 | 91 | public void setType(String type) { 92 | this.type = type; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/log/LogPointer.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.log; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.UUID; 6 | 7 | public class LogPointer { 8 | private static ThreadLocal traceId = new ThreadLocal<>(); 9 | private static ThreadLocal> points = new ThreadLocal<>(); 10 | 11 | public static void init() { 12 | traceId.set(UUID.randomUUID().toString()); 13 | points.set(new HashMap<>()); 14 | } 15 | 16 | public static String getTraceId() { 17 | return traceId.get(); 18 | } 19 | 20 | public static void addPoint(String key, Object value) { 21 | if (points.get() != null) { 22 | points.get().put(key, value); 23 | } 24 | } 25 | 26 | public static Map getPoints() { 27 | return points.get() == null ? new HashMap<>() : points.get(); 28 | } 29 | 30 | public static void clear() { 31 | traceId.remove(); 32 | points.remove(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/log/RequestLog.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.log; 2 | 3 | public class RequestLog { 4 | private String requestBody; 5 | private int requestBodyLength; 6 | private String response; 7 | private String responseLength; 8 | private boolean successful; 9 | private String url; 10 | private Long interval; 11 | private String name; 12 | private Throwable error; 13 | private transient String errorMsg; 14 | private String remoteIp; 15 | 16 | 17 | public String getError() { 18 | if (null != error && null == errorMsg) { 19 | StringBuffer sb = new StringBuffer(); 20 | StackTraceElement[] stackTraces = error.getStackTrace(); 21 | for (StackTraceElement stackTraceElement : stackTraces) { 22 | sb.append(stackTraceElement).append("\r\n"); 23 | } 24 | errorMsg = sb.toString(); 25 | } 26 | return errorMsg; 27 | } 28 | 29 | public String getRemoteIp() { 30 | return remoteIp; 31 | } 32 | 33 | public void setRemoteIp(String remoteIp) { 34 | this.remoteIp = remoteIp; 35 | } 36 | 37 | public void setError(Throwable error) { 38 | this.error = error; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public void setName(String name) { 46 | this.name = name; 47 | } 48 | 49 | public Long getInterval() { 50 | return interval; 51 | } 52 | 53 | public void setInterval(Long interval) { 54 | this.interval = interval; 55 | } 56 | 57 | public String getUrl() { 58 | return url; 59 | } 60 | 61 | public void setUrl(String url) { 62 | this.url = url; 63 | } 64 | 65 | public String getRequestBody() { 66 | return requestBody; 67 | } 68 | 69 | public void setRequestBody(String requestBody) { 70 | this.requestBody = requestBody; 71 | } 72 | 73 | public int getRequestBodyLength() { 74 | return requestBodyLength; 75 | } 76 | 77 | public void setRequestBodyLength(int requestBodyLength) { 78 | this.requestBodyLength = requestBodyLength; 79 | } 80 | 81 | public String getResponse() { 82 | return response; 83 | } 84 | 85 | public void setResponse(String response) { 86 | this.response = response; 87 | } 88 | 89 | public String getResponseLength() { 90 | return responseLength; 91 | } 92 | 93 | public void setResponseLength(String responseLength) { 94 | this.responseLength = responseLength; 95 | } 96 | 97 | public boolean isSuccessful() { 98 | return successful; 99 | } 100 | 101 | public void setSuccessful(boolean successful) { 102 | this.successful = successful; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/model/request/AuthRequest.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.model.request; 2 | 3 | public class AuthRequest { 4 | private int status; 5 | private String token; 6 | private String errMsg; 7 | 8 | public int getStatus() { 9 | return status; 10 | } 11 | 12 | public void setStatus(int status) { 13 | this.status = status; 14 | } 15 | 16 | public String getToken() { 17 | return token; 18 | } 19 | 20 | public void setToken(String token) { 21 | this.token = token; 22 | } 23 | 24 | public String getErrMsg() { 25 | return errMsg; 26 | } 27 | 28 | public void setErrMsg(String errMsg) { 29 | this.errMsg = errMsg; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/model/request/LoginVO.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.model.request; 2 | 3 | public class LoginVO { 4 | private String username; 5 | private String password; 6 | 7 | public String getUsername() { 8 | return username; 9 | } 10 | 11 | public void setUsername(String username) { 12 | this.username = username; 13 | } 14 | 15 | public String getPassword() { 16 | return password; 17 | } 18 | 19 | public void setPassword(String password) { 20 | this.password = password; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/model/result/AuthResult.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.model.result; 2 | 3 | public class AuthResult extends BaseResult { 4 | private String token; 5 | private String errMsg; 6 | 7 | public String getToken() { 8 | return token; 9 | } 10 | 11 | public void setToken(String token) { 12 | this.token = token; 13 | } 14 | 15 | public String getErrMsg() { 16 | return errMsg; 17 | } 18 | 19 | public void setErrMsg(String errMsg) { 20 | this.errMsg = errMsg; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/model/result/BaseResult.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.model.result; 2 | 3 | import com.cml.springcloud.constant.ApiServiceContanst; 4 | 5 | public class BaseResult { 6 | private int status; 7 | private String errMsg; 8 | 9 | public int getStatus() { 10 | return status; 11 | } 12 | 13 | public void setStatus(int status) { 14 | this.status = status; 15 | } 16 | 17 | public String getErrMsg() { 18 | return errMsg; 19 | } 20 | 21 | public void setErrMsg(String errMsg) { 22 | this.errMsg = errMsg; 23 | } 24 | 25 | public boolean isSuccess() { 26 | return status == ApiServiceContanst.ResultCode.RESULT_OK; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/model/result/LoginResult.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.model.result; 2 | 3 | public class LoginResult extends BaseResult { 4 | private String token; 5 | 6 | public String getToken() { 7 | return token; 8 | } 9 | 10 | public void setToken(String token) { 11 | this.token = token; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/model/result/UserResult.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.model.result; 2 | 3 | public class UserResult extends BaseResult { 4 | private String username; 5 | private String nickname; 6 | 7 | public String getUsername() { 8 | return username; 9 | } 10 | 11 | public void setUsername(String username) { 12 | this.username = username; 13 | } 14 | 15 | public String getNickname() { 16 | return nickname; 17 | } 18 | 19 | public void setNickname(String nickname) { 20 | this.nickname = nickname; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/com/cml/springcloud/util/ApplicationUtil.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class ApplicationUtil { 10 | 11 | private static ApplicationContext applicationContext; 12 | 13 | @Autowired 14 | public void setApplicationContext(ApplicationContext applicationContext) { 15 | ApplicationUtil.applicationContext = applicationContext; 16 | } 17 | 18 | /** 19 | * 获取环境 20 | *

21 | * 获取不到环境配置的情况下,默认是DEV环境 22 | * 23 | * @return env 24 | */ 25 | public static String getEnv() { 26 | String env = System.getProperty("spring.profiles.active"); 27 | return StringUtils.defaultIfBlank(env, "local").toLowerCase(); 28 | } 29 | 30 | public static String getApplicationName() { 31 | String name = applicationContext.getEnvironment().getProperty("spring.application.name"); 32 | return StringUtils.defaultIfBlank(name, "none").toLowerCase(); 33 | } 34 | } -------------------------------------------------------------------------------- /common/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | system.config.error.message=\u5F53\u524D\u7CFB\u7EDF\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\uFF01 2 | system.config.error.invalidToken=\u65E0\u6548\u7684token 3 | system.config.accessTokenFilter.ignore=/user/login 4 | 5 | #auth config 6 | system.config.authFilter.authUrl=/user/login 7 | system.config.authFilter.tokenKey=token 8 | 9 | #about auth 10 | system.auth.jwtKey=d1465f91-8bf1-42c1-9e58-4d3e01fd7d2c 11 | system.auth.validTime=3600000 -------------------------------------------------------------------------------- /config-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /config-server/README.MD: -------------------------------------------------------------------------------- 1 | # eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ 3 | # 获取订单 4 | http://192.168.1.183:8762/test?user=333 5 | # 获取用户信息 6 | http://192.168.1.183:8763/test?user=test 7 | 8 | # 查看配置中心是否成功 9 | http://localhost:8761/${文件名}.properties -------------------------------------------------------------------------------- /config-server/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | config-server 6 | 1.0 7 | 8 | config-server 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-web 21 | 22 | 23 | de.codecentric 24 | spring-boot-admin-starter-client 25 | 26 | 27 | org.springframework.cloud 28 | spring-cloud-config-server 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | test 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-maven-plugin 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /config-server/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD config-server-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /config-server/src/main/java/com/cml/springcloud/ConfigServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.config.server.EnableConfigServer; 6 | 7 | @EnableConfigServer 8 | @SpringBootApplication 9 | public class ConfigServerApplication { 10 | public static void main(String[] args) { 11 | new SpringApplicationBuilder(ConfigServerApplication.class).web(true).run(args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /config-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=config-server 2 | server.port=9000 3 | 4 | #use local file ignore git 5 | spring.profiles.active=native 6 | #scan local file 7 | spring.cloud.config.server.native.searchLocations=classpath:/config 8 | 9 | 10 | spring.boot.admin.client.url=http://localhost:8600 11 | management.security.enabled=false 12 | management.endpoints.web.exposure.include=* 13 | management.endpoints.health.show-details=ALWAYS 14 | management.endpoint.heapdump.enabled=false 15 | management.endpoint.threaddump.enabled=false 16 | management.health.db.enabled=false 17 | #use git as configcenter 18 | #spring.cloud.config.server.git.uri=https://gitee.com/cmlbeliever/springcloud.git 19 | #spring.cloud.config.server.git.searchPaths=Config/config 20 | #spring.cloud.config.label=master 21 | #spring.cloud.config.server.git.username= your username 22 | #spring.cloud.config.server.git.password= your password -------------------------------------------------------------------------------- /config-server/src/main/resources/config/admin-metrics-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8600 2 | 3 | -------------------------------------------------------------------------------- /config-server/src/main/resources/config/api-gateway-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=7000 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 3 | 4 | 5 | zuul.routes.user-api.path=/user/* 6 | zuul.routes.user-api.serviceId=USER-SERVICE 7 | 8 | zuul.routes.order-api.path=/order/* 9 | zuul.routes.order-api.serviceId=ORDER-SERVICE -------------------------------------------------------------------------------- /config-server/src/main/resources/config/auth-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8400 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /config-server/src/main/resources/config/eureka-server-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8761 2 | eureka.client.serviceUrl.defaultZone=http://127.0.0.1:${server.port}/eureka/ -------------------------------------------------------------------------------- /config-server/src/main/resources/config/order-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8100 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 3 | system.order.serverName=Order Service modified -------------------------------------------------------------------------------- /config-server/src/main/resources/config/token-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8500 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /config-server/src/main/resources/config/user-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8300 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /config-server/src/main/resources/config/user-service-mq-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8301 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /config-server/src/main/resources/config/user-service-pro.properties: -------------------------------------------------------------------------------- 1 | server.port=8301 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /config-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | ${APP_NAME} 11 | 12 | 13 | 14 | 15 | ${ENCODER_PATTERN} 16 | 17 | 18 | 19 | 20 | 22 | 23 | ${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.log 24 | 25 | 26 | 27 | ${ENCODER_PATTERN} 28 | 29 | 30 | 31 | 32 | 34 | 35 | ${LOG_HOME}/${APP_NAME}-error.%d{yyyy-MM-dd}.log 36 | 37 | 38 | 39 | ${ENCODER_PATTERN} 40 | 41 | 42 | ERROR 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /config/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /config/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /config/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | config-center 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /config/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /config/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 3 | org.eclipse.jdt.core.compiler.compliance=1.5 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.5 6 | -------------------------------------------------------------------------------- /config/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /config/config/api-getway-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=7000 2 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 3 | 4 | zuul.routes.user-api.path=/user/* 5 | zuul.routes.user-api.serviceId=USER-SERVICE 6 | 7 | zuul.routes.order-api.path=/order/* 8 | zuul.routes.order-api.serviceId=ORDER-SERVICE -------------------------------------------------------------------------------- /config/config/auth-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8400 -------------------------------------------------------------------------------- /config/config/eureka-server-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8000 -------------------------------------------------------------------------------- /config/config/order-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8100 -------------------------------------------------------------------------------- /config/config/user-service-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8300 -------------------------------------------------------------------------------- /config/deploy/deploy-config.bat: -------------------------------------------------------------------------------- 1 | 2 | cd D:\gitrepository\springcloud\ 3 | cd ConfigServer 4 | mvn spring-boot:run -------------------------------------------------------------------------------- /config/deploy/deploy-eureka-server.bat: -------------------------------------------------------------------------------- 1 | 2 | cd D:\gitrepository\springcloud\ 3 | cd EurekaServer 4 | mvn spring-boot:run -------------------------------------------------------------------------------- /config/deploy/deploy-order.bat: -------------------------------------------------------------------------------- 1 | 2 | cd D:\gitrepository\springcloud\ 3 | cd UserService 4 | mvn spring-boot:run -------------------------------------------------------------------------------- /config/deploy/deploy-user-service.bat: -------------------------------------------------------------------------------- 1 | 2 | cd D:\gitrepository\springcloud\ 3 | cd EurekaClient 4 | mvn spring-boot:run -------------------------------------------------------------------------------- /config/deploy/deploy-zuul.bat: -------------------------------------------------------------------------------- 1 | 2 | cd D:\gitrepository\springcloud\ 3 | cd BuissnessApi 4 | mvn spring-boot:run -------------------------------------------------------------------------------- /config/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | config-center 6 | 1.0 7 | 8 | UTF-8 9 | UTF-8 10 | 1.8 11 | 12 | 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-maven-plugin 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /eureka-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /eureka-server/README.MD: -------------------------------------------------------------------------------- 1 | # eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ 3 | # 获取订单 4 | http://192.168.1.183:8762/test?user=333 5 | # 获取用户信息 6 | http://192.168.1.183:8763/test?user=test 7 | 8 | # 查看配置中心是否成功 9 | http://localhost:8761/${文件名}.properties -------------------------------------------------------------------------------- /eureka-server/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | eureka-server 6 | 1.0 7 | 8 | eureka-server 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-netflix-eureka-server 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-test 28 | test 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /eureka-server/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD eureka-server-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /eureka-server/src/main/java/com/cml/springcloud/EurakeServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @EnableEurekaServer 8 | @SpringBootApplication 9 | public class EurakeServerApplication { 10 | public static void main(String[] args) { 11 | new SpringApplicationBuilder(EurakeServerApplication.class).web(true).run(args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /eureka-server/src/main/java/com/cml/springcloud/ServerTest.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.beans.factory.InitializingBean; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class ServerTest implements InitializingBean { 9 | 10 | @Value("${test.application:none}") 11 | private String testValue; 12 | 13 | @Value("${server.port}") 14 | private String port; 15 | 16 | @Override 17 | public void afterPropertiesSet() throws Exception { 18 | System.out.println("==================>" + testValue + "," + port); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /eureka-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | #eureka.client.serviceUrl.defaultZone=http://127.0.0.1:${server.port}/eureka/ -------------------------------------------------------------------------------- /eureka-server/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=eureka-server 2 | spring.profiles.active=dev 3 | eureka.client.registerWithEureka=false 4 | eureka.client.fetchRegistry=false 5 | eureka.server.enable-self-preservation=false 6 | server.port=8761 7 | #启用主动失效,并且每次主动失效检测间隔为3s 8 | eureka.server.eviction-interval-timer-in-ms=30000 9 | #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 10 | #默认30s 11 | eureka.server.responseCacheUpdateInvervalMs=30000 12 | #eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。 13 | #由于启用了evict其实就用不太上改这个配置了 14 | #默认180s 15 | eureka.server.responseCacheAutoExpirationInSeconds=180 16 | eureka.server.peer-eureka-nodes-update-interval-ms=30 17 | #服务刷新时间配置,每隔这个时间会主动心跳一次 18 | #默认30s 19 | eureka.instance.lease-renewal-interval-in-seconds=5 20 | #spring.cloud.config.uri=http://localhost:9000 21 | 22 | management.security.enabled=false 23 | management.endpoint.heapdump.enabled=false 24 | management.endpoint.threaddump.enabled=false 25 | management.health.db.enabled=false 26 | -------------------------------------------------------------------------------- /mq-service/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /mq-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /mq-service/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | user-service 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /mq-service/README.MD: -------------------------------------------------------------------------------- 1 | #mqservice 2 | -------------------------------------------------------------------------------- /mq-service/src/main/java/com/cml/springcloud/KafkaApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import com.cml.springcloud.kafka.Stream; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.cloud.stream.annotation.EnableBinding; 9 | import org.springframework.cloud.stream.annotation.StreamListener; 10 | import org.springframework.cloud.stream.messaging.Sink; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.messaging.support.MessageBuilder; 13 | 14 | //@EnableFeignClients 15 | //@EnableDiscoveryClient 16 | @SpringBootApplication() 17 | @EnableBinding({Stream.class, Sink.class}) 18 | public class KafkaApplication { 19 | public static void main(String[] args) { 20 | SpringApplication.run(KafkaApplication.class, args); 21 | } 22 | 23 | @Autowired 24 | private Stream stream; 25 | 26 | @Bean 27 | public ApplicationRunner runner() { 28 | return (args) -> { 29 | stream.send().send(MessageBuilder.withPayload("2134567890").build()); 30 | }; 31 | } 32 | 33 | @StreamListener(Stream.channel) 34 | public void handle(String message) { 35 | System.out.println("receiveMessage==>" + message); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /mq-service/src/main/java/com/cml/springcloud/domain/Person.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.domain; 2 | 3 | public class Person { 4 | private String name; 5 | 6 | public String getName() { 7 | return name; 8 | } 9 | 10 | public void setName(String name) { 11 | this.name = name; 12 | } 13 | 14 | public String toString() { 15 | return this.name; 16 | } 17 | } -------------------------------------------------------------------------------- /mq-service/src/main/java/com/cml/springcloud/kafka/Stream.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.kafka; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface Stream { 9 | String channel = "myChannel"; 10 | 11 | @Input(channel) 12 | SubscribableChannel subscribe(); 13 | 14 | @Output(channel) 15 | MessageChannel send(); 16 | } 17 | -------------------------------------------------------------------------------- /mq-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=mq-service 3 | 4 | spring.cloud.stream.bindings.myChannel.destination=mqTestDefault 5 | spring.cloud.stream.bindings.myChannel.contentType=text/plain 6 | 7 | 8 | #eureka\u914d\u7f6e 9 | #eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 10 | 11 | #config center 12 | #spring.cloud.config.label=master 13 | #spring.cloud.config.profile=dev 14 | #spring.cloud.config.uri=http://localhost:9000/ 15 | # 16 | 17 | 18 | spring.cloud.stream.kafka.binder.brokers=localhost 19 | spring.cloud.stream.kafka.binder.defaultBrokerPort=9092 20 | 21 | spring.cloud.stream.kafka.binder.zkNodes=192.168.99.100 22 | spring.cloud.stream.kafka.binder.defaultZkPort=2181 23 | #Default: 10000. 24 | spring.cloud.stream.kafka.binder.offsetUpdateTimeWindow=1000 25 | spring.cloud.stream.kafka.binder.offsetUpdateCount=0 26 | spring.cloud.stream.kafka.binder.requiredAcks=1 27 | spring.cloud.stream.kafka.binder.minPartitionCount=1 28 | #The replication factor of auto-created topics if autoCreateTopics is active. Default: 1. 29 | spring.cloud.stream.kafka.binder.replicationFactor=1 30 | spring.cloud.stream.kafka.binder.autoCreateTopics=true 31 | spring.cloud.stream.kafka.binder.autoAddPartitions=true 32 | #spring.cloud.stream.kafka.binder.socketBufferSize 33 | #spring.cloud.stream.kafka.binder.configuration= 34 | #spring.cloud.stream.kafka.binder.headers 35 | 36 | #----------consumer config------ 37 | spring.cloud.stream.kafka.bindings.mychannel.consumer.autoRebalanceEnabled=true 38 | spring.cloud.stream.kafka.bindings.mychannel.consumer.autoCommitOffset=true 39 | #spring.cloud.stream.kafka.bindings.mychannel.consumer. 40 | #spring.cloud.stream.kafka.bindings.mychannel.consumer. 41 | #spring.cloud.stream.kafka.bindings.mychannel.consumer. 42 | 43 | #kafka\u914d\u7f6e 44 | #spring.kafka.bootstrap-servers=localhost:9092 45 | #spring.kafka.consumer.group-id=testGroup2 46 | #spring.kafka.consumer.auto-offset-reset=earliest 47 | #spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer 48 | #spring.kafka.consumer.properties.spring.json.trusted.packages=com.cml.springboot.message 49 | #spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer 50 | # 51 | #spring.kafka.consumer.enable.auto.commit=true 52 | #spring.kafka.consumer.ack-mode=MANUAL 53 | # 54 | #spring.kafka.listener.enable.auto.commit=true 55 | #spring.kafka.listener.ack-mode=MANUAL 56 | -------------------------------------------------------------------------------- /order-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /order-service/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | order-service 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /order-service/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ -------------------------------------------------------------------------------- /order-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | order-service 6 | 1.0 7 | 8 | order-service 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | de.codecentric 20 | spring-boot-admin-starter-client 21 | 22 | 23 | org.springframework.cloud 24 | spring-cloud-starter-netflix-eureka-client 25 | 26 | 27 | org.springframework.cloud 28 | spring-cloud-starter-config 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-actuator 33 | 34 | 35 | org.springframework.cloud 36 | spring-cloud-starter-openfeign 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-security 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-maven-plugin 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /order-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD order-service-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /order-service/src/main/java/com/cml/springcloud/DemoController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import com.netflix.discovery.EurekaClient; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.cloud.client.discovery.DiscoveryClient; 7 | import org.springframework.cloud.context.config.annotation.RefreshScope; 8 | import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient; 9 | import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration; 10 | import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.ResponseBody; 15 | 16 | import com.cml.springcloud.api.UserApi; 17 | 18 | import java.lang.reflect.InvocationTargetException; 19 | import java.lang.reflect.Method; 20 | import java.util.concurrent.atomic.AtomicLong; 21 | 22 | @RefreshScope 23 | @Controller 24 | @RequestMapping("/") 25 | public class DemoController { 26 | 27 | @Value("${server.port}") 28 | private String port; 29 | 30 | @Value("${spring.application.name}") 31 | private String sererName; 32 | 33 | @Value("${system.order.serverName}") 34 | private String serverName; 35 | 36 | @Autowired 37 | private DiscoveryClient client; 38 | 39 | @Autowired 40 | private EurekaClient eurekaClient; 41 | 42 | @Autowired 43 | private UserApi userApi; 44 | 45 | @Autowired 46 | private EurekaAutoServiceRegistration eurekaAutoServiceRegistration; 47 | 48 | @ResponseBody 49 | @RequestMapping("/test") 50 | public String test(String user) { 51 | return "port:" + port + ",serverName:" + sererName + ",getUser info ==>" + userApi.getUser(user); 52 | } 53 | 54 | private AtomicLong counter = new AtomicLong(1); 55 | 56 | /** 57 | * 每次請求計數器加一,当请求的次数不为3的倍数时,休眠2.1s返回 58 | * 59 | * @return 60 | * @throws InterruptedException 61 | */ 62 | @ResponseBody 63 | @RequestMapping("/testRetry") 64 | public String testRetry() throws InterruptedException { 65 | if (counter.incrementAndGet() % 3 != 0) { 66 | Thread.sleep(2100); 67 | } 68 | return "port:" + port; 69 | } 70 | 71 | @ResponseBody 72 | @RequestMapping("/infoTest") 73 | public Object info() { 74 | return client.getServices() + ",serverName:" + serverName; 75 | } 76 | 77 | @ResponseBody 78 | @RequestMapping("/info2") 79 | public Object info2() { 80 | return client.getServices(); 81 | } 82 | 83 | @ResponseBody 84 | @RequestMapping("/hello") 85 | public String sayHello(String req) { 86 | return "req:" + req + ",from : port:" + port + ",serverName:" + sererName; 87 | } 88 | 89 | @RequestMapping("/order") 90 | @ResponseBody 91 | public String getOrder(String user) throws InterruptedException { 92 | return "Get user[ " + user + "] order from port:" + port + ",serverName:" + sererName; 93 | } 94 | 95 | @ResponseBody 96 | @GetMapping("/eurekaUnRegister") 97 | public String shutDown() { 98 | eurekaClient.shutdown(); 99 | return "eurekaUnRegistering"; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /order-service/src/main/java/com/cml/springcloud/OrderServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 | import org.springframework.cloud.openfeign.EnableFeignClients; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 10 | 11 | @EnableFeignClients 12 | @EnableEurekaClient 13 | @SpringBootApplication 14 | public class OrderServiceApplication { 15 | public static void main(String[] args) { 16 | new SpringApplicationBuilder(OrderServiceApplication.class).web(true).run(args); 17 | } 18 | @Configuration 19 | public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { 20 | @Override 21 | protected void configure(HttpSecurity http) throws Exception { 22 | http.authorizeRequests().anyRequest().permitAll() 23 | .and().csrf().disable(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /order-service/src/main/java/com/cml/springcloud/api/UserApi.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | 7 | @FeignClient("USER-SERVICE") 8 | public interface UserApi { 9 | 10 | @RequestMapping(value = "/getUser") 11 | String getUser(@RequestParam("user") String user); 12 | } 13 | -------------------------------------------------------------------------------- /order-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=order-service 3 | system.order.serverName=order-service 4 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 5 | eureka.instance.leaseRenewalIntervalInSeconds=5 6 | eureka.client.registryFetchIntervalSeconds=5 7 | eureka.instance.lease-expiration-duration-in-seconds=5 8 | eureka.instance.prefer-ip-address=true 9 | eureka.instance.lease-renewal-interval-in-seconds=5 10 | 11 | #spring.boot.admin.client.url=http://localhost:8600 12 | management.security.enabled=false 13 | management.endpoints.web.exposure.include=* 14 | management.endpoints.health.show-details=ALWAYS 15 | management.endpoint.shutdown.enabled=true 16 | 17 | 18 | #config center 19 | spring.cloud.config.label=master 20 | spring.cloud.config.profile=dev 21 | spring.cloud.config.uri=http://localhost:9000/ 22 | 23 | #bus config 24 | ## \u5237\u65b0\u65f6\uff0c\u5173\u95ed\u5b89\u5168\u9a8c\u8bc1 25 | #management.security.enabled=false 26 | ## \u5f00\u542f\u6d88\u606f\u8ddf\u8e2a 27 | #spring.cloud.bus.trace.enabled=false 28 | 29 | #spring.rabbitmq.host=192.168.99.100 30 | #spring.rabbitmq.port=5672 31 | #spring.rabbitmq.username=guest 32 | #spring.rabbitmq.password=guest -------------------------------------------------------------------------------- /springcloud-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cml.learn 8 | springcloud-gateway 9 | 1.0-SNAPSHOT 10 | jar 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.2.RELEASE 16 | 17 | 18 | 19 | 20 | UTF-8 21 | UTF-8 22 | 1.8 23 | Finchley.RC2 24 | 25 | 26 | 27 | 28 | 29 | org.springframework.cloud 30 | spring-cloud-dependencies 31 | ${spring-cloud.version} 32 | pom 33 | import 34 | 35 | 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-actuator 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-webflux 46 | 47 | 48 | org.springframework.cloud 49 | spring-cloud-starter-gateway 50 | 51 | 52 | org.springframework.cloud 53 | spring-cloud-starter-netflix-ribbon 54 | 55 | 56 | org.springframework.cloud 57 | spring-cloud-starter-netflix-eureka-client 58 | 59 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-test 67 | test 68 | 69 | 70 | io.projectreactor 71 | reactor-test 72 | test 73 | 74 | 75 | org.assertj 76 | assertj-core 77 | test 78 | 79 | 80 | 81 | 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-maven-plugin 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /springcloud-gateway/readme.MD: -------------------------------------------------------------------------------- 1 | # 项目使用说明 2 | 启动eureka-server,config-server,user-service后启动此项目,访问http://127.0.0.1:8801/user-gateway/user2/testGet?name=name 将请求转发的了user-service中,且新增了自定义参数extraParameter 3 | 4 | # metrics 5 | 6 | - http://localhost:8801/actuator/gateway/globalfilters 查看所有filter 7 | - http://localhost:8801/actuator/gateway/routefilters 8 | - http://localhost:8801/actuator/gateway/routes 所有的路由 9 | - -------------------------------------------------------------------------------- /springcloud-gateway/src/main/java/com/cml/learn/springcloud/gateway/CustomFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.learn.springcloud.gateway; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.cloud.gateway.filter.GlobalFilter; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.annotation.Order; 9 | import reactor.core.publisher.Mono; 10 | 11 | /** 12 | * @Auther: cml 13 | * @Date: 2019-01-31 13:57 14 | * @Description: 15 | */ 16 | @Configuration 17 | public class CustomFilter { 18 | private Logger logger = LoggerFactory.getLogger(getClass()); 19 | 20 | @Bean 21 | @Order(-1) 22 | public GlobalFilter requestLogFilter() { 23 | return (exchange, chain) -> { 24 | logger.info("first pre filter:" + exchange.getRequest().getURI()); 25 | return chain.filter(exchange).then(Mono.fromRunnable(() -> { 26 | logger.info("third post filter finish"); 27 | })); 28 | }; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /springcloud-gateway/src/main/java/com/cml/learn/springcloud/gateway/ErrorHandler.java: -------------------------------------------------------------------------------- 1 | package com.cml.learn.springcloud.gateway; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.reactive.function.server.ServerResponse; 7 | import reactor.core.publisher.Mono; 8 | 9 | /** 10 | * @Auther: cml 11 | * @Date: 2019-01-31 14:23 12 | * @Description: 13 | */ 14 | @Component 15 | public class ErrorHandler { 16 | 17 | @ExceptionHandler(Throwable.class) 18 | public Mono onError(Throwable throwable) { 19 | ServerResponse serverResponse = ServerResponse.badRequest().body(t -> { 20 | t.onNext("出错啦" + throwable.getMessage()); 21 | t.onComplete(); 22 | }, String.class).block(); 23 | return Mono.just(serverResponse); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /springcloud-gateway/src/main/java/com/cml/learn/springcloud/gateway/SpringCloudGatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.learn.springcloud.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository; 7 | import org.springframework.cloud.gateway.route.RouteDefinitionWriter; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | @EnableDiscoveryClient 11 | @SpringBootApplication 12 | public class SpringCloudGatewayApplication { 13 | public static void main(String[] args) { 14 | SpringApplication.run(SpringCloudGatewayApplication.class, args); 15 | } 16 | 17 | // @Bean 18 | // public RouteDefinitionWriter routeDefinitionWriter() { 19 | // return new InMemoryRouteDefinitionRepository(); 20 | // } 21 | } 22 | -------------------------------------------------------------------------------- /springcloud-gateway/src/main/java/com/cml/learn/springcloud/gateway/controller/CustomRouteController.java: -------------------------------------------------------------------------------- 1 | package com.cml.learn.springcloud.gateway.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.cloud.gateway.event.RefreshRoutesEvent; 5 | import org.springframework.cloud.gateway.filter.FilterDefinition; 6 | import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; 7 | import org.springframework.cloud.gateway.route.RouteDefinition; 8 | import org.springframework.cloud.gateway.route.RouteDefinitionWriter; 9 | import org.springframework.context.ApplicationEventPublisher; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import reactor.core.publisher.Mono; 14 | 15 | import java.net.URI; 16 | import java.util.Arrays; 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | 20 | @RestController 21 | @RequestMapping("/route/def") 22 | public class CustomRouteController { 23 | 24 | @Autowired 25 | private ApplicationEventPublisher applicationEventPublisher; 26 | @Autowired 27 | private RouteDefinitionWriter routeDefinitionWriter; 28 | 29 | @RequestMapping("/addRoute") 30 | public String addRoute(@RequestParam String routeName) { 31 | RouteDefinition routeDefinition = new RouteDefinition(); 32 | routeDefinition.setId(routeName); 33 | routeDefinition.setUri(URI.create("lb://USER-SERVICE")); 34 | 35 | PredicateDefinition predicateDefinition = new PredicateDefinition(); 36 | predicateDefinition.setName("Path"); 37 | predicateDefinition.addArg("pattern", "/user-gateway2/*"); 38 | 39 | routeDefinition.setPredicates(Arrays.asList(predicateDefinition)); 40 | 41 | // FilterDefinition filterDefinition = new FilterDefinition(); 42 | // filterDefinition.setName("AddRequestParameter"); 43 | // Map args = new HashMap(); 44 | // args.put("_genkey_0", "customArg"); 45 | // args.put("_genkey_1", "xxxx" + System.currentTimeMillis()); 46 | // filterDefinition.setArgs(args); 47 | // routeDefinition.setFilters(Arrays.asList(filterDefinition)); 48 | 49 | routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe(); 50 | 51 | applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this)); 52 | 53 | return "新增成功"; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /springcloud-gateway/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | management: 2 | endpoint: 3 | gateway: 4 | enabled: true 5 | heapdump: 6 | enabled: false 7 | shutdown: 8 | enabled: true 9 | threaddump: 10 | enabled: false 11 | endpoints: 12 | health: 13 | show-details: ALWAYS 14 | web: 15 | exposure: 16 | include: '*' 17 | 18 | server: 19 | port: 8801 20 | 21 | eureka: 22 | client: 23 | service-url: 24 | - http://localhost:8761/eureka/ 25 | instance: 26 | ip-address: 127.0.0.1 27 | non-secure-port: 8801 28 | spring: 29 | application: 30 | name: springcloud-gateway 31 | cloud: 32 | gateway: 33 | metrics: 34 | enabled: true 35 | filter: 36 | remove-non-proxy-headers: #去除默认的header https://cloud.spring.io/spring-cloud-gateway/single/spring-cloud-gateway.html#gateway-starter 37 | headers: 38 | - Connection 39 | - Keep-Alive 40 | - Proxy-Authenticate 41 | routes: 42 | - id: cookie_route 43 | uri: lb://USER-SERVICE 44 | predicates: 45 | - Path=/user-gateway/** 46 | filters: 47 | - StripPrefix=1 #去除user-gateway这一层数据 48 | - AddRequestHeader=from-gateway,Yes${server.port} 49 | - AddRequestParameter=extraParameter, defaultValue 50 | - AddResponseHeader=X-Response-Foo, springcloud-gateway 51 | - PreserveHostHeader 52 | # - RedirectTo=302, http://acme.org 重定向 53 | # - id: host_route 54 | # uri: http://example.org 55 | # predicates: 56 | # - Path=/foo/{segment},/bar/{segment} -------------------------------------------------------------------------------- /token-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /token-service/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | user-service 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /token-service/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | token服务,保障redi队列中的token数量 -------------------------------------------------------------------------------- /token-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | token-service 6 | 1.0 7 | 8 | token-service 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-security 22 | 23 | 24 | de.codecentric 25 | spring-boot-admin-starter-client 26 | 27 | 28 | 29 | org.redisson 30 | redisson 31 | 3.6.4 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-netflix-eureka-client 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-openfeign 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-config 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-maven-plugin 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /token-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD token-service-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/TokenServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 | 10 | //@EnableScheduling 11 | @EnableDiscoveryClient 12 | @SpringBootApplication 13 | public class TokenServiceApplication { 14 | public static void main(String[] args) { 15 | new SpringApplicationBuilder(TokenServiceApplication.class).web(true).run(args); 16 | } 17 | @Configuration 18 | public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { 19 | @Override 20 | protected void configure(HttpSecurity http) throws Exception { 21 | http.authorizeRequests().anyRequest().permitAll() 22 | .and().csrf().disable(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/configuration/RedissonAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.configuration; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.redisson.Redisson; 5 | import org.redisson.api.RedissonClient; 6 | import org.redisson.config.Config; 7 | import org.redisson.config.SentinelServersConfig; 8 | import org.redisson.config.SingleServerConfig; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 11 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 12 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 13 | import org.springframework.context.annotation.Bean; 14 | import org.springframework.context.annotation.Configuration; 15 | import org.springframework.context.annotation.Primary; 16 | 17 | @Configuration 18 | @ConditionalOnClass(Config.class) 19 | @EnableConfigurationProperties(RedissonProperties.class) 20 | public class RedissonAutoConfiguration { 21 | 22 | @Autowired 23 | private RedissonProperties redssionProperties; 24 | 25 | /** 26 | * 哨兵模式自动装配 27 | * @return 28 | */ 29 | @Bean 30 | @ConditionalOnProperty(name="redisson.master-name") 31 | RedissonClient redissonSentinel() { 32 | Config config = new Config(); 33 | SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redssionProperties.getSentinelAddresses()) 34 | .setMasterName(redssionProperties.getMasterName()) 35 | .setTimeout(redssionProperties.getTimeout()) 36 | .setMasterConnectionPoolSize(redssionProperties.getMasterConnectionPoolSize()) 37 | .setSlaveConnectionPoolSize(redssionProperties.getSlaveConnectionPoolSize()); 38 | 39 | if(StringUtils.isNotBlank(redssionProperties.getPassword())) { 40 | serverConfig.setPassword(redssionProperties.getPassword()); 41 | } 42 | return Redisson.create(config); 43 | } 44 | 45 | /** 46 | * 单机模式自动装配 47 | * @return 48 | */ 49 | @Bean 50 | @ConditionalOnProperty(name="redisson.address") 51 | @Primary 52 | RedissonClient redissonSingle() { 53 | Config config = new Config(); 54 | SingleServerConfig serverConfig = config.useSingleServer() 55 | .setAddress(redssionProperties.getAddress()) 56 | .setTimeout(redssionProperties.getTimeout()) 57 | .setConnectionPoolSize(redssionProperties.getConnectionPoolSize()) 58 | .setConnectionMinimumIdleSize(redssionProperties.getConnectionMinimumIdleSize()); 59 | 60 | if(StringUtils.isNotBlank(redssionProperties.getPassword())) { 61 | serverConfig.setPassword(redssionProperties.getPassword()); 62 | } 63 | 64 | return Redisson.create(config); 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/configuration/RedissonProperties.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.configuration; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "redisson") 6 | public class RedissonProperties { 7 | 8 | private int timeout = 3000; 9 | 10 | private String address; 11 | 12 | private String password; 13 | 14 | private int connectionPoolSize = 64; 15 | 16 | private int connectionMinimumIdleSize = 10; 17 | 18 | private int slaveConnectionPoolSize = 250; 19 | 20 | private int masterConnectionPoolSize = 250; 21 | 22 | private String[] sentinelAddresses; 23 | 24 | private String masterName; 25 | 26 | public int getTimeout() { 27 | return timeout; 28 | } 29 | 30 | public void setTimeout(int timeout) { 31 | this.timeout = timeout; 32 | } 33 | 34 | public int getSlaveConnectionPoolSize() { 35 | return slaveConnectionPoolSize; 36 | } 37 | 38 | public void setSlaveConnectionPoolSize(int slaveConnectionPoolSize) { 39 | this.slaveConnectionPoolSize = slaveConnectionPoolSize; 40 | } 41 | 42 | public int getMasterConnectionPoolSize() { 43 | return masterConnectionPoolSize; 44 | } 45 | 46 | public void setMasterConnectionPoolSize(int masterConnectionPoolSize) { 47 | this.masterConnectionPoolSize = masterConnectionPoolSize; 48 | } 49 | 50 | public String[] getSentinelAddresses() { 51 | return sentinelAddresses; 52 | } 53 | 54 | public void setSentinelAddresses(String sentinelAddresses) { 55 | this.sentinelAddresses = sentinelAddresses.split(","); 56 | } 57 | 58 | public String getMasterName() { 59 | return masterName; 60 | } 61 | 62 | public void setMasterName(String masterName) { 63 | this.masterName = masterName; 64 | } 65 | 66 | public String getPassword() { 67 | return password; 68 | } 69 | 70 | public void setPassword(String password) { 71 | this.password = password; 72 | } 73 | 74 | public String getAddress() { 75 | return address; 76 | } 77 | 78 | public void setAddress(String address) { 79 | this.address = address; 80 | } 81 | 82 | public int getConnectionPoolSize() { 83 | return connectionPoolSize; 84 | } 85 | 86 | public void setConnectionPoolSize(int connectionPoolSize) { 87 | this.connectionPoolSize = connectionPoolSize; 88 | } 89 | 90 | public int getConnectionMinimumIdleSize() { 91 | return connectionMinimumIdleSize; 92 | } 93 | 94 | public void setConnectionMinimumIdleSize(int connectionMinimumIdleSize) { 95 | this.connectionMinimumIdleSize = connectionMinimumIdleSize; 96 | } 97 | } -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/controller/TokenController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import com.cml.springcloud.service.TokenService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.cloud.client.discovery.DiscoveryClient; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | 11 | 12 | @Controller 13 | @RequestMapping("/") 14 | public class TokenController { 15 | 16 | @Value("${spring.application.name:test}") 17 | private String port; 18 | @Value("${server.port:555}") 19 | private String sererName; 20 | 21 | @Autowired 22 | private DiscoveryClient client; 23 | 24 | @Autowired 25 | private TokenService tokenService; 26 | 27 | 28 | @ResponseBody 29 | @RequestMapping("/info") 30 | public Object info() { 31 | return client.getServices(); 32 | } 33 | 34 | @ResponseBody 35 | @RequestMapping("/getToken") 36 | public String getToken() { 37 | return tokenService.pop(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/quarz/TokenSentinelQuarz.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.quarz; 2 | 3 | import com.cml.springcloud.service.TokenService; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 8 | import org.springframework.scheduling.annotation.Scheduled; 9 | import org.springframework.stereotype.Component; 10 | 11 | /** 12 | * 保障token数量 13 | */ 14 | @ConditionalOnProperty(name = "sentinel.enable", havingValue = "true") 15 | @Component 16 | public class TokenSentinelQuarz { 17 | private Logger logger = LoggerFactory.getLogger(getClass()); 18 | 19 | @Autowired 20 | private TokenService tokenService; 21 | 22 | @Scheduled(fixedRate = 1000) 23 | public void sentinelTask() { 24 | tokenService.fillTokenList(); 25 | } 26 | 27 | // @Scheduled(fixedRate = 100) 28 | // public void sentinelTask2() { 29 | // logger.info("==========>sentinelTask2"); 30 | // RList rList = redissonClient.getList(redisTokenKey); 31 | // for (int i = 0; i < 1000; i++) { 32 | // String token = (String) rList.remove(0); 33 | // } 34 | // } 35 | } 36 | -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/service/TokenGeneratorService.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.service; 2 | 3 | public interface TokenGeneratorService { 4 | String generate(); 5 | } 6 | -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/service/TokenGeneratorServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.service; 2 | 3 | import com.cml.springcloud.util.SnowflakeIdWorker; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class TokenGeneratorServiceImpl implements TokenGeneratorService { 8 | 9 | private SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1); 10 | 11 | @Override 12 | public String generate() { 13 | return idWorker.nextId() + ""; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/service/TokenService.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.service; 2 | 3 | public interface TokenService { 4 | String pop(); 5 | 6 | void fillTokenList(); 7 | } 8 | -------------------------------------------------------------------------------- /token-service/src/main/java/com/cml/springcloud/service/TokenServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.service; 2 | 3 | import org.redisson.api.RList; 4 | import org.redisson.api.RedissonClient; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class TokenServiceImpl implements TokenService { 13 | 14 | private Logger logger = LoggerFactory.getLogger(getClass()); 15 | 16 | @Autowired 17 | private RedissonClient redissonClient; 18 | 19 | @Autowired 20 | private TokenGeneratorService tokenGeneratorService; 21 | 22 | @Value("${token.sentinel.key}") 23 | private String redisTokenKey; 24 | 25 | @Value("${token.sentinel.count}") 26 | private int tokenMaxCount; 27 | @Value("${token.sentinel.threshold}") 28 | private int tokenThresholdCount; 29 | 30 | 31 | @Override 32 | public String pop() { 33 | return (String) redissonClient.getList(redisTokenKey).remove(0); 34 | } 35 | 36 | @Override 37 | public void fillTokenList() { 38 | RList rList = redissonClient.getList(redisTokenKey); 39 | int realCount = rList.size(); 40 | 41 | logger.info("{}队列中数量为:{},需要:{}", redisTokenKey, realCount, tokenMaxCount); 42 | 43 | if (realCount < tokenThresholdCount) { 44 | long start = System.currentTimeMillis(); 45 | int needCount = tokenMaxCount - realCount; 46 | for (int i = 0; i < needCount; i++) { 47 | rList.add(tokenGeneratorService.generate()); 48 | } 49 | logger.info("本次生成token数量:{}耗时:{}ms", needCount, System.currentTimeMillis() - start); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /token-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/token-service/src/main/resources/bootstrap.properties -------------------------------------------------------------------------------- /user-service-mq/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /user-service-mq/README.MD: -------------------------------------------------------------------------------- 1 | #项目说明 2 | 在分布式系统中,调查问题的时候在需要到多台服务器上进行查看 Log,或者到数据库查询访问记录,不仅效率低而且不直观,那么有没有更好更轻松的方式呢? 3 | 4 | 基于 ELK 的 Log 查看系统可以非常高效的解决传统 Log 文件的弊端,下面介绍下系统中如何基于 ELK 对 Log 进行优雅的处理,优雅的调查问题和查看统计信息。 5 | 6 | 本场 Chat 将基于如下几个主题进行讲解: 7 | 8 | - 常用 Log 记录的方式的不足 9 | - 如何使用 Filebeat 进行 Log 收集? 10 | - 为什么不推荐使用 Filebeat? 11 | - 如何对所有请求进行记录? 12 | - 如何对所有对外请求的记录? 13 | - 如何记录任何需要的 Log,如何将 Log 埋点更方便调查问题? 14 | - ELK, Kafka 安装与使用。 15 | - 基于 Kibana Dashboard 直观查看 Log 信息,形成请求量,请求时长与埋点信息。 16 | 17 | 本场 Chat 将基于 SpringCloud 系统调用,详细讲解从一个请求到系统内部运转与对外接口调用的完整流程,提供完整可执行代码。 18 | 19 | 详情请看:https://gitbook.cn/gitchat/activity/5bcaf3f274594b3751235c1c -------------------------------------------------------------------------------- /user-service-mq/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | user-service-mq 6 | 1.0 7 | 8 | user-service-ma 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | org.springframework.cloud 20 | spring-cloud-stream 21 | 22 | 23 | org.springframework.cloud 24 | spring-cloud-starter-stream-kafka 25 | 26 | 30 | 31 | org.springframework.cloud 32 | spring-cloud-starter-netflix-eureka-client 33 | 34 | 35 | org.springframework.cloud 36 | spring-cloud-starter-config 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-actuator 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-openfeign 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-security 49 | 50 | 51 | spring-beans 52 | org.springframework 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-test 59 | test 60 | 61 | 62 | org.springframework.retry 63 | spring-retry 64 | 65 | 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-maven-plugin 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /user-service-mq/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD user-service-ma-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/UserMQClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import com.cml.springcloud.filter.ElkFilter; 4 | import com.cml.springcloud.kafka.Stream; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.boot.builder.SpringApplicationBuilder; 9 | import org.springframework.boot.web.servlet.ServletComponentScan; 10 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 11 | import org.springframework.cloud.openfeign.EnableFeignClients; 12 | import org.springframework.cloud.stream.annotation.EnableBinding; 13 | import org.springframework.context.ConfigurableApplicationContext; 14 | import org.springframework.context.annotation.Configuration; 15 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 16 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 17 | 18 | @EnableFeignClients() 19 | @EnableEurekaClient 20 | @SpringBootApplication() 21 | @EnableBinding(Stream.class) 22 | @ServletComponentScan(basePackageClasses = ElkFilter.class) 23 | public class UserMQClientApplication { 24 | static Logger logger = LoggerFactory.getLogger(UserMQClientApplication.class); 25 | 26 | private static final String CUSTOM_COUNTER = "xxl_my_counter"; 27 | 28 | public static void main(String[] args) { 29 | try { 30 | ConfigurableApplicationContext run = new SpringApplicationBuilder(UserMQClientApplication.class).web(true).run(args); 31 | 32 | } catch (Exception e) { 33 | logger.error("", e); 34 | } 35 | } 36 | 37 | // @Bean 38 | // public ApplicationRunner applicationRunner() { 39 | // return (arg) -> { 40 | // new Thread(() -> { 41 | // for (int i = 0; i < 10000; i++) { 42 | // Metrics.counter(CUSTOM_COUNTER, "test", "失败的次数").increment((int) (100 * Math.random())); 43 | // Metrics.counter(CUSTOM_COUNTER, "test2", "成功的次数").increment((int) (100 * Math.random())); 44 | // try { 45 | // Thread.sleep(1000); 46 | // } catch (InterruptedException e) { 47 | // e.printStackTrace(); 48 | // } 49 | // } 50 | // }).start(); 51 | // }; 52 | // } 53 | 54 | @Configuration 55 | public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { 56 | @Override 57 | protected void configure(HttpSecurity http) throws Exception { 58 | http.authorizeRequests().anyRequest().permitAll() 59 | .and().csrf().disable(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/api/OrderApi.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | 8 | @FeignClient("ORDER-SERVICE") 9 | public interface OrderApi { 10 | 11 | @RequestMapping(value = "/order") 12 | String getOrder(@RequestParam("user") String user); 13 | 14 | @RequestMapping(value = "/testRetry") 15 | String testRetry(); 16 | } 17 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import java.util.UUID; 4 | 5 | import com.netflix.discovery.DiscoveryClient; 6 | import com.netflix.discovery.DiscoveryManager; 7 | import com.netflix.discovery.EurekaClient; 8 | import org.apache.commons.lang.StringUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.ResponseBody; 17 | 18 | import com.cml.springcloud.constant.ApiServiceContanst; 19 | import com.cml.springcloud.model.request.LoginVO; 20 | import com.cml.springcloud.model.result.LoginResult; 21 | import com.cml.springcloud.model.result.UserResult; 22 | 23 | @Controller 24 | @RequestMapping("/") 25 | public class UserController { 26 | protected static Logger logger = LoggerFactory.getLogger(UserController.class); 27 | 28 | @Autowired 29 | private EurekaClient eurekaClient; 30 | 31 | @ResponseBody 32 | @GetMapping("/eurekaUnRegister") 33 | public String shutDown() { 34 | eurekaClient.shutdown(); 35 | return "eurekaUnRegistering"; 36 | } 37 | 38 | /** 39 | * 用户登录接口,只需要用户名和密码相同即可 40 | * 41 | * @param user 42 | * @return 43 | */ 44 | @ResponseBody 45 | @PostMapping("/login") 46 | public LoginResult login(LoginVO user) { 47 | logger.info("用户登录:username:" + user.getUsername()); 48 | LoginResult result = new LoginResult(); 49 | if (StringUtils.isNotBlank(user.getUsername()) && StringUtils.equals(user.getUsername(), user.getPassword())) { 50 | String token = UUID.randomUUID().toString(); 51 | result.setToken(token); 52 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_OK); 53 | } else { 54 | result.setErrMsg("用户名或密码错误"); 55 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_FAIL); 56 | } 57 | return result; 58 | } 59 | 60 | @ResponseBody 61 | @PostMapping("/getUserInfoByToken") 62 | public UserResult getUserInfoByToken(String token) { 63 | logger.info("获取用户信息:token:" + token); 64 | UserResult result = new UserResult(); 65 | if (StringUtils.isNotBlank(token)) { 66 | // 查询数据库获取用户信息 67 | result.setUsername("username"); 68 | result.setNickname("nickname"); 69 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_OK); 70 | } else { 71 | result.setErrMsg("invalid token!"); 72 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_FAIL); 73 | } 74 | return result; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/filter/ElkFilter.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.filter; 2 | 3 | import com.cml.springcloud.log.KafkaLog; 4 | import com.cml.springcloud.log.LogPointer; 5 | import com.cml.springcloud.log.RequestLog; 6 | import com.cml.springcloud.util.ApplicationUtil; 7 | import com.google.common.eventbus.AsyncEventBus; 8 | import com.google.gson.Gson; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.beans.factory.annotation.Qualifier; 13 | import org.springframework.messaging.MessageChannel; 14 | import org.springframework.messaging.support.MessageBuilder; 15 | 16 | import javax.servlet.annotation.WebFilter; 17 | import java.net.InetAddress; 18 | import java.net.UnknownHostException; 19 | 20 | @WebFilter(urlPatterns = "/*") 21 | public class ElkFilter extends BaseWebFilter { 22 | 23 | private Logger logger = LoggerFactory.getLogger(getClass()); 24 | 25 | private AsyncEventBus asyncEventBus; 26 | 27 | @Qualifier("elkTopic") 28 | @Autowired 29 | private MessageChannel messageChannel; 30 | 31 | @Override 32 | protected void onRequestFinished(RequestLog requestLog) { 33 | 34 | KafkaLog requestLogKafkaLog = new KafkaLog<>(); 35 | requestLogKafkaLog.setData(requestLog); 36 | requestLogKafkaLog.setType("WebRequest"); 37 | requestLogKafkaLog.setIndex("web-request"); 38 | requestLogKafkaLog.setExtra(LogPointer.getPoints()); 39 | requestLogKafkaLog.setEnv(ApplicationUtil.getEnv()); 40 | requestLogKafkaLog.setServiceName(ApplicationUtil.getApplicationName()); 41 | requestLogKafkaLog.setTraceId(LogPointer.getTraceId()); 42 | try { 43 | requestLogKafkaLog.setIp(InetAddress.getLocalHost().getHostAddress()); 44 | } catch (UnknownHostException e) { 45 | e.printStackTrace(); 46 | } 47 | 48 | boolean sendResult = messageChannel.send(MessageBuilder.withPayload(requestLogKafkaLog).build()); 49 | if (!sendResult) { 50 | logger.error("发送kafka消息失败:{}", new Gson().toJson(requestLogKafkaLog)); 51 | } 52 | 53 | logger.info(new Gson().toJson(requestLogKafkaLog)); 54 | logger.info("points:" + new Gson().toJson(LogPointer.getPoints())); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/kafka/Stream.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.kafka; 2 | 3 | import org.springframework.cloud.stream.annotation.Output; 4 | import org.springframework.messaging.MessageChannel; 5 | 6 | public interface Stream { 7 | String channel = "elkTopic"; 8 | 9 | @Output(channel) 10 | MessageChannel elkTopic(); 11 | } 12 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/log/ElkRemoteLogInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.log; 2 | 3 | import com.cml.springcloud.interceptor.RemoteLogInterceptor; 4 | import com.google.gson.Gson; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.messaging.MessageChannel; 10 | import org.springframework.messaging.support.MessageBuilder; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.io.IOException; 14 | 15 | @Component 16 | public class ElkRemoteLogInterceptor implements RemoteLogInterceptor { 17 | private Logger logger = LoggerFactory.getLogger(getClass()); 18 | @Qualifier("elkTopic") 19 | @Autowired 20 | private MessageChannel messageChannel; 21 | 22 | @Override 23 | public void onResponse(String apiName, String url, String requestBody, Integer status, String responseBody, long interval) throws IOException { 24 | logger.info("apiName:{},url:{},requestBody:{},responseBody:{},interval:{}", apiName, url, requestBody, responseBody, interval); 25 | 26 | RequestLog requestLog = new RequestLog(); 27 | requestLog.setResponse(responseBody); 28 | requestLog.setRequestBody(requestBody); 29 | requestLog.setUrl(url); 30 | requestLog.setInterval(interval); 31 | requestLog.setName(apiName); 32 | 33 | KafkaLog requestLogKafkaLog = new KafkaLog<>(); 34 | requestLogKafkaLog.setData(requestLog); 35 | requestLogKafkaLog.setType("Feign"); 36 | requestLogKafkaLog.setIndex("web-request"); 37 | requestLogKafkaLog.setExtra(LogPointer.getPoints()); 38 | 39 | boolean sendResult = messageChannel.send(MessageBuilder.withPayload(requestLogKafkaLog).build()); 40 | if (!sendResult) { 41 | logger.error("发送kafka消息失败:{}", new Gson().toJson(requestLogKafkaLog)); 42 | } 43 | 44 | logger.info(new Gson().toJson(requestLogKafkaLog)); 45 | logger.info("points:" + new Gson().toJson(LogPointer.getPoints())); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/ribbon/DefaultRibbonLoadBalanceRetryFactory.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.ribbon; 2 | 3 | 4 | import com.cml.springcloud.ribbon.listener.RibbonRetryListener; 5 | import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory; 6 | import org.springframework.cloud.netflix.ribbon.SpringClientFactory; 7 | import org.springframework.retry.RetryListener; 8 | 9 | public class DefaultRibbonLoadBalanceRetryFactory extends RibbonLoadBalancedRetryFactory { 10 | public DefaultRibbonLoadBalanceRetryFactory(SpringClientFactory clientFactory) { 11 | super(clientFactory); 12 | } 13 | 14 | @Override 15 | public org.springframework.retry.RetryListener[] createRetryListeners(String service) { 16 | return new RetryListener[]{new RibbonRetryListener()}; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/ribbon/RibbonConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.ribbon; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory; 4 | import org.springframework.cloud.netflix.ribbon.SpringClientFactory; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class RibbonConfiguration { 10 | @Bean 11 | public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory(final SpringClientFactory clientFactory) { 12 | return new DefaultRibbonLoadBalanceRetryFactory(clientFactory); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /user-service-mq/src/main/java/com/cml/springcloud/ribbon/listener/RibbonRetryListener.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.ribbon.listener; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext; 6 | import org.springframework.retry.RetryCallback; 7 | import org.springframework.retry.RetryContext; 8 | import org.springframework.retry.RetryListener; 9 | 10 | public class RibbonRetryListener implements RetryListener { 11 | 12 | private Logger logger = LoggerFactory.getLogger(getClass()); 13 | 14 | @Override 15 | public boolean open(RetryContext context, RetryCallback callback) { 16 | return true; 17 | } 18 | 19 | @Override 20 | public void close(RetryContext context, RetryCallback callback, Throwable throwable) { 21 | 22 | } 23 | 24 | @Override 25 | public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { 26 | String service = ((LoadBalancedRetryContext) context).getServiceInstance().getServiceId(); 27 | logger.error(service + "微服务调用错误:", throwable); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /user-service-mq/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #management.endpoints.web.exposure.include=* 2 | #spring.boot.admin.url=http://localhost:8600 -------------------------------------------------------------------------------- /user-service-mq/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=user-service-mq 3 | server.port=8301 4 | 5 | #eureka\u914d\u7f6e 6 | #spring.boot.admin.client.url=http://localhost:8600 7 | management.security.enabled=false 8 | management.endpoints.web.exposure.include=* 9 | management.endpoints.health.show-details=ALWAYS 10 | management.endpoint.heapdump.enabled=false 11 | management.endpoint.threaddump.enabled=false 12 | management.health.db.enabled=false 13 | management.endpoint.shutdown.enabled=true 14 | 15 | eureka.instance.leaseRenewalIntervalInSeconds=5 16 | eureka.instance.lease-expiration-duration-in-seconds=5 17 | eureka.instance.prefer-ip-address=true 18 | eureka.instance.lease-renewal-interval-in-seconds=5 19 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 20 | #eureka clientˢ�±��ػ���ʱ�� 21 | #Ĭ��30s 22 | eureka.client.registryFetchIntervalSeconds=5 23 | #eureka�ͻ���ribbonˢ��ʱ�� 24 | #Ĭ��30s 25 | ribbon.ServerListRefreshInterval=5000 26 | 27 | ribbon.ConnectTimeout=2000 28 | ribbon.ReadTimeout=2000 29 | ribbon.MaxAutoRetriesNextServer=1 30 | ribbon.MaxAutoRetries=1 31 | ribbon.OkToRetryOnAllOperations=true 32 | 33 | #config center 34 | spring.cloud.config.label=master 35 | spring.cloud.config.profile=dev 36 | spring.cloud.config.uri=http://localhost:9000/ 37 | 38 | #kafka配置 39 | spring.cloud.stream.bindings.elkTopic.destination=elkTopic 40 | spring.cloud.stream.kafka.binder.brokers=localhost:9092 41 | 42 | #actuator config 43 | # HEALTH INDICATORS 44 | #management.health.db.enabled=true # Whether to enable database health check. 45 | #management.health.cassandra.enabled=true # Whether to enable Cassandra health check. 46 | #management.health.couchbase.enabled=true # Whether to enable Couchbase health check. 47 | #management.health.defaults.enabled=true # Whether to enable default health indicators. 48 | #management.health.diskspace.enabled=true # Whether to enable disk space health check. 49 | #management.health.diskspace.path= # Path used to compute the available disk space. 50 | #management.health.diskspace.threshold=0 # Minimum disk space, in bytes, that should be available. 51 | #management.health.elasticsearch.enabled=true # Whether to enable Elasticsearch health check. 52 | #management.health.elasticsearch.indices= # Comma-separated index names. 53 | #management.health.elasticsearch.response-timeout=100ms # Time to wait for a response from the cluster. 54 | #management.health.influxdb.enabled=true # Whether to enable InfluxDB health check. 55 | #management.health.jms.enabled=true # Whether to enable JMS health check. 56 | #management.health.ldap.enabled=true # Whether to enable LDAP health check. 57 | #management.health.mail.enabled=true # Whether to enable Mail health check. 58 | #management.health.mongo.enabled=true # Whether to enable MongoDB health check. 59 | #management.health.neo4j.enabled=true # Whether to enable Neo4j health check. 60 | #management.health.rabbit.enabled=true # Whether to enable RabbitMQ health check. 61 | #management.health.redis.enabled=true # Whether to enable Redis health check. 62 | #management.health.solr.enabled=true # Whether to enable Solr health check. 63 | #management.health.status.http-mapping= # Mapping of health statuses to HTTP status codes. By default, registered health statuses map to sensible defaults (for example, UP maps to 200). 64 | #management.health.status.order=DOWN,OUT_OF_SERVICE,UP,UNKNOWN # Comma-separated list of health statuses in order of severity -------------------------------------------------------------------------------- /user-service-mq/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | ${APP_NAME} 11 | 12 | 13 | 14 | 15 | ${ENCODER_PATTERN} 16 | 17 | 18 | 19 | 20 | 22 | 23 | ${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.log 24 | 25 | 26 | 27 | ${ENCODER_PATTERN} 28 | 29 | 30 | 31 | 32 | 34 | 35 | ${LOG_HOME}/${APP_NAME}-error.%d{yyyy-MM-dd}.log 36 | 37 | 38 | 39 | ${ENCODER_PATTERN} 40 | 41 | 42 | ERROR 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /user-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /user-service/README.MD: -------------------------------------------------------------------------------- 1 | #eureka 服务注册中心 2 | 打开后访问:http://localhost:8761/ -------------------------------------------------------------------------------- /user-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.cml.springcloud 5 | user-service 6 | 1.0 7 | 8 | user-service 9 | Demo project for Spring Boot 10 | 11 | 12 | com.cml.springcloud 13 | parent-service 14 | 1.0 15 | 16 | 17 | 18 | 19 | org.springframework.cloud 20 | spring-cloud-starter-stream-kafka 21 | 22 | 26 | 27 | org.springframework.cloud 28 | spring-cloud-starter-netflix-eureka-client 29 | 30 | 31 | org.springframework.cloud 32 | spring-cloud-starter-config 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-actuator 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-openfeign 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-security 45 | 46 | 47 | spring-beans 48 | org.springframework 49 | 50 | 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-test 55 | test 56 | 57 | 58 | org.springframework.retry 59 | spring-retry 60 | 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-maven-plugin 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /user-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM frolvlad/alpine-oraclejdk8:slim 2 | VOLUME /tmp 3 | ADD user-service-1.0.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/UserClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.builder.SpringApplicationBuilder; 7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 | import org.springframework.cloud.openfeign.EnableFeignClients; 9 | import org.springframework.context.ConfigurableApplicationContext; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13 | 14 | @EnableFeignClients 15 | @EnableEurekaClient 16 | @SpringBootApplication() 17 | public class UserClientApplication { 18 | static Logger logger = LoggerFactory.getLogger(UserClientApplication.class); 19 | 20 | private static final String CUSTOM_COUNTER = "xxl_my_counter"; 21 | 22 | public static void main(String[] args) { 23 | try { 24 | ConfigurableApplicationContext run = new SpringApplicationBuilder(UserClientApplication.class).web(true).run(args); 25 | 26 | } catch (Exception e) { 27 | logger.error("", e); 28 | } 29 | } 30 | 31 | // @Bean 32 | // public ApplicationRunner applicationRunner() { 33 | // return (arg) -> { 34 | // new Thread(() -> { 35 | // for (int i = 0; i < 10000; i++) { 36 | // Metrics.counter(CUSTOM_COUNTER, "test", "失败的次数").increment((int) (100 * Math.random())); 37 | // Metrics.counter(CUSTOM_COUNTER, "test2", "成功的次数").increment((int) (100 * Math.random())); 38 | // try { 39 | // Thread.sleep(1000); 40 | // } catch (InterruptedException e) { 41 | // e.printStackTrace(); 42 | // } 43 | // } 44 | // }).start(); 45 | // }; 46 | // } 47 | 48 | @Configuration 49 | public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { 50 | @Override 51 | protected void configure(HttpSecurity http) throws Exception { 52 | http.authorizeRequests().anyRequest().permitAll() 53 | .and().csrf().disable(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/api/OrderApi.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | 8 | @FeignClient("ORDER-SERVICE") 9 | public interface OrderApi { 10 | 11 | @RequestMapping(value = "/order") 12 | String getOrder(@RequestParam("user") String user); 13 | 14 | @RequestMapping(value = "/testRetry") 15 | String testRetry(); 16 | } 17 | -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/controller/DemoController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import com.cml.springcloud.api.OrderApi; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.cloud.client.discovery.DiscoveryClient; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | @Controller 14 | @RequestMapping("/") 15 | public class DemoController { 16 | private Logger logger = LoggerFactory.getLogger(getClass()); 17 | 18 | @Value("${server.port}") 19 | private String port; 20 | 21 | @Value("${spring.application.name}") 22 | private String sererName; 23 | 24 | @Autowired 25 | private DiscoveryClient client; 26 | 27 | @Autowired 28 | private OrderApi orderApi; 29 | 30 | @ResponseBody 31 | @RequestMapping("/info") 32 | public Object info() { 33 | return client.getServices(); 34 | } 35 | 36 | @ResponseBody 37 | @RequestMapping("/getUser") 38 | public String getUser(String user) { 39 | return "get userInfo user:[" + user + "],from : port:" + port + ",serverName:" + sererName; 40 | } 41 | 42 | @RequestMapping("/test") 43 | @ResponseBody 44 | public String test(String user) { 45 | return "Get userInfo[ " + user + "] from port:" + port + ",serverName:" + sererName + "\n has order:" 46 | + orderApi.getOrder("u" + user); 47 | } 48 | 49 | @RequestMapping("/retryListener") 50 | @ResponseBody 51 | public String testRetryListener() { 52 | try { 53 | return orderApi.testRetry(); 54 | } catch (Exception e) { 55 | logger.error("", e); 56 | return "error:" + e.getMessage(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import java.util.UUID; 4 | 5 | import com.netflix.discovery.DiscoveryClient; 6 | import com.netflix.discovery.DiscoveryManager; 7 | import com.netflix.discovery.EurekaClient; 8 | import org.apache.commons.lang.StringUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.ResponseBody; 17 | 18 | import com.cml.springcloud.constant.ApiServiceContanst; 19 | import com.cml.springcloud.model.request.LoginVO; 20 | import com.cml.springcloud.model.result.LoginResult; 21 | import com.cml.springcloud.model.result.UserResult; 22 | 23 | @Controller 24 | @RequestMapping("/") 25 | public class UserController { 26 | protected static Logger logger = LoggerFactory.getLogger(UserController.class); 27 | 28 | @Autowired 29 | private EurekaClient eurekaClient; 30 | 31 | @ResponseBody 32 | @GetMapping("/eurekaUnRegister") 33 | public String shutDown() { 34 | eurekaClient.shutdown(); 35 | return "eurekaUnRegistering"; 36 | } 37 | 38 | /** 39 | * 用户登录接口,只需要用户名和密码相同即可 40 | * 41 | * @param user 42 | * @return 43 | */ 44 | @ResponseBody 45 | @PostMapping("/login") 46 | public LoginResult login(LoginVO user) { 47 | logger.info("用户登录:username:" + user.getUsername()); 48 | LoginResult result = new LoginResult(); 49 | if (StringUtils.isNotBlank(user.getUsername()) && StringUtils.equals(user.getUsername(), user.getPassword())) { 50 | String token = UUID.randomUUID().toString(); 51 | result.setToken(token); 52 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_OK); 53 | } else { 54 | result.setErrMsg("用户名或密码错误"); 55 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_FAIL); 56 | } 57 | return result; 58 | } 59 | 60 | @ResponseBody 61 | @PostMapping("/getUserInfoByToken") 62 | public UserResult getUserInfoByToken(String token) { 63 | logger.info("获取用户信息:token:" + token); 64 | UserResult result = new UserResult(); 65 | if (StringUtils.isNotBlank(token)) { 66 | // 查询数据库获取用户信息 67 | result.setUsername("username"); 68 | result.setNickname("nickname"); 69 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_OK); 70 | } else { 71 | result.setErrMsg("invalid token!"); 72 | result.setStatus(ApiServiceContanst.ResultCode.RESULT_FAIL); 73 | } 74 | return result; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/controller/UserGatewayController.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * @Auther: cml 10 | * @Date: 2019-01-31 13:58 11 | * @Description: 12 | */ 13 | @RestController 14 | @RequestMapping("/user2") 15 | public class UserGatewayController { 16 | 17 | @GetMapping("/testGet") 18 | public String test(@RequestParam() String extraParameter, @RequestParam(required = false, defaultValue = "none") String name) { 19 | return "welcome to user service name:" + name + ",extraParameter:" + extraParameter; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/ribbon/DefaultRibbonLoadBalanceRetryFactory.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.ribbon; 2 | 3 | 4 | import com.cml.springcloud.ribbon.listener.RibbonRetryListener; 5 | import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory; 6 | import org.springframework.cloud.netflix.ribbon.SpringClientFactory; 7 | import org.springframework.retry.RetryListener; 8 | 9 | public class DefaultRibbonLoadBalanceRetryFactory extends RibbonLoadBalancedRetryFactory { 10 | public DefaultRibbonLoadBalanceRetryFactory(SpringClientFactory clientFactory) { 11 | super(clientFactory); 12 | } 13 | 14 | @Override 15 | public org.springframework.retry.RetryListener[] createRetryListeners(String service) { 16 | return new RetryListener[]{new RibbonRetryListener()}; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/ribbon/RibbonConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.ribbon; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory; 4 | import org.springframework.cloud.netflix.ribbon.SpringClientFactory; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class RibbonConfiguration { 10 | @Bean 11 | public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory(final SpringClientFactory clientFactory) { 12 | return new DefaultRibbonLoadBalanceRetryFactory(clientFactory); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /user-service/src/main/java/com/cml/springcloud/ribbon/listener/RibbonRetryListener.java: -------------------------------------------------------------------------------- 1 | package com.cml.springcloud.ribbon.listener; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext; 6 | import org.springframework.retry.RetryCallback; 7 | import org.springframework.retry.RetryContext; 8 | import org.springframework.retry.RetryListener; 9 | 10 | public class RibbonRetryListener implements RetryListener { 11 | 12 | private Logger logger = LoggerFactory.getLogger(getClass()); 13 | 14 | @Override 15 | public boolean open(RetryContext context, RetryCallback callback) { 16 | return true; 17 | } 18 | 19 | @Override 20 | public void close(RetryContext context, RetryCallback callback, Throwable throwable) { 21 | 22 | } 23 | 24 | @Override 25 | public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { 26 | String service = ((LoadBalancedRetryContext) context).getServiceInstance().getServiceId(); 27 | logger.error(service + "微服务调用错误:", throwable); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /user-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #management.endpoints.web.exposure.include=* 2 | #spring.boot.admin.url=http://localhost:8600 -------------------------------------------------------------------------------- /user-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #\u5e94\u7528(\u670d\u52a1)\u540d\u79f0 2 | spring.application.name=user-service 3 | server.port=8301 4 | 5 | #eureka\u914d\u7f6e 6 | #spring.boot.admin.client.url=http://localhost:8600 7 | management.security.enabled=false 8 | management.endpoints.web.exposure.include=* 9 | management.endpoints.health.show-details=ALWAYS 10 | management.endpoint.heapdump.enabled=false 11 | management.endpoint.threaddump.enabled=false 12 | management.health.db.enabled=false 13 | management.endpoint.shutdown.enabled=true 14 | 15 | eureka.instance.leaseRenewalIntervalInSeconds=5 16 | eureka.instance.lease-expiration-duration-in-seconds=5 17 | eureka.instance.prefer-ip-address=true 18 | eureka.instance.lease-renewal-interval-in-seconds=5 19 | eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 20 | #eureka clientˢ�±��ػ���ʱ�� 21 | #Ĭ��30s 22 | eureka.client.registryFetchIntervalSeconds=5 23 | #eureka�ͻ���ribbonˢ��ʱ�� 24 | #Ĭ��30s 25 | ribbon.ServerListRefreshInterval=5000 26 | 27 | ribbon.ConnectTimeout=2000 28 | ribbon.ReadTimeout=2000 29 | ribbon.MaxAutoRetriesNextServer=1 30 | ribbon.MaxAutoRetries=1 31 | ribbon.OkToRetryOnAllOperations=true 32 | 33 | #config center 34 | spring.cloud.config.label=master 35 | spring.cloud.config.profile=dev 36 | spring.cloud.config.uri=http://localhost:9000/ 37 | 38 | 39 | #actuator config 40 | # HEALTH INDICATORS 41 | #management.health.db.enabled=true # Whether to enable database health check. 42 | #management.health.cassandra.enabled=true # Whether to enable Cassandra health check. 43 | #management.health.couchbase.enabled=true # Whether to enable Couchbase health check. 44 | #management.health.defaults.enabled=true # Whether to enable default health indicators. 45 | #management.health.diskspace.enabled=true # Whether to enable disk space health check. 46 | #management.health.diskspace.path= # Path used to compute the available disk space. 47 | #management.health.diskspace.threshold=0 # Minimum disk space, in bytes, that should be available. 48 | #management.health.elasticsearch.enabled=true # Whether to enable Elasticsearch health check. 49 | #management.health.elasticsearch.indices= # Comma-separated index names. 50 | #management.health.elasticsearch.response-timeout=100ms # Time to wait for a response from the cluster. 51 | #management.health.influxdb.enabled=true # Whether to enable InfluxDB health check. 52 | #management.health.jms.enabled=true # Whether to enable JMS health check. 53 | #management.health.ldap.enabled=true # Whether to enable LDAP health check. 54 | #management.health.mail.enabled=true # Whether to enable Mail health check. 55 | #management.health.mongo.enabled=true # Whether to enable MongoDB health check. 56 | #management.health.neo4j.enabled=true # Whether to enable Neo4j health check. 57 | #management.health.rabbit.enabled=true # Whether to enable RabbitMQ health check. 58 | #management.health.redis.enabled=true # Whether to enable Redis health check. 59 | #management.health.solr.enabled=true # Whether to enable Solr health check. 60 | #management.health.status.http-mapping= # Mapping of health statuses to HTTP status codes. By default, registered health statuses map to sensible defaults (for example, UP maps to 200). 61 | #management.health.status.order=DOWN,OUT_OF_SERVICE,UP,UNKNOWN # Comma-separated list of health statuses in order of severity -------------------------------------------------------------------------------- /user-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | ${APP_NAME} 11 | 12 | 13 | 14 | 15 | ${ENCODER_PATTERN} 16 | 17 | 18 | 19 | 20 | 22 | 23 | ${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.log 24 | 25 | 26 | 27 | ${ENCODER_PATTERN} 28 | 29 | 30 | 31 | 32 | 34 | 35 | ${LOG_HOME}/${APP_NAME}-error.%d{yyyy-MM-dd}.log 36 | 37 | 38 | 39 | ${ENCODER_PATTERN} 40 | 41 | 42 | ERROR 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /wiki/img/eureka-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/wiki/img/eureka-server.png -------------------------------------------------------------------------------- /wiki/img/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/wiki/img/login.png -------------------------------------------------------------------------------- /wiki/img/login2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/wiki/img/login2.png -------------------------------------------------------------------------------- /wiki/img/springcloud-strut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/wiki/img/springcloud-strut.png -------------------------------------------------------------------------------- /wiki/img/zuul1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmlbeliever/SpringCloudBucket/c324179ca9bcb99e70ae2399908a21b9e34dc09f/wiki/img/zuul1.png --------------------------------------------------------------------------------