接口实现 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. .Net-using-Class:String 类

    ylbtech-.Net-using-Class:String类 1. 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b ...

  2. Win2008建立域时administrator账户密码不符合要求

    在win2008中建立域时,有时会出现administrator账户密码不符合要求的现象,报错会说明目前本地administrator账户不需要密码.这是什么原因造成的呢?原来,目前的2008镜像在网 ...

  3. window.open 浏览器差异.

    首先引入 w3help的,莫的测试: 原帖地址:http://www.w3help.org/zh-cn/causes/BX1053   w3help的测试,和我的测试相互补充,应该比较完整了.悲剧的是 ...

  4. ubuntu服务器常见使用技巧及-kill掉后GPU显存不释放进程-

    如何解决python进程被kill掉后GPU显存不释放的问题 1 重新开一个shell,然后输入: ps aux|grep user_name|grep python.所有该用户下的python程序就 ...

  5. MySQL 高可用性—keepalived+mysql双主(有详细步骤和全部配置项解释)

    博主QQ:819594300 博客地址:http://zpf666.blog.51cto.com/ 有什么疑问的朋友可以联系博主,博主会帮你们解答,谢谢支持! 前言:生产环境中一台mysql主机存在单 ...

  6. iOS开发中FMDB的使用

    1.什在日常的开发中,我们需要用到离线缓存将数据信息存入数据库,在没有网络的时候进行加载,而我们IOS用的就是sqlite3数据库,用原生的sql我们也能实现,但是书写起来比较麻烦,尤其是其它语言转过 ...

  7. Python3 比较两个图片是否类似或相同

    Python代码 #coding:utf8 import os from PIL import Image,ImageDraw,ImageFile import numpy import pytess ...

  8. Laravel应用性能调优

    这次性能测试方案中用到的优化技巧主要基于 Laravel 框架本身及其提供的工具. 关闭应用debugapp.debug=false 缓存配置信息php artisan config:cache 缓存 ...

  9. SVN迁移部署

    迁移svn并修改目录结构的方法 http://blog.csdn.net/jianxin1009/article/details/8220461 测试成功的命令: svnadmin –parent-d ...

  10. codeforces 551 C GukiZ hates Boxes

    --睡太晚了. ..脑子就傻了-- 这个题想的时候并没有想到该这样-- 题意大概是有n堆箱子从左往右依次排列,每堆ai个箱子,有m个人,最開始都站在第一个箱子的左边, 每个人在每一秒钟都必须做出两种选 ...