接口实现 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:} spring:
application:
name: scot-commons eureka:
client:
serviceUrl:
defaultZone: http://localhost:/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:}
servlet:
session:
timeout: spring:
application:
name: scot-web
session:
store-type: redis
redis:
flush-mode: ON_SAVE
namespace: spring:session redis:
host: 127.0.0.1
port:
database:
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:/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. 使用字符串, 自己做转换

.

Spring Cloud开发实践 - 03 - 接口实现和下游调用的更多相关文章

  1. Spring Cloud开发实践 - 01 - 简介和根模块

    简介 使用Spring Boot的提升主要在于jar的打包形式给运维带来了很大的便利, 而Spring Cloud本身的优点不是那么明显, 相对于Dubbo而言, 可能体现在跨语言的交互性上(例如可以 ...

  2. Spring Cloud开发实践 - 02 - Eureka服务和接口定义

    服务注册 EurekaServer Eureka服务模块只有三个文件, 分别是pom.xml, application.yml 和 EurekaServerApplication.java, 内容如下 ...

  3. Spring Cloud开发实践 - 04 - Docker部署

    Docker的安装和命令可以参考 https://www.cnblogs.com/milton/p/9866963.html . 资源规划 这一步要区分传统资源和Docker资源, 为后面的细节定好基 ...

  4. Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)

    一.背景 在我上一篇文章<Spring Cloud开发人员如何解决服务冲突和实例乱窜?>中提到使用服务的元数据来实现隔离和路由,有朋友问到能不能直接通过IP来实现?本文就和大家一起来讨论一 ...

  5. Spring Cloud(三):服务提供与调用 Eureka【Finchley 版】

    Spring Cloud(三):服务提供与调用 Eureka[Finchley 版]  发表于 2018-04-15 |  更新于 2018-05-07 |  上一篇文章我们介绍了 Eureka 服务 ...

  6. Spring AOP开发时如何得到某个方法内调用的方法的代理对象?

    Spring AOP开发时如何得到某个方法内调用的方法的代理对象? 问题阅读起来拗口,看代码 在方法中调用其他方法很常见,也经常使用,如果在一个方法内部调用其他方法,比如 public class U ...

  7. Spring cloud项目实践(一)

    链接地址:http://sail-y.github.io/2016/03/21/Spring-cloud%E9%A1%B9%E7%9B%AE%E5%AE%9E%E8%B7%B5/ 什么是Spring ...

  8. spring/spring boot/spring cloud开发总结

    背景        针对RPC远程调用,都在使用dubbo.dubbox等,我们也是如此.由于社区暂停维护.应对未来发展,我们准备尝试新技术(或许这时候也不算什么新技术了吧),选择使用了spring ...

  9. Spring Cloud开发人员如何解决服务冲突和实例乱窜?

    一.背景 在我们开发微服务架构系统时,虽然说每个微服务都是孤立的可以单独开发,但实际上并非如此,要调试和测试你的服务不仅需要您的微服务启动和运行,还需要它的上下文服务.依赖的基础服务等都要运行:但如果 ...

随机推荐

  1. linux驱动编写(电源管理驱动)

    对于嵌入式设备来说,合适的电源管理,不仅可以延长电池的寿命,而且可以省电,延长设备运行时间,在提高用户体验方面有很大的好处.所以,各个soc厂家在这方面花了很多的功夫.下面,我们可以看看linux是如 ...

  2. iOS开发-UIActionSheet简单介绍

    UIActionSheet和UIAlertView都是ios系统自带的模态视图,模态视图的一个重要的特性就是在显示模态视图的时候可以阻断其他视图的事件响应.一般情况下我们对UIAlertView使用的 ...

  3. Angular2 -- 生命周期钩子

    组件生命周期钩子 指令和组件的实例有一个生命周期:新建.更新和销毁. 每个接口都有唯一的一个钩子方法,它们的名字是由接口名加上 ng前缀构成的.比如,OnInit接口的钩子方法叫做ngOnInit. ...

  4. 用Python开始机器学习(2:决策树分类算法)

    http://blog.csdn.net/lsldd/article/details/41223147 从这一章开始进入正式的算法学习. 首先我们学习经典而有效的分类算法:决策树分类算法. 1.决策树 ...

  5. java中两种发起POST请求,并接收返回的响应内容的方式  (转)

    http://xyz168000.blog.163.com/blog/static/21032308201162293625569/ 2.利用java自带的java.net.*包下提供的工具类 代码如 ...

  6. Altium Designer 基本封装

    1. 按键的绘制和封装怎么画?如下图: 回答:注意元件的画法不要看错了,封装采用Miscellaneous Devices.IntLib[Footprint View]中的DPST-4 2.蜂鸣器的绘 ...

  7. dubbo Framework pic

    dubbo Framework pic

  8. linux不解压超大日志gz包直接查找特定内容

    gzip -dc myfile.gz | grep 'Exception' | more 或者 gzip -c myfile.gz | grep 'Exception' | more

  9. 关于 URL 编码及 JavaScript 编码函数【转载+整理】

    原文地址:http://www.ruanyifeng.com/blog/2010/02/url_encoding.html 本文内容 引入 环境 测试 JavaScript 编码函数   引入 URL ...

  10. 1418 This function has none of DETERMINISTIC,NO SQL,or R

    标签: [err]1418 函数创建报错 分类: 菜鸟DBA之MySQL --------------------------------------------------------------- ...