how2j.cn

步骤 1 : 先运行,看到效果,再学习   
步骤 2 : 模仿和排错   
步骤 3 : 拓扑图点亮   
步骤 4 : 创建子模块   
步骤 5 : pom.xml   
步骤 6 : application.yml   
步骤 7 : TrendTradingBackTestViewApplication   
步骤 8 : ViewController   
步骤 9 : static   
步骤 10 : header.html   
步骤 11 : footer.html   
步骤 12 : view.html   

步骤 1 :

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

edit
老规矩,先下载右上角的可运行项目,配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。
首先启动 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
步骤 7 :

TrendTradingBackTestViewApplication

edit
启动类
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 了。。。
static
这是个被包含的文件,放在 如图所示的位置。
简单说下做了什么:
1. 包含了各种 css
2. 包含了各种 js
3. 自定义了几个函数:

formatMoney 格式化金额
formatNumber 格式化数字

4. 创建几个过滤器方便 vue 来使用

formatMoneyFilter 格式化金额
formatNumberFilter 格式化数字
formatDateFilter 格式化日期
header.html
<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公众号,关注后实时获知最新的教程和优惠活动,谢谢。


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

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

上传截图