接口實現 Scot Commons Impl
接口實現模塊 scot-commons-impl, 一方面實現了 scot-commons-api 的接口, 一方面將自己暴露為 REST 服務. 有4個文件, 分別為 pom.xml, application.yml, ServiceImplApplication.xml 和 UserDTOServiceImpl.java
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.rockbb</groupId> <artifactId>scot</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../scot/pom.xml</relativePath> </parent> <artifactId>scot-commons-impl</artifactId> <packaging>jar</packaging> <name>Scot: Commons Implementation</name> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>com.rockbb</groupId> <artifactId>scot-commons-api</artifactId> <version>${project.version}</version> </dependency> </dependencies> <build> <finalName>scot-commons</finalName> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build> </project>
application.yml
server: port: ${PORT:8762} spring: application: name: scot-commons eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
ServiceImplApplication.java
這里不能引入FeignClient, 以免激活api中的注解.
@EnableEurekaClient @SpringBootApplication public class ServiceImplApplication { public static void main(String[] args) { SpringApplication.run(ServiceImplApplication.class, args); } }
UserDTOServiceImpl.java
在UserDTOServiceImpl.java中, 實現了UserDTOService的接口, 因為這里的RequestMapping就是FeignClient將要讀取的路徑, 所以可以原封不動地將UserDTOService中的定義復制到這里. 統一了接口與實現.
@RequestMapping("/user") @RestController public class UserDTOServiceImpl implements UserDTOService { @Value("${spring.cloud.client.hostname}") String ipAddress; @Value("${server.port}") String port; @Value("${spring.application.name}") String applicationName; @Override @RequestMapping(value = "/diagnos", method = RequestMethod.GET) public String diagnos(@RequestParam String name) { return ipAddress+":"+port+":"+applicationName+": " + name; } @Override @RequestMapping(value = "/get", method = RequestMethod.GET) public UserDTO get(@RequestParam String id) { return new UserDTO().initialize("3utowired5nnotation9ean0osterocessor", "system"); } @Override @RequestMapping(value = "/list", method = RequestMethod.GET) public List<UserDTO> list() { return new ArrayList<>(); } @Override @RequestMapping(value = "/count", method = RequestMethod.GET) public long count() { return 99; } }
下游調用 Scot Web
在這個模塊中主要實現了兩個功能, 一是通過scot-commons-api的定義引用scot-commons-impl中的服務, 二是使用redis保存HttpSession. 這個模塊一共有4個文件: pom.xml, application.yml, WebApplication.java 和 IndexController.java
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.rockbb</groupId> <artifactId>scot</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../scot/pom.xml</relativePath> </parent> <artifactId>scot-web</artifactId> <packaging>jar</packaging> <name>Scot: Web</name> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <dependency> <groupId>com.rockbb</groupId> <artifactId>scot-commons-api</artifactId> <version>${project.version}</version> </dependency> </dependencies> <build> <finalName>scot-web</finalName> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build> </project>
application.yml
server: port: ${PORT:8763} servlet: session: timeout: 600 spring: application: name: scot-web session: store-type: redis redis: flush-mode: ON_SAVE namespace: spring:session redis: host: 127.0.0.1 port: 6379 database: 2 password: foobar logging: pattern: console: '%d{yyMMdd HH:mm:ssSSS} %8.8thread %1.-1level %25.25logger{50}#%4.4line %msg%n' level: com.rockbb: DEBUG eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ registerWithEureka: false
WebApplication.java
@EnableFeignClients 需要指定 basePackages, 否則不會去jar中掃描
@EnableDiscoveryClient @EnableFeignClients(basePackages = {"com.rockbb.scot.commons.api"}) @SpringBootApplication public class WebApplication { public static void main(String[] args) { SpringApplication.run(WebApplication.class, args); } }
IndexController.java
這里可以直接Autowire或Resource引用scot-commons的服務.
直接用瀏覽器訪問的話, 返回的格式實際上是根據request header來判斷的, 如果要強制返回json格式, 需要加上 produces = "application/json"
@RestController public class IndexController { private static Logger logger = LoggerFactory.getLogger(IndexController.class); @Resource private UserDTOService userDTOService; @RequestMapping(value = "/test1",method = RequestMethod.GET) public String test1(@RequestParam String name){ logger.debug("/test1"); return userDTOService.diagnos(name); } @RequestMapping(value = "/test11",method = RequestMethod.GET, produces = "application/json") public String test11(@RequestParam String name){ return userDTOService.diagnos(name); } @RequestMapping(value = "/test2",method = RequestMethod.GET) public UserDTO test2(@RequestParam String id){ return userDTOService.get(id); } @RequestMapping(value = "/test21",method = RequestMethod.GET, produces = "application/json") public UserDTO test21(@RequestParam String id){ return userDTOService.get(id); } @RequestMapping(value = "/test3",method = RequestMethod.GET) public List<UserDTO> users(@RequestParam String id){ return userDTOService.list(); } @RequestMapping(value = "/test4",method = RequestMethod.GET) public long users(){ return userDTOService.count(); } @GetMapping("/session") public String session(HttpSession session) { return session.getId(); } }
Feign Client傳參的坑
使用Date類型參數會產生14小時的時差
接口使用Date類型時, 會發現服務提供方收到的時間, 比調用方傳遞的時間要晚14個小時, 例如調用為 Thu Jul 04 19:00:00 CST 2019 收到的為 Fri Jul 05 09:00:00 CST 2019. 原因是服務端將接收的String類型日期轉換為Date類型采用的是Date的默認構造器 new Date('Thu Jul 04 19:00:00 CST 2019'), 這里就產生錯誤了, 因為CTS代表的時區有四個Central Standard Time (USA) UT-6:00、Central Standard Time (Australia) UT+9:30、China Standard Time UT+8:00、Cuba Standard Time UT-4:00, 同時表示美澳中古巴四個國家的標准時間, jvm會將CTS理解成了美國中部時區, 而美國的-6和中國的+8正好相差14個小時.
解決方案:
1. 使用json化的對象傳輸, 不會有問題
2. 使用long類型的timestamp
3. 使用字符串, 自己做轉換
.