how2j.cn

步骤 1 : 先运行,看到效果,再学习   
步骤 2 : 模仿和排错   
步骤 3 : 模拟回测微服务   
步骤 4 : 拓扑图点亮   
步骤 5 : 创建子模块   
步骤 6 : pom.xml   
步骤 7 : application.yml   
步骤 8 : IndexData.java   
步骤 9 : IndexDataClient   
步骤 10 : IndexDataClientFeignHystrix   
步骤 11 : BackTestService   
步骤 12 : BackTestController   
步骤 13 : TrendTradingBackTestServiceApplication   
步骤 14 : 测试   

步骤 1 :

先运行,看到效果,再学习

edit
老规矩,先下载右上角的可运行项目,配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。
先启动 EurekaServerApplication
然后启动 IndexDataApplication
最后启动 TrendTradingBackTestServiceApplication
注: 记得运行redis-server.exe 以启动 redis 服务器
访问地址:

http://127.0.0.1:8051/simulate/000300
先运行,看到效果,再学习
在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。
模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较正确答案 ( 可运行项目 ) 和自己的代码,来定位问题所在。
采用这种方式,学习有效果,排错有效率,可以较为明显地提升学习速度,跨过学习路上的各个槛。

推荐使用diffmerge软件,进行文件夹比较。把你自己做的项目文件夹,和我的可运行项目文件夹进行比较。
这个软件很牛逼的,可以知道文件夹里哪两个文件不对,并且很明显地标记出来
这里提供了绿色安装和使用教程:diffmerge 下载和使用教程
步骤 3 :

模拟回测微服务

edit
在模拟回测视图那里需要很多的数据,这些数据都是从这个模拟回测服务里产生的。 虽然现在看上去只有单纯的指数原数据,但是随着业务的增加,功能的迭代,会有越来越丰富的数据产生出来啦。
拓扑图点亮
创建子模块: trend-trading-backtest-service
创建子模块
比起以前的多了一个 spring-cloud-starter-openfeign jar 用于启动 Feign 方式访问其他微服务。
<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>cn.how2j.trend</groupId> <artifactId>trendParentProject</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>trend-trading-backtest-service</artifactId> <dependencies> <!-- springboot web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- eureka-client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- feign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- 断路器 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> </dependencies> </project>
需要注意,这里增加了

feign.hystrix.enabled: true

用于开启 feign 模式的断路器
feign 模式是什么意思呢? 在接下来的 IndexDataClient 就会运用了。
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: trend-trading-backtest-service feign.hystrix.enabled: true
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name:  trend-trading-backtest-service

feign.hystrix.enabled: true
package cn.how2j.trend.pojo; public class IndexData { String date; float closePoint; public String getDate() { return date; } public void setDate(String date) { this.date = date; } public float getClosePoint() { return closePoint; } public void setClosePoint(float closePoint) { this.closePoint = closePoint; } }
package cn.how2j.trend.pojo;

public class IndexData {

	String date;
	float closePoint;
	public String getDate() {
		return date;
	}
	public void setDate(String date) {
		this.date = date;
	}
	public float getClosePoint() {
		return closePoint;
	}
	public void setClosePoint(float closePoint) {
		this.closePoint = closePoint;
	}
	
}
使用 feign 模式从 INDEX-DATA-SERVICE 微服务获取数据。
与之前使用的 RestTemplate 方式不同,这里是声明式的。

fallback = IndexDataClientFeignHystrix.class)

这句话表示访问不了的时候,就去找 IndexDataClientFeignHystrix 要数据了。
package cn.how2j.trend.client; import java.util.List; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import cn.how2j.trend.pojo.IndexData; @FeignClient(value = "INDEX-DATA-SERVICE",fallback = IndexDataClientFeignHystrix.class) public interface IndexDataClient { @GetMapping("/data/{code}") public List<IndexData> getIndexData(@PathVariable("code") String code); }
package cn.how2j.trend.client;

import java.util.List;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import cn.how2j.trend.pojo.IndexData;

@FeignClient(value = "INDEX-DATA-SERVICE",fallback = IndexDataClientFeignHystrix.class)
public interface IndexDataClient {
    @GetMapping("/data/{code}")
    public List<IndexData> getIndexData(@PathVariable("code") String code);
}
步骤 10 :

IndexDataClientFeignHystrix

