步骤 2 : 模仿和排错 步骤 3 : 拓扑图点亮 步骤 4 : 创建子模块 步骤 5 : pom.xml 步骤 6 : application.yml 步骤 7 : TrendTradingBackTestViewApplication 步骤 8 : ViewController 步骤 9 : static 步骤 10 : header.html 步骤 11 : footer.html 步骤 12 : view.html
老规矩,先下载右上角的可运行项目,配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。
首先启动 EurekaServerApplication 然后启动 TrendTradingBackTestViewApplication 注: 记得运行redis-server.exe 以启动 redis 服务器 访问地址: http://127.0.0.1:8041/ 就可以看到如图所示的视图效果了,虽然看上去很苍白。。。但是是把架子搭起来了~~
在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。
模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较正确答案 ( 可运行项目 ) 和自己的代码,来定位问题所在。 采用这种方式,学习有效果,排错有效率,可以较为明显地提升学习速度,跨过学习路上的各个槛。 推荐使用diffmerge软件,进行文件夹比较。把你自己做的项目文件夹,和我的可运行项目文件夹进行比较。 这个软件很牛逼的,可以知道文件夹里哪两个文件不对,并且很明显地标记出来 这里提供了绿色安装和使用教程:diffmerge 下载和使用教程
创建子模块: trend-trading-backtest-view
增加 spring-boot-starter-thymeleaf jar, 用于对 thymeleaf 进行支持
<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-view</artifactId>
<dependencies>
<!-- springboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
增加 thymeleaf 的配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: trend-trading-backtest-view
thymeleaf:
mode: LEGACYHTML5
encoding: UTF-8
content-type: text/html
cache: false
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: trend-trading-backtest-view thymeleaf: mode: LEGACYHTML5 encoding: UTF-8 content-type: text/html cache: false
启动类
package cn.how2j.trend;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
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;
@SpringBootApplication
@EnableEurekaClient
public class TrendTradingBackTestViewApplication {
public static void main(String[] args) {
int port = 0;
int defaultPort = 8041;
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(TrendTradingBackTestViewApplication.class).properties("server.port=" + port).run(args);
}
}
控制类
package cn.how2j.trend.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ViewController {
@GetMapping("/")
public String view() throws Exception {
return "view";
}
}
package cn.how2j.trend.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class ViewController { @GetMapping("/") public String view() throws Exception { return "view"; } }
增加静态资源,一大堆 js 和 css. 放在右上角 static里了。解压 复制到 resources 目录下去
简单说下: 1. bootstrap 就是 bootstrap了。。。 2. bootstrap-datepicker 是日期控件 3. axois 是做 ajax的 4. chartjs 是画图表的 5. jquery 就是 jquery 了 6. vue 就是 vue 了。。。
这是个被包含的文件,放在 如图所示的位置。
简单说下做了什么: 1. 包含了各种 css 2. 包含了各种 js 3. 自定义了几个函数: formatMoney 格式化金额 formatNumber 格式化数字 4. 创建几个过滤器方便 vue 来使用 formatMoneyFilter 格式化金额 formatNumberFilter 格式化数字 formatDateFilter 格式化日期 <template th:fragment="html(title)" >
<link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap-datepicker/1.8.0/bootstrap-datepicker.min.css" rel="stylesheet">
<script src="js/jquery/2.0.0/jquery.min.js"></script>
<script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
<script src="js/vue/2.5.16/vue.min.js"></script>
<script src="js/chartjs/2.8.0/chart.min.js"></script>
<script src="js/axios/0.17.1/axios.min.js"></script>
<script src="js/bootstrap-datepicker/1.8.0/bootstrap-datepicker.min.js"></script>
<script src="js/bootstrap-datepicker/1.8.0/bootstrap-datepicker.zh-CN.min.js"></script>
<script>
function formatMoney(num){
num = new String(num);
num = num.toString().replace(/\$|\,/g,'');
if(isNaN(num))
num = "0";
sign = (num == (num = Math.abs(num)));
num = Math.floor(num*100+0.50000000001);
cents = num%100;
num = Math.floor(num/100).toString();
if(cents<10)
cents = "0" + cents;
for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
num = num.substring(0,num.length-(4*i+3))+','+
num.substring(num.length-(4*i+3));
return (((sign)?'':'-') + num + '.' + cents);
}
function formatNumber(number, decimals, dec_point, thousands_sep) {
/*
* 参数说明:
* number:要格式化的数字
* decimals:保留几位小数
* dec_point:小数点符号
* thousands_sep:千分位符号
* */
number = (number + '').replace(/[^0-9+-Ee.]/g, '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function (n, prec) {
var k = Math.pow(10, prec);
return '' + Math.ceil(n * k) / k;
};
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
var re = /(-?\d+)(\d{3})/;
while (re.test(s[0])) {
s[0] = s[0].replace(re, "$1" + sep + "$2");
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
Vue.filter("formatMoneyFilter", function(value){
return formatMoney(value);
});
Vue.filter("formatNumberFilter", function(value,decimal){
if(decimal==null)
decimal = 0;
return formatNumber(value,decimal, ".",",");
});
Vue.filter('formatDateFilter', function (value, formatString) {
if(null==value)
return "";
formatString = formatString || 'YYYY-MM-DD';
return moment(value).format(formatString);
});
</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title th:text="${title}" ></title>
</template>
页脚
<div th:fragment="html">
<div style="margin:0px auto;text-align:center">
powered by <a href="http://how2j.cn">how2j.cn</a> version 1.0.1
</div>
</div>
<div th:fragment="html"> <div style="margin:0px auto;text-align:center"> powered by <a href="http://how2j.cn">how2j.cn</a> version 1.0.1 </div> </div>
业务页面,做了如下几件事情。
1. 在开始包含了 header.html 2. 在结束包含了 footer.html 3. 做了 vue 的框架搭建,虽然什么都没做,先放在这里了,后面直接在这个基础上修改就是了 4. 有一些当前页面的简单 样式 5. 工作区div: workingArea 6. 本页唯一的内容,一个span: <span class="label label-info">回测参数</span> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="include/header::html('趋势投资模拟回测')" ></head>
<body >
<script>
$(function(){
var data4Vue = {
};
//ViewModel
var vue = new Vue({
el: '#workingArea',
data: data4Vue,
mounted:function(){ //mounted 表示这个 Vue 对象加载成功了
this.init();
},
methods: {
init:function(){
}
}
});
});
</script>
<style>
table.inputTable{
width:100%;
}
table.inputTable td{
padding:20px 20px;
}
table{
margin:20px;
}
div#workingArea{
margin:50px;
}
</style>
<div id="workingArea">
<span class="label label-info">回测参数</span>
</div>
<div th:replace="include/footer::html" ></div>
</body>
</html>
HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。
提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
|