Spring Cloud规范实战

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: Spring Cloud规范实战

Spring cloud 架构建立规范文档


版本1.0


作者:阿伏(王伏芃)




目录

1. 建立规范的目的 3

2.模板源码位置 3

3.系统架构图 3

4.路由服务Zuul Server 4

5.MybatisGeneratorPlus生成器 9

6.业务应用服务SpringBoot Server 15

6.1 服务启动方法: 16

6.2 @EnableCaching 17

6.3 @EnableScheduling 18

6.4@EnableFeignClients(basePackages="com.pay.api.client") 19

6.5 @ComponentScan(basePackages = "com.pay.api") 19

6.6 @ServletComponentScan 20

6.7 @EnableCircuitBreaker 20

6.8 @EnableHystrixDashboard 21

6.9 @EnableDiscoveryClient 22

6.10 @EnableSwagger2 22

7.注册中心服务Eureka Server 24

7.1 在pom.xml里添加依赖: 24

7.2 在bootstrap.yml里面配置如此: 25

7.3 EurekaServerApplication.java 25

7.4 运行时界面如下 26

8.全链路监控服务Zipkin Server 26

8.1 pom.xml 26

8.2 Bootstrap.yml 27

8.3 ZipkinServerApplication.java 27

8.4 客户端sleuth配置 28

9.配置服务Config Server 29

9.1. Pom.xml 29

9.2. ConfigServerApplication.java 29

9.3. Config server 的yml的配置 30

9.4. Client端的Pom.xml 30

9.5 Client端的在代码中的使用 31

9.6 Client端的yml中的配置: 31

10.各种命名规范 31

10.1变量命名规范。 31

10.2 强制要求所有魔法值全部用KeyCommon这个类里的属性来替代。 32

10.3 所有抛出的异常在TemplateErrorCode里面定义。 32

10.4 方法名命名规范 32

11. 模板使用方法 33

11.1 从git上面下载代码,查看章节2。 33

11.2用STS打开。STS下载地址在http://spring.io/tools/sts 33

11.3 配置好maven和jdk 34

11.3 导入template源码 37

11.4 重命名模板里面的文件夹名称或者更改目录结构,改成自己要的包名。 41

11.5 把com.caituo.template替换成自己的包名。 41

11.6 启动方法 42

12.附上之前做的一整套架构。 44

13.阿里巴巴的P3C标准 45

13.1. P3C标准的pdf文档 45

13.2.P3C的Eclipse插件安装办法及启动检查 45








1. 建立规范的目的


是为了统一规格,提高代码的可读性,系统的易用性,可维护性。

本规范作为搭建spring cloud的指导文档。确保照着搭建就能成功。


2.模板源码位置

在公司的gitlab上面。

http://10.66.1.168:10080/wangfupeng/pay-template.git

如果没有权限,请联系胡立开(hulikai@91steel.com),赵超(zhaochao@91steel.com)


3.系统架构图


 


下面是介绍各种服务器和各种应用。


4.路由服务Zuul Server


代码目录如图所示:

 

其中bootstrap.yml里面的

spring:

  config:

    location: classpath:/${ENV:dev}/

这个注释说明,通过环境变量来读取ENV的值来决定在哪个目录里面找着application.yml

application.yml里配置如下:

spring:

  application:

    name: zuul


server:

  port: 8020


eureka:

  client:

    service-url:

      defaultZone: http://localhost:8010/eureka/