edit
IndexDataClientFeignHystrix 实现了 IndexDataClient,所以就提供了对应的方法,当熔断发生的时候,对应的方法就会被调用了。
这里的方法就是指如果 INDEX-DATA-SERVICE 不可用或者不可访问,就会返回个 0000-00-00 出去啦。
package cn.how2j.trend.client; import java.util.List; import org.springframework.stereotype.Component; import cn.how2j.trend.pojo.IndexData; import cn.hutool.core.collection.CollectionUtil; @Component public class IndexDataClientFeignHystrix implements IndexDataClient { @Override public List<IndexData> getIndexData(String code) { IndexData indexData = new IndexData(); indexData.setClosePoint(0); indexData.setDate("0000-00-00"); return CollectionUtil.toList(indexData); } }
这就是用于提供所有模拟回测数据的微服务了。 当然,现在比较简单,随着业务的增加和功能的迭代,就会越来愈丰富起来了。
站长用这种由浅入深的方式来把这个复杂的服务逐渐发展起来,大家通过这个过程参与进来会更加容易理解和消化。
package cn.how2j.trend.service; import cn.how2j.trend.client.IndexDataClient; import cn.how2j.trend.pojo.IndexData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; @Service public class BackTestService { @Autowired IndexDataClient indexDataClient; public List<IndexData> listIndexData(String code){ List<IndexData> result = indexDataClient.getIndexData(code); Collections.reverse(result); for (IndexData indexData : result) { System.out.println(indexData.getDate()); } return result; } }
步骤 12 :

BackTestController

edit
控制器,返回的数据是放在一个 Map 里的,而目前的key是 indexDatas。
因为将来会返回各种各样的数据,通过这种方式才好区分不同的数据。
package cn.how2j.trend.web; import cn.how2j.trend.pojo.IndexData; import cn.how2j.trend.service.BackTestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController public class BackTestController { @Autowired BackTestService backTestService; @GetMapping("/simulate/{code}") @CrossOrigin public Map<String,Object> backTest(@PathVariable("code") String code) throws Exception { List<IndexData> allIndexDatas = backTestService.listIndexData(code); Map<String,Object> result = new HashMap<>(); result.put("indexDatas", allIndexDatas); return result; } }
步骤 13 :

TrendTradingBackTestServiceApplication

edit
启动类,注意一下:
@EnableFeignClients 这个注解用与启动 Feign 方式。
package cn.how2j.trend; import cn.hutool.core.convert.Convert; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.NetUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; import java.util.Scanner; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient @EnableFeignClients public class TrendTradingBackTestServiceApplication { public static void main(String[] args) { int port = 0; int defaultPort = 8051; int eurekaServerPort = 8761; if(NetUtil.isUsableLocalPort(eurekaServerPort)) { System.err.printf("检查到端口%d 未启用,判断 eureka 服务器没有启动,本服务无法使用,故退出%n", eurekaServerPort ); System.exit(1); } if(null!=args && 0!=args.length) { for (String arg : args) { if(arg.startsWith("port=")) { String strPort= StrUtil.subAfter(arg, "port=", true); if(NumberUtil.isNumber(strPort)) { port = Convert.toInt(strPort); } } } } if(0==port) { Future<Integer> future = ThreadUtil.execAsync(() ->{ int p = 0; System.out.printf("请于5秒钟内输入端口号, 推荐 %d ,超过5秒将默认使用 %d ",defaultPort,defaultPort); Scanner scanner = new Scanner(System.in); while(true) { String strPort = scanner.nextLine(); if(!NumberUtil.isInteger(strPort)) { System.err.println("只能是数字"); continue; } else { p = Convert.toInt(strPort); scanner.close(); break; } } return p; }); try{ port=future.get(5,TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e){ port = defaultPort; } } if(!NetUtil.isUsableLocalPort(port)) { System.err.printf("端口%d被占用了,无法启动%n", port ); System.exit(1); } new SpringApplicationBuilder(TrendTradingBackTestServiceApplication.class).properties("server.port=" + port).run(args); } }
先启动 EurekaServerApplication
然后启动 IndexDataApplication
最后启动 TrendTradingBackTestServiceApplication
访问地址:

http://127.0.0.1:8051/simulate/000300
测试


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 回收站-------不要的------模拟回测微服务 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图