# CodeMerge **Repository Path**: ShareEveryDay/UnifiedGateway ## Basic Information - **Project Name**: CodeMerge - **Description**: No description available - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: dev-oracle - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-06-17 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # open-capacity-platform 微服务能力开放平台 简称ocp是基于layui+springcloud的企业级微服务框架(用户权限管理,配置中心管理,应用管理,....),其核心的设计目标是分离前后端,快速开发部署,学习简单,功能强大,提供快速接入核心接口能力,其目标是帮助企业搭建一套类似百度能力开放平台的框架; - 基于layui前后端分离的企业级微服务架构 - 兼容spring cloud netflix & spring cloud alibaba - 优化Spring Security内部实现,实现API调用的统一出口和权限认证授权中心 - 提供完善的企业微服务流量监控,日志监控能力 - 提供完善的压力测试方案 - 提供完善的灰度发布方案 - 提供完善的微服务部署方案 ​ # 技术介绍
# **功能介绍** - 统一安全认证中心 - 支持oauth的四种模式登录 - 支持用户名、密码加图形验证码登录 - 支持第三方系统单点登录 - 微服务架构基础支撑 - 服务注册发现、路由与负载均衡 - 服务熔断与限流 - 统一配置中心 - 统一日志中心 - 分布式锁 - 分布式任务调度器 - 系统服务监控中心 - 服务调用链监控 - 应用吞吐量监控 - 服务降级、熔断监控 - 微服务服务监控 - 能力开放平台业务支撑 - 网关基于应用方式API接口隔离 - 网关基于应用限制调用次数 - 下游服务基于RBAC权限管理,实现细粒度控制 - 代码生成器中心 - 网关聚合服务内部Swagger接口文档 - 统一跨域处理 - 统一异常处理 - docker容器化部署 - 基于rancher的容器化部署 - 基于docker的elk日志监控 - 基于docker的服务动态扩容 ## 工程结构 > open-capacity-platform > > > common -- 基础公共模块 > > > > > common-spring-starter --工具类、常量、基础配置、基础基类封装 > > > > > > db-spring-boot-starter -- 关系型数据库逻辑及依赖封装 > > > > > > redis-spring-boot-starter -- 非关系型数据库逻辑及依赖封装 > > > > > > uaa-server-spring-boot-starter -- 认证服务器封装 > > > > > > uaa-client-spring-boot-starter -- 资源服务器封装 > > > > > > log-spring-boot-starter -- 日志封装 > > > > > > rabbitmq-spring-boot-starter -- mq封装 > > > > > > ribbon-spring-boot-starter -- 自定义负载均衡策略 > > > > > > swagger-spring-boot-starter -- api文档封装 > > > > business-center -- 业务中心 > > > > >business-demo -- demo模块用于示例部分代码 > > > > > >deposit -- 存款服务业务模块 > > > > > >financial -- 理财服务业务模块 > > > > > >life -- 生活服务业务模块 > > > > > >loan -- 贷款服务业务模块 > > > > > >payment -- 支付结算服务业务模块 > > > > > >user-account -- 用户/账户服务业务模块 > > > > gateway-center -- 网关中心 > > > > > external-gateway -- 内联网关 > > > > > > inside-gateway -- 外联网关 > > > > oauth-center --认证中心 > > > > > auth-server -- 认证服务 > > > > > > auth-sso -- 单点登陆示例代码 > > > > monitor-center > > > > >admin-server -- spring boot监控和管理模块 > > > > > >gray-console > > > > > >log-center -- 日志中心 > > > > > >maintenance -- 运维管理平台 > > > > > >transaction-center -- 分部式事务中心 > > > > task-center --分部式任务中心 > > > > >task-executor -- 任务执行器 > > > > > >task-scheduler -- 任务调度器 > > > > web-portal web前端 # IDEA项目导入 #### 1. 由于整个项目依赖于Lombok,所以使用idea开发的过程中请使用Lombok插件 #### 2.导入项目 - 在maven工程中导入,根目录下的pom文件 ![1594713815025](C:\Users\Administrator\Desktop\readme\img\1594713763050.png) - 安装整个项目,在maven工程的open-capacity-platform(root)模块下install,等待安装完成 ![1594713965932](C:\Users\Administrator\Desktop\readme\img\1594713913416.png) # 业务开发 ### 代码结构 - 业务模块在business_center父模块下进行子模块开发,结构如下: ![1594716940563](C:\Users\Administrator\Desktop\readme\img\1594714471053.png) - java目录 ![1594714868556](C:\Users\Administrator\Desktop\readme\img\1594714868556.png) - 包结构 - config:统一存放配置类相关代码 - controller:统一存放控制器相关代码 - dao: 统一存放数据访问层相关代码包括xml - model: 统一存放实体类 - service: 统一存服务层存着代码 - feign:统一存放服务间调用接口 - fallback:存放熔断处理相关类 - strategy: - resource目录 ![1594716610084](C:\Users\Administrator\Desktop\readme\img\1594716610084.png) - resources目录 - application.yml: spring-boot配置文件 - bootstrap.yml: - logback-spring.xml: 日志配置文件 - mybatis.cfg.xml: mybatis配置文件 - view目录: 用于存放静态资源 - docker目录: 存放Dockerfile文件,用于快数部署 ### 相关示例代码及配置使用 --- - #### 统一结果对象 ```java package com.open.capacity.common.web; @Data @NoArgsConstructor @AllArgsConstructor public class Result implements Serializable { private static final long serialVersionUID = -4696008537295855861L; private T data; private Integer resp_code; private String resp_msg; public static Result succeed(String msg) { return succeedWith(CodeEnum.SUCCESS.getCode(), msg, null); } public static Result succeed(String msg, T data) { return succeedWith(CodeEnum.SUCCESS.getCode(), msg, data); } public static Result succeedWith(Integer code, String msg) { return succeedWith(code, msg, null); } public static Result succeedWith(Integer code, String msg, T data) { return new Result(data, code, msg); } public static Result failed(String msg) { return failedWith(CodeEnum.ERROR.getCode(), msg, null); } public static Result failed(String msg, T data) { return failedWith(CodeEnum.ERROR.getCode(), msg, data); } public static Result failedWith(Integer code, String msg) { return failedWith(code, msg, null); } public static Result failedWith(Integer code, String msg, T data) { return new Result(data, code, msg); } } ``` --- - #### feign接口的调用 ##### 开户FeignClient - 启动类上添加注解@@EnableFeignClients(basePackages = {"com.open.capacity.xxx.feign"}) - basePackages中指定扫描的feign接口包名 - 引入FeignInterceptorConfig.class, RestTemplateConfig.class配置类,用于access_token的传递 - 以com.open.capacity.BusinessDemoApp为例 ```java @SpringBootApplication @EnableFeignClients(basePackages = {"com.open.capacity.demo.feign"}) @Import({FeignInterceptorConfig.class, RestTemplateConfig.class}) public class BusinessDemoApp { public static void main(String[] args) { // 固定端口启动 // SpringApplication.run(UserCenterApp.class, args); //随机端口启动 SpringApplication app = new SpringApplication(BusinessDemoApp.class); app.addListeners(new PortApplicationEnvironmentPreparedEventListener()); app.run(args); } } ``` ##### 建立feign接口,用于远程调用 - 在相应模块下com.open.capacity.xxx.feign建立feign接口,以com.open.capacity.demo.feign.UserFeignClient接口为例 ```java @FeignClient(value="user-account",configuration = FeignExceptionConfig.class ,fallbackFactory = UserFeignClientFallbackFactory.class) public interface UserFeignClient { @GetMapping("/users/current") public Result getLoginAppUser(); } ``` ##### 建立UserFeignClientFallbackFactory接口,用于熔断处理 - 在com.open.capacity.xxx.feign.fallback建立feignFeignClientFallbackFactory接口(功能不需要可不用),以com.open.capacity.demo.feign.fallback.UserFeignClientFallbackFactory为例 ```java @Slf4j @Component public class UserFeignClientFallbackFactory implements FallbackFactory { /**这里进行熔断后的处理,这里直接进行了异常的抛出,并未处理*/ @Override public UserFeignClient create(Throwable throwable) { return new UserFeignClient() { @Override public Result getLoginAppUser() { log.error("查询登陆用户异常", throwable.getMessage()); throw new RuntimeException(throwable); } }; } } ``` --- - #### swagger ##### 配置 - 以com.open.capacity.demo.config.SwaggerConfig为例 ```java @Component @Configuration @EnableSwagger2 public class SwaggerConfig implements WebMvcConfigurer { @Bean public Docket createRestApi() { ParameterBuilder tokenPar = new ParameterBuilder(); List pars = new ArrayList<>(); tokenPar.name("Authorization").description("令牌"). modelRef(new ModelRef("string")). parameterType("header").required(false).build(); pars.add(tokenPar.build()); return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() // .apis(RequestHandlerSelectors.basePackage("com.open.capacity")) .apis(RequestHandlerSelectors.any()) /**配置api资源uri*/ .paths(input -> PathSelectors.regex("/demo.*").apply(input) || PathSelectors.regex("/auth.*").apply(input) ) // .paths(PathSelectors.any()) .build().globalOperationParameters(pars); } /**swagger 标题、版本、描述*/ private ApiInfo apiInfo() { return new ApiInfoBuilder().title("demo api").description("demo api").version("1.0").build(); } @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setViewClass(JstlView.class); resolver.setPrefix("/"); resolver.setSuffix(".html"); return resolver; } @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("messages"); return messageSource; } /**资源地址*/ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // super.addResourceHandlers(registry); registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } } ``` --- ##### controller上使用 - 以com.open.capacity.demo.controller.DemoController为例 ```java @Slf4j @RestController /**api 标签*/ @Api(tags = "Demo API") @RequestMapping("/demo") public class DemoController { @Autowired private DemoService demoService; @PostMapping("/save") /**@ApiOperation,value:api摘要,notes:api注释,response返回的数据类型*/ @ApiOperation(value = "demo数据保存",notes = "",response=Result.class) public Result save(@RequestBody Demo demo) { try { demoService.save(demo); return Result.succeed("保存成功"); } catch (Exception e) { throw new ControllerException(e); } } } ``` --- - #### 权限控制 ##### 启动类配置 ```java @SpringBootApplication /**在启动类上需添加注解 @EnableGlobalMethodSecurity(prePostEnabled = true)*/ @EnableGlobalMethodSecurity(prePostEnabled = true) public class BusinessDemoApp { public static void main(String[] args) { //随机端口启动 SpringApplication app = new SpringApplication(BusinessDemoApp.class); app.addListeners(new PortApplicationEnvironmentPreparedEventListener()); app.run(args); } } ``` --- ##### 方法上配置 ```java @Slf4j @RestController @RequestMapping("/demo") public class DemoController { @Autowired private DemoService demoService; @PostMapping("/save") @PreAuthorize("hasAnyRole('ADMIN,adminUserRole')") public Result save(@RequestBody Demo demo) { try { demoService.save(demo); return Result.succeed("保存成功",demo); } catch (Exception e) { throw new ControllerException(e); } } } ``` 如果对方法执行后进行权限认证可使用@PostAuthorize注解,如: ```java /**方法执行后的返回值data.name='demo' 放权*/ @PostAuthorize("returnObject.data.name=='demo'") ``` --- - #### application.yml配置及使用 - 开发过程中可将配置文件写入application.yml中进行开发调试,调度完成后使用**nacos配置中心**进行统一配置管理 --- - ##### 数据源配置 ```yml spring: datasource: druid: # JDBC 配置(驱动类自动从url的oracle识别,数据源类型自动识别) url: jdbc:oracle:thin:@//127.0.0.1:1521/orcl username: CABINAPP password: CABINAPP driver-class-name: oracle.jdbc.driver.OracleDriver #连接池配置(通常来说,只需要修改initialSize、minIdle、maxActive initial-size: 1 max-active: 20 min-idle: 1 # 配置获取连接等待超时的时间 max-wait: 60000 #打开PSCache,并且指定每个连接上PSCache的大小 pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 validation-query: select 1 from dual test-on-borrow: false test-on-return: false test-while-idle: true #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 time-between-eviction-runs-millis: 60000 #配置一个连接在池中最小生存的时间,单位是毫秒 min-evictable-idle-time-millis: 300000 filters: stat,wall # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter #是否启用StatFilter默认值true web-stat-filter.enabled: false web-stat-filter.url-pattern: /* web-stat-filter.exclusions: "*.js , *.gif ,*.jpg ,*.png ,*.css ,*.ico , /druid/*" web-stat-filter.session-stat-max-count: 1000 web-stat-filter.profile-enable: true # StatViewServlet配置 #展示Druid的统计信息,StatViewServlet的用途包括:1.提供监控信息展示的html页面2.提供监控信息的JSON API #是否启用StatViewServlet默认值true stat-view-servlet.enabled: false #根据配置中的url-pattern来访问内置监控页面,如果是上面的配置,内置监控页面的首页是/druid/index.html例如: #http://110.76.43.235:9000/druid/index.html #http://110.76.43.235:8080/mini-web/druid/index.html stat-view-servlet.url-pattern: /druid/* #允许清空统计数据 stat-view-servlet.reset-enable: true stat-view-servlet.login-username: admin stat-view-servlet.login-password: admin #StatViewSerlvet展示出来的监控信息比较敏感,是系统运行的内部情况,如果你需要做访问控制,可以配置allow和deny这两个参数 #deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝。如果allow没有配置或者为空,则允许所有访问 #配置的格式 # #或者/其中128.242.127.1/24 #24表示,前面24位是子网掩码,比对的时候,前面24位相同就匹配,不支持IPV6。 #stat-view-servlet.allow= #stat-view-servlet.deny=128.242.127.1/24,128.242.128.1 # Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置 #aop-patterns= # Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔 ``` --- - redis 配置 ```yml spring: ################### redis 单机版 start ########################## redis: host: 127.0.0.1 port: 6379 timeout: 6000 database: 1 lettuce: pool: max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽) max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8 max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0 shutdown-timeout: 100ms ################### redis 单机版 end ########################## ################### redis 集群 start ############################ # cluster: # nodes: 130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 # #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 # #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001 # timeout: 1000 # 连接超时时间(毫秒) # lettuce: # pool: # max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽) # max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8 # max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException # min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0 # shutdown-timeout: 100ms ################### redis 集群 end ############################ ``` --- - discovery 配置 ```yml spring: cloud: nacos: ################### discovery for nacos ####################### discovery: server-addr: localhost:8848 metadata: group: service-center-group version: 1.0 namespace: test-environment-xy ``` --- - monitor for admin 配置 ```yml spring: ################### monitor for admin ####################### boot: admin: client: instance: prefer-ip: true url: http://localhost:9001 ``` --- - config for gray ```yml spring: application: ################### config for gray ####################### strategy: rest: intercept: enabled: true debug: enabled: true context: request: headers: trace-id;span-id businese: request: headers: user;mobile rpc: intercept: enabled: true scan: #指定restcontroller类下的资源的路径 用于实现rpc的调用拦截,消费端和服务端的隔离和调用链的关系 packages: com.open.capacity.user.controller register: isolation: enabled: true consumer: isolation: enabled: true provider: isolation: enabled: true monitor: enabled: true logger: enabled: true tracer: enabled: true sentinel: enabled: true service: sentinel: limit: app: enabled: false environment: isolation: enabled: true route: enabled: false ``` --- - mybatis及mybaits-plus配置 ```yml ################### mybatis 配置 ############### mybatis-plus: global-config: banner: false configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath*:com/open/**/dao/*.xml mybatis: config-location: classpath:mybatis.cfg.xml mapper-locations: classpath*:com/owen/**/dao/*.xml ``` --- - 权限认证配置 ```yml ##################### 权限控制配置 ################### security: oauth2: #无需权限控制的资源 ignored: /users-anon/** , /doc.html ,/document.html ,/users/save #token储存类型,目录只支持redis存储 token: store: type: redis ``` --- - 其它配置 ```yml #设置最大超时时间 ribbon: ServerListRefreshInterval: 10 #刷新服务列表源的间隔时间 OkToRetryOnAllOperations: true MaxAutoRetries: 1 MaxAutoRetriesNextServer: 1 ReadTimeout: 1000 #1000ms ConnectTimeout: 1000 #设置最大容错超时时间 hystrix: command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 2000 ##feign参数优化 feign: hystrix: enabled: true client: config: default: loggerLevel: full ## 配合logging.level=trace debug用于开发调式日志 compression: request: enabled: true mine-types: text/xml,application/xml,application/json min-request-size: 2048 response: enabled: true #日志配置 logging: level: com.open.capacity: INFO ```