zuul: 

  routes:

    api-a:

      path: /service-a/**

      serviceId: service-a

    api-b:

      path: /service-b/**

      serviceId: service-b

  sensitive-headers:  #设置忽略的头信息,设置为空能解决会话保持问题

  add-host-header: true #设为true才能保持Host头信息处理正确

#这表示,我们不希望 /hello 接口被路由,调用 "/service-a"会跳转到"service-a"服务。路由必须配置一个可以被指定为"ant路径匹配原则"的"path",所以"/service-a/"只能匹配一个层级, 但"/service-a/*"可以匹配多级.


Ant匹配规则表

Wildcard Description  

? 匹配任何单字符  

* 匹配0或者任意数量的字符  

** 匹配0或者更多的目录


Pom.xml里面的配置如此:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">


<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.4.RELEASE</version>

<relativePath /> <!-- lookup parent from repository -->

</parent>


<modelVersion>4.0.0</modelVersion>

<groupId>com.caituo.server</groupId>

<artifactId>zuul</artifactId>

<version>66602</version>

<packaging>jar</packaging>


<name>zuul</name>

<url>http://maven.apache.org</url>


<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>1.8</java.version>

<spring-cloud.version>Dalston.SR1</spring-cloud.version>

</properties>


<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-zuul</artifactId>

</dependency>

</dependencies>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>${spring-cloud.version}</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>



</project>

然后在ZuulApplication.java里面写上如下代码就行了。


package com.caituo.server;


import org.springframework.boot.SpringApplication;

import org.springframework.boot.web.servlet.ServletComponentScan;

import org.springframework.cloud.client.SpringCloudApplication;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

import org.springframework.context.annotation.Bean;


import com.caituo.server.filter.MyZuulFilter;


@SpringCloudApplication

@EnableZuulProxy

@ServletComponentScan

public class ZuulApplication {

    public static void main(String[] args) {

        SpringApplication.run(ZuulApplication.class, args);

    }


    @Bean

    public MyZuulFilter getZuulFilter(){

        return new MyZuulFilter();

    }

}


当然还有其他高级用法,就具体问题具体分析了



5.MybatisGeneratorPlus生成器

目录结构如图

 

使用方法:

1.右键Pom.xml->Run As->Maven Install

 

2. 在template里面找着generatorConfig.xml。如图所示。

 

3. 然后编辑。

在这里改连接字符串。

<jdbcConnection driverClass="com.mysql.jdbc.Driver"

connectionURL="jdbc:mysql://10.66.1.32:3306/payment" 

userId="ssc"

password="ssc">

</jdbcConnection>


然后找着<table tableName=

然后编辑,复制,粘贴真个<table></table>标签

编辑成自己要的东东。

一般自己有几张表,就写复制粘贴几张表。


其余的别改,保存后。

Pom.xml->右键->Run As->Maven build…

 

复制下面命令进入Goals里面

-Dfile.encoding=UTF-8 -Dmybatis.generator.overwrite=true mybatis-generator:generate -e -X

点Run

 

好了,生成器会自动帮助生成Model, ModelExample, Mapper, Service, Controller. 包括@RequestMapping注解,swagger注释和文档。Cache的注解。


规范点:

1.Mysql里所有字段必须勾上非空。(暂缓推行)

如图所示。下面的软件是Navicat,如果用SqlYog软件也类似。

 

强制要求在插入字段时,必须设置一个值。




2. 所有的字段都要上索引,除了Blob字段。

 

3. 用mybatisGenerator生成器一次性生成所有代码,后期不允许自己写SQL语句。(暂缓推行)


有特殊要求比如join之类的跨表查询,用循环遍历来解决。


这样做好处:

1.把程序员从框架层面解放出来,专心实现业务代码。

2.各种数据表层面解耦。

3.提高代码可读性。

4.后期维护很容易。

5.把操作数据库变成操作对象一样容易。

6.后期做其他微服务改造很容易。


6.业务应用服务SpringBoot Server


目录结构如图所示:

 


 


6.1 服务启动方法:

@SpringBootApplication

@EnableCaching

@EnableScheduling

@EnableFeignClients(basePackages = "com.pay.api.client")

@ComponentScan(basePackages = "com.pay.api")

@ServletComponentScan

@EnableCircuitBreaker

@EnableHystrixDashboard

@EnableSwagger2

@EnableDiscoveryClient

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

}


6.2 @EnableCaching

打开缓存标志, 打开之后,我们可以这么使用Cache

    @Cacheable(value = "cache:card", key = "'cache:card:get:id:'+#id")

    public Card get(Integer id) {

        return cardMapper.selectByPrimaryKey(id);

    }

    @CacheEvict(value = "cache:card", key = "'cache:card:get:id:'+#card.getId()")

    public Integer update(Card card) {

        return cardMapper.updateByPrimaryKeySelective(card);

    }

要求再pom里面配置:

<dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-cache</artifactId>

</dependency>


同时要实现2个类

@Component

public class RedisCacheManager implements CacheManager, DisposableBean {

@Autowired

@Qualifier("myRedisCache")

private Cache cache;

@Override

public void destroy() throws Exception {

cache.clear();

}

@Override

public Cache getCache(String name) {

return cache;

}

@Override

public Collection<String> getCacheNames() {

return null;

}

}


@Component("myRedisCache")

public class RedisCache implements Cache {

public static final Logger logger = LoggerFactory.getLogger(ShardedRedisCache.class);

……

@Override

public ValueWrapper get(Object key) {

//主要是在这里实现get方法

}

@Override

public void put(Object key, Object value) {

//主要在这里实现put方法

}

@Override

public <T> T get(Object key, Class<T> type) {

//主要是在这里实现get方法

}

@Override

public void evict(Object key) {

//主要在这里实现删除方法

}

……其余方法略

}


6.3 @EnableScheduling

打开Schedule标志

然后我们就可以在方法上面加上

@Scheduled(fixedRate = 1000)

来显式的声明这个方法是个定时任务。其余的高级表达式要具体情况具体分析

这个要在xml里面配置

<task:scheduler id="taskScheduler" pool-size="30" />

然后把xml加载进来

可以用如下方式加载

@Configuration

@ImportResource("classpath:/applicationContext.xml")

public class XmlConfiguration {

}

最后application.java上面要加上

@ComponentScan(basePackages = "com.pay.api")


6.4@EnableFeignClients(basePackages="com.pay.api.client")

意思是会扫描包com.pay.api.client下面的所有feign的远程调用代码

在这里声明了,就能够和在本地调用服务一样请求远程服务器了。

例如

@FeignClient(name = "tencentIMClient", url = "http://www.qq.com")

public interface TencentIMClient {

    @RequestMapping(method = {RequestMethod.POST}, value = {"/v4/openim/sendmsg"})

    String openimSendmsg(

        @RequestBody OpenimSendMsgRequest request,

        @RequestParam("identifier") String identifier,

        @RequestParam("sdkappid") int sdkAppId,

        @RequestParam("contenttype") String contentType,

        @RequestParam("random") int random,

        @RequestParam("usersig") String usersig

        );

}

注意,如果url没有指定,会去eureka服务器上面去查找name值的应用,然后访问后面对应的@RequestMapping对应的路径里的值

如果定义了url则是访问以url开头的网址

其中还可以指定一些其他的属性。


6.5 @ComponentScan(basePackages = "com.pay.api")

意思是扫描所有包名是com.pay.api下面的所有class,匹配所有AOP,注册成bean

6.6 @ServletComponentScan

在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

例如:

@WebServlet(urlPatterns="/xs/myservlet", description="Servlet的说明") 

public class MyServlet2 extends HttpServlet{ 

……

}

@WebServlet还有一个属性是name,在不指定name的情况下,name默认值为类全路径

再例如:用这个filter来解决跨域问题。

@WebFilter(filterName="corsFilter",urlPatterns="/*")

public class CorsFilter implements Filter{  

……

@Override

    public void doFilter(ServletRequest request, ServletResponse servletResponse,  

            FilterChain chain) throws IOException, ServletException {

            HttpServletResponse response = (HttpServletResponse) servletResponse;  

            response.setHeader("Access-Control-Allow-Origin", "*");

            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");  

            response.setHeader("Access-Control-Max-Age", "3600");

            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, token");  

            chain.doFilter(request, response);

    }  

其余的还有一些高级应用,要具体情况具体分析了

6.7 @EnableCircuitBreaker

这个是打开断路器的功能。

1. 引入Hystrix的依赖包

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-hystrix</artifactId>

</dependency>

2. bootstrap.yml中加上这个配置

#超时500毫秒, 基础服务运行超时。用于feign的中断

hystrix:

  command.default.execution.isolation.thread.timeoutInMilliseconds: 5000 //设置默认超时时间

  threadpool.default.coreSize: 50

  threadpool.default.maximumSize: 60

  threadpool.default.maxQueueSize: 40

#打开feign的断路器,可以在feign调用时使用超时熔断

feign:

  hystrix:

    enabled: true

3. 再要断路的地方上面加上这个AOP

@HystrixCommand(fallbackMethod = “fallback”, //要在同一个类里面写这个方法fallback(), 参数和返回对象要完全和下面的方法一致

commandProperties = {

@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "16666"),//超时时间

@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "26"),//设置一个滑动窗口内触发熔断的最少请求量,默认20。

@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "6000") },//设置触发熔断后,拒绝请求后多长时间开始尝试再次执行。默认5000ms。

threadPoolProperties = {

@HystrixProperty(name = "coreSize", value = "10")})//设置线程池的core size,这是最大的并发执行数量。默认10

6.8 @EnableHystrixDashboard

运行Hystrix仪表板需要在spring boot主类上标注@EnableHystrixDashboard。然后访问/ hystrix查看仪表盘,在hystrix客户端应用使用/hystrix.stream监控。

 


6.9 @EnableDiscoveryClient

开启服务发现,自动往eureka服务器上注册自己的api来方便其他应用在eureka上查找相关服务。

需要在bootstrap.yml中配置

#打开eureka的注册查找地址

eureka:

  instance:

    lease-expiration-duration-in-seconds: 30

    lease-renewal-interval-in-seconds: 10

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka


6.10 @EnableSwagger2

通过注解EnableSwagger2声明Swagger的可用性。Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。步骤如下:

6.10.1. 添加maven依赖,需要在系统的pom中添加如下依赖:

<dependency>

   <groupId>io.springfox</groupId>

   <artifactId>springfox-swagger2</artifactId>

   <version>2.6.1</version>

</dependency>

<dependency>

   <groupId>io.springfox</groupId>

   <artifactId>springfox-swagger-ui</artifactId>

   <version>2.6.1</version>

</dependency>

6.10.2. 添加swagger配置文件,配置文件如下:

@Configuration

@EnableSwagger2

public class SwaggerConfig {

    @Bean

    public Docket api() {

        return new Docket(DocumentationType.SWAGGER_2)

                .select()  // 选择那些路径和api会生成document

                .apis(RequestHandlerSelectors.any()) // 对所有api进行监控或者可以用.apis(RequestHandlerSelectors.basePackage("com.fpfpp.server.controller"))

                .paths(PathSelectors.any()) // 对所有路径进行监控

                .build();

    }

}

6.10.3. 在Controller上面加

@Api(description = "增删改查列表Card")

@RestController

在方法上面加上@ApiOperation("查询Card")

在参数上面加上@ApiParam(value = "id")

示例如下:

@Api(description = "增删改查列表Card")

@RestController

@RequestMapping(value = "/v1/card", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

public class CardController implements Logging {

    public static final Logger logger = LoggerFactory.getLogger(CardController.class);

    @Autowired

    private CardService cardService;

    @ApiOperation("查询Card")

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)

    public SimpleResponse get(@ApiParam(value = "id") @PathVariable Integer id) {

        return SimpleResponse.success(cardService.get(id));

    }

}

6.10.4最后查看swagger-ui

请访问http://hostname/rootpath/swagger-ui.html

 


7.注册中心服务Eureka Server

7.1 在pom.xml里添加依赖:

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-eureka-server</artifactId>

</dependency>

7.2 在bootstrap.yml里面配置如此:

server:

  port: 16661 #服务端口

spring:

  application:

    name: eureka-server

eureka:

  instance:

    preferIpAddress: true

    ipAddress: ${EUREKA_IPADDRESS:10.200.120.8}

    lease-renewal-interval-in-seconds: 6

    lease-expiration-duration-in-seconds: 6

    instanceId: ${spring.cloud.client.ipAddress}:${server.port}

  server:

    enable-self-preservation: false

    eviction-interval-timer-in-ms: 6666

  client:

    register-with-eureka: true #是否将eureka自身作为应用注册到eureka注册中心

    fetch-registry: true #为true时,可以启动,但报异常:Cannot execute request on any known server

    serviceUrl:

      defaultZone: ${EUREKA_DEFAULTZONE:http://10.200.120.8:16661/eureka/,http://10.200.110.8:16661/eureka/} 


7.3 EurekaServerApplication.java

最后应用程序是这么写,run起来就是一个eureka 服务器

上面的配置说明是个eureka集群。

@SpringBootApplication

@EnableEurekaServer

public class EurekaServerApplication {

    public static void main(String[] args) {

        SpringApplication.run(EurekaServerApplication.class, args);

    }

}


7.4 运行时界面如下

 


其他还有一些高级用法,就具体问题具体分析了


8.全链路监控服务Zipkin Server

8.1 pom.xml

<dependency>

      <groupId>org.springframework.cloud</groupId>

      <artifactId>spring-cloud-starter-eureka-server</artifactId>

</dependency>

<dependency>

      <groupId>io.zipkin.java</groupId>

      <artifactId>zipkin-server</artifactId>

</dependency>

<dependency>

      <groupId>io.zipkin.java</groupId>

      <artifactId>zipkin-autoconfigure-ui</artifactId>

</dependency>

<dependency>

<groupId>io.zipkin.java</groupId>

      <artifactId>zipkin-storage-mysql</artifactId>

      <version>1.19.0</version>

</dependency>

<dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-jdbc</artifactId>

</dependency>

<dependency>

      <groupId>mysql</groupId>

      <artifactId>mysql-connector-java</artifactId>

</dependency>


8.2 Bootstrap.yml

server:

  port: ${SERVER_PORT:16662}

spring:

  rabbitmq:

    host: ${RABBIT_HOST:localhost}

  datasource:

    url: jdbc:mysql://${SERVER_NAME:rm-uf637082fw6y68ufh.mysql.rds.aliyuncs.com}:${SERVER_PORT:3306}/${DATABASE_NAME:zipkin_91pay}

    username: ${MYSQL_USERNAME:payservice}

    password: ${MYSQL_PASSWORD:ADdKN0oZIQYH}

    # Switch this on to create the schema on startup:

    schema: classpath:/mysql.sql

    initialize: false

    continueOnError: true

  zipkin:

    base-url: http://${ZIPKIN_URL:10.200.110.8}:${ZIPKIN_PORT:16662}

  sleuth:

    enabled: true

zipkin:

  storage:

    type: mysql


8.3 ZipkinServerApplication.java

最后加上这几个,就跑起来就好了。

@SpringBootApplication

@EnableZipkinServer

public class ZipkinServerApplication {

    public static void main(String[] args) {

        SpringApplication.run(ZipkinServerApplication.class, args);

    }

    

    @Bean

    public MySQLStorage mySQLStorage(DataSource datasource) {

        return MySQLStorage.builder().datasource(datasource).executor(Runnable::run).build();

    }

    

}

8.4 客户端sleuth配置

然后客户端要使用zipkin server需要在bootstrap.yml配置里面加上。

bootstrap.yml

#zipkin

spring.zipkin.enabled=true

spring.zipkin.baseUrl=http://172.20.67.15:16662

spring.sleuth.sampler.percentage=0.1

Pom.xml里面加上

Pom.xml

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-sleuth</artifactId>

</dependency>

就可爽爽的使用sleuth往zipkin里面发数据啦。


8.5 运行时界面如下。

 


其他还有一些高级用法,就具体问题具体分析了


9.配置服务Config Server

9.1. Pom.xml

<dependencies>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-config-server</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-eureka</artifactId>

    </dependency>

</dependencies>


9.2. ConfigServerApplication.java

@SpringBootApplication

@EnableConfigServer

@EnableEurekaClient

@EnableAutoConfiguration

public class ConfigServerApplication {

public static void main(String[] args) {

SpringApplication.run(PayConfigServerApplication.class, args);

}

}


9.3. Config server 的yml的配置

server:

  port: 10663


eureka:

  client:

    serviceUrl:

      #eureka服务注册地址

      defaultZone: http://172.20.67.15:10661/eureka/


# git管理配置

spring:

  cloud:

    config:

      server:

        git:

          #git仓库地址

          uri: http://10.66.1.168:10080/91Pay/config-server

          #搜索路径配成变量,这样不同客户端会请求自己的目录名

          searchPaths: '{application}'

          username: wangfupeng@91steel.com

          password: Fff66p66p66p

  application:

    name: config-server

management:

  security:

enabled: false


如果有必要可以把config server配置到eureka上去也是支持的。



9.4. Client端的Pom.xml

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-config</artifactId>

</dependency>

9.5 Client端的在代码中的使用

在使用时用

@Value("${lucky-word}") 

String luckyWord;

把值注入进变量就好。


9.6 Client端的yml中的配置:

环境资源的命名规则由以下的三个参数确定:

{application}映射到Config客户端的spring.application.name属性

{profile}映射到Config客户端的spring.profiles.active属性,可以用来区分环境,比如dev,test,produce等等

{label}映射到Git服务器的commit id,分支名称或者tag,默认值为master

所以配置如下:

spring.application.name=accountServer

spring.profiles.active=dev

spring.cloud.config.label=master

spring.cloud.config.uri=http://localhost:8888

如果spring.cloud.config.uri没有配置,然后从eureka上面去发现config server也是可以的。

这样就是到configserver上的master分支上的accountServer目录里面的accountServer-dev.yml上面去找资料了。


其他还有一些高级用法,就具体问题具体分析了


10.各种命名规范

10.1变量命名规范。


强制要求所有变量命名用类名首字母小写,然后在后面加上适当含义 。

比如

JedisPool jedisPool 合规

JedisPool jedisPoolForAccountServer. 合规


JedisPool hcc     不合规


10.2 强制要求所有魔法值全部用KeyCommon这个类里的属性来替代。

比如.andIsAdminEqualTo(true).andStatusEqualTo("40");

要改成

.andIsAdminEqualTo(true).andStatusEqualTo(KeyCommon.STATUS_COMPLETE_VERIFY);

然后在KeyCommon里面写一个

public static final String STATUS_COMPLETE_VERIFY = "40";


10.3 所有抛出的异常在TemplateErrorCode里面定义。

 


使用方式用throw new 

TemplateException(TemplateErrorCode.LIMIT_PROGRAM_AOP_PREFERENCE_ERROR);

在要抛出异常的地方抛出异常即可。


10.4 方法名命名规范

用有意义的英文单词来做命名。遵从驼峰标志。



11. 模板使用方法

11.1 从git上面下载代码,查看章节2。

 


11.2用STS打开。STS下载地址在http://spring.io/tools/sts

 

下载后,解压缩。运行STS.exe


11.3 配置好maven和jdk

 


 


Maven的Settings.xml配置如下

已经删除了无用的注释和没有用的组件。

<?xml version="1.0" encoding="UTF-8"?>

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <localRepository>c:/java/maven/repository6</localRepository>

  <pluginGroups>

  </pluginGroups>

  <servers>

  </servers> 

  <proxies>

  </proxies>

  <mirrors>

    <mirror>

      <id>Fff666666</id>

      <mirrorOf>central</mirrorOf>

      <name>Maven Repository Caituo</name>

      <url>http://10.66.1.40:8081/nexus/content/groups/public/</url>

    </mirror>

  </mirrors>

  <profiles>

    <profile>

      <id>caituo</id>

      <repositories>

        <repository>

          <id>caituo</id>

          <name>Caituo Repositories Group</name>

          <url>http://10.66.1.40:8081/nexus/content/groups/public/</url>

 <snapshots>

<enabled>true</enabled>

 </snapshots>

        </repository>

      </repositories>

    </profile>

  </profiles>

  <activeProfiles>

    <activeProfile>caituo</activeProfile>

  </activeProfiles>

</settings>


 


11.3 导入template源码

 


 


 


Maven Update一下下载相应的jar包。

只要你配的nexus服务器是10.66.1.40. 能确保加载成功,没有报异常。

 


 


11.4 重命名模板里面的文件夹名称或者更改目录结构,改成自己要的包名。

 


11.5 把com.caituo.template替换成自己的包名。

 


要全部都替换。

 


 



11.6 启动方法

开发时的启动方法就时Application.java->右键->Debug As->Java Application


 


在服务器上面启动方法是:

1. 先maven install成一个jar包假设名字叫zzzzzz-66601.jar

2. 在secureCRT用sz命令上传至服务器。如果没有sz可以用yum install lrzsz安装。

3. 用这个命令运行起来就好了。

nohup java –jar zzzzzz-66601.jar –-ENV=prod >/dev/null &

如果java没有找着,可以带上java的全路径。


12.附上之前做的一整套架构。

 


其中有几个不足:


1. Redis版本低2.8.7,没法做Cluster,如果用redis cluster(版本3.0+)就可以不用shardedJedisPool。其实差不多。


2. ElasticSearch对大数据量查询(返回数据10000条+)支持很差。对小数据量查询(返回数据100条以内)支持非常好。


13.阿里巴巴的P3C标准

13.1. P3C标准的pdf文档

 


13.2.P3C的Eclipse插件安装办法及启动检查

1. Help->Install New Software

 

输入https://p3c.alibaba.com/plugin/eclipse/update, 按回车,选中插件,

点Next->Next->I Accept -> Finish

 

 

 

重启STS

再右键选中项目。会出来一个

 


点击开始扫描。

扫描结果在P3C Results里面有

 

要把所有的提示全部清除掉

更改时在当前STS里改会很慢,建议再起一个没有装P3C的STS来改。

P3C只是在扫描代码时使用。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
5天前
|
安全 Java 测试技术
Spring Boot集成支付宝支付:概念与实战
【4月更文挑战第29天】在电子商务和在线业务应用中,集成有效且安全的支付解决方案是至关重要的。支付宝作为中国领先的支付服务提供商,其支付功能的集成可以显著提升用户体验。本篇博客将详细介绍如何在Spring Boot应用中集成支付宝支付功能,并提供一个实战示例。
20 2
|
5天前
|
Java 关系型数据库 数据库
Spring Boot多数据源及事务管理:概念与实战
【4月更文挑战第29天】在复杂的企业级应用中,经常需要访问和管理多个数据源。Spring Boot通过灵活的配置和强大的框架支持,可以轻松实现多数据源的整合及事务管理。本篇博客将探讨如何在Spring Boot中配置多数据源,并详细介绍事务管理的策略和实践。
24 3
|
3天前
|
JSON Java Apache
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
|
4天前
|
XML Java API
Spring Boot 整合 LiteFlow 规则引擎:概念与实战
【4月更文挑战第30天】在现代软件开发中,规则引擎允许我们以声明式的方式定义业务逻辑和决策路径。LiteFlow 是一个轻量级、易于使用的组件式规则引擎,它可以与 Spring Boot 应用无缝整合。本文将介绍如何在 Spring Boot 项目中引入 LiteFlow,实现灵活的业务流程管理。
16 0
|
4天前
|
负载均衡 Java 开发者
Spring Cloud:一文读懂其原理与架构
Spring Cloud 是一套微服务解决方案,它整合了Netflix公司的多个开源框架,简化了分布式系统开发。Spring Cloud 提供了服务注册与发现、配置中心、消息总线、负载均衡、熔断机制等工具,让开发者可以快速地构建一些常见的微服务架构。
|
5天前
|
安全 Java 测试技术
利用Java反射机制提高Spring Boot的代码质量:概念与实战
【4月更文挑战第29天】Java反射机制提供了一种强大的方法来在运行时检查或修改类和对象的行为。在Spring Boot应用中,合理利用反射可以提高代码的灵活性和可维护性。本篇博客将探讨Java反射的核心概念,并展示如何通过反射提高Spring Boot项目的代码质量。
20 0
|
5天前
|
监控 Java 测试技术
Spring Boot与事务钩子函数:概念与实战
【4月更文挑战第29天】在复杂的业务逻辑中,事务管理是确保数据一致性和完整性的关键。Spring Boot提供了强大的事务管理机制,其中事务钩子函数(Transaction Hooks)允许开发者在事务的不同阶段插入自定义逻辑。本篇博客将详细探讨事务钩子函数的概念及其在Spring Boot中的应用。
15 1
|
5天前
|
安全 Java 数据安全/隐私保护
Spring Boot优雅实现多租户架构:概念与实战
【4月更文挑战第29天】在多租户系统中,一个应用实例服务于多个租户,每个租户享有独立的数据视图,而应用的基础设施被共享。这样的架构不仅优化了资源使用,还能降低维护和运营成本。本文将详细介绍如何在Spring Boot中实现多租户架构,并提供具体的实战案例。
26 2
|
5天前
|
前端开发 Java 数据安全/隐私保护
Spring Boot使用拦截器:概念与实战
【4月更文挑战第29天】拦截器(Interceptors)在Spring Boot应用中常用于在请求处理的前后执行特定的代码,如日志记录、认证校验、权限控制等。本篇博客将详细介绍Spring Boot中拦截器的概念及其实战应用,帮助开发者理解和利用拦截器来增强应用的功能。
15 0
|
5天前
|
Java 调度 开发者
Spring Boot与定时任务:整合与实战
【4月更文挑战第29天】定时任务是现代应用中常见的需求,用于执行周期性的活动,如数据备份、报告生成等。Spring Boot通过集成Spring Task的功能,提供了一种简单有效的方式来调度和执行定时任务。
19 1