1.定时任务调度服务XXL-JOB通过RestTemplate+多线程动态拉去股票接口数据,刷入数据库;
2.国内指数服务
3.板块指数服务
4.涨幅榜展示功能
5.涨停跌停数展示功能
6.成交量对比展示功能
7.个股涨停服务展示功能
8.个股详情展示功能包含分时行情、日k线、周K线图等
9.个股描述服务;
10.报表导出服务
开发工具版本要求:
注意事项:后期股票相关的数据量非常庞大,表与表之间尽量不要构建外键约束(提升数据库性能),同时也为后期分库分表准备!
因为我边的CentOS7连接不上 所以在这里面 用本地(windoms)运行
数据库可视化选用 SQLyog - 64 bit mysql用的是5.7.24
创建stock_parent maven工程:
接下来 复制以下maven到pom.xml
pom UTF-8 UTF-8 8 8 true 2.1.4 1.2.12 5.1.49 1.2.71 2.9.2 1.1.22 1.2.8 4.0.0-RC1 0.9.1 3.0.4 2.3.0 2.5.3 2.10.5 30.0-jre org.springframework.boot spring-boot-starter-parent ${spring-boot.version} pom import org.mybatis.spring.boot mybatis-spring-boot-starter ${mybatis-spring-boot-starter.version} com.github.pagehelper pagehelper-spring-boot-starter ${pagehelper-spring-boot-starter.version} mysql mysql-connector-java ${mysql-driver.version} org.apache.shardingsphere sharding-jdbc-spring-boot-starter ${sharding-jdbc.version} com.alibaba fastjson ${fastjson.version} com.alibaba druid-spring-boot-starter ${druid-spring-boot-starter.version} com.alibaba druid ${druid-core-version} io.springfox springfox-swagger2 ${springfox-swagger2.version} io.springfox springfox-swagger-ui ${springfox-swagger2.version} io.jsonwebtoken jjwt ${jjwt.version} com.alibaba easyexcel ${easyExcel.version} com.xuxueli xxl-job-core ${xxl-job-core.version} joda-time joda-time ${joda-time.version} com.google.guava guava ${google.guava.version} org.springframework.boot spring-boot-maven-plugin ${spring-boot.version} org.springframework.boot spring-boot-configuration-processor org.apache.maven.plugins maven-surefire-plugin ${maven.test.skip}
注意事项:
1.打包方式:pom
2.通过dependencyManagement、pluginManagement锁定开发中的依赖和插件的版本;
接下来 删除父工程的src
创建stock_parent的maven子工程stock_backend:
stock_backend工程被stock_parent父工程聚合,pom配置如下:
jar stock_backend 8 8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-aop mysql mysql-connector-java org.springframework.boot spring-boot-starter-test test org.projectlombok lombok true org.mybatis.spring.boot mybatis-spring-boot-starter com.github.pagehelper pagehelper-spring-boot-starter com.alibaba druid-spring-boot-starter org.springframework.boot spring-boot-configuration-processor true joda-time joda-time ${project.artifactId} org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-surefire-plugin
找到资料中的公共包结构
复制com
进入到项目的物理路径(IntelliJ IDEA 2020.1.3 x64)
不同的idea进行项目物理环境的选项不同
把刚才复制过来的com复制到main/java下面
这样就能得到目录结构(里面为空目录) 这样做的目的是不能一次次创建目录结构
安装
使用
生成效果
# web定义
server:port: 8081 #指定当前端口号spring:# 配置mysql数据源datasource:druid:username: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/stock_db?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.jdbc.Driver# 初始化时建立物理连接的个数。初始化发生在显示调用 init 方法,或者第一次 getConnection 时initialSize: 6# 最小连接池数量minIdle: 2# 最大连接池数量maxActive: 20# 获取连接时最大等待时间,单位毫秒。配置了 maxWait 之后,缺省启用公平锁,# 并发效率会有所下降,如果需要可以通过配置 useUnfairLock 属性为 true 使用非公平锁。maxWait: 60000# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒timeBetweenEvictionRunsMillis: 60000# 配置一个连接在池中最小生存的时间,单位是毫秒minEvictableIdleTimeMillis: 300000# 用来检测连接是否有效的 sql 因数据库方言而差, 例如 oracle 应该写成 SELECT 1 FROM DUALvalidationQuery: SELECT 1 FROM DUAL# 建议配置为 true,不影响性能,并且保证安全性。申请连接的时候检测,# 如果空闲时间大于 timeBetweenEvictionRunsMillis,执行 validationQuery 检测连接是否有效。testWhileIdle: true# 申请连接时执行 validationQuery 检测连接是否有效,做了这个配置会降低性能。testOnBorrow: false# 归还连接时执行 validationQuery 检测连接是否有效,做了这个配置会降低性能。testOnReturn: false# 是否自动回收超时连接poolPreparedStatements: truemaxPoolPreparedStatementPerConnectionSize: 20# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙filters: stat,wall# 通过connectProperties属性来打开mergeSql功能;慢SQL记录connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000# 配置mybatis
mybatis:type-aliases-package: com.itheima.stock.pojo #指定的包下类名取别名mapper-locations: classpath:mapper/*.xmlconfiguration:map-underscore-to-camel-case: true #开启驼峰映射cache-enabled: false #使全局的映射器启用或禁用缓存。lazy-loading-enabled: false #全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。aggressive-lazy-loading: true #当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。# pagehelper配置
pagehelper:helper-dialect: mysql #指定分页数据库类型(方言)reasonable: true #合理查询超过最大也,则查询最后一页support-methods-arguments: true # 支持通过Mapper接口参数来传递分页参数,默认falseparams: pacount=countSql # POJO或者Map中发现了countSql属性,就会作为count参数使用returnPageInfo: check # always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page
因为上面配置了少了一个mapper 所以我们现 在创建这个包
注意:
第一点
url: jdbc:mysql://127.0.0.1:3306/stock_db?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
这里面的url 如果是连接的是linux的 刚要写成Linux上的Ip 如果连接的是本地(win)则url 刚要写成
jdbc:mysql:///数据库名称或jdbc:mysql://localhost:3306/数据库名称jdbc:mysql://127.0.0.1:3306/数据库名称
第二点 本项目用到的mysql为5.7 不是8.0 所以把
driver-class-name: com.mysql.cj.jdbc.Driver 把cj删除
补充知识
driver-class-name: com.mysql.cj.jdbc.Driver mysql8.0
driver-class-name: com.mysql.jdbc.Driver mysql5.7
第三点 接口扫描
IntelliJ IDEA 2020.1.3 x64版本复制路径写法
视频中的idea版本复制路径写法
然后把复制过来的路径给放在下图所示
package com.itheima.stock;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.itheima.stock.mapper")
public class StockApp {public static void main(String[] args) {SpringApplication.run(StockApp.class, args);}
}
package com.itheima.stock.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class UserController {@GetMapping("/test")public String getName(){return "itheima";}}
启动:
注意:这里面启动时 要注意你连接的mysql是linux的还是本地的 要注意他们的账户和密码否正确
启动成功
在浏览器上测试能够获取到
在做接口调试的时候 在这里面建议用postman 因为用浏览器只能用到git
演示使用课程资料中的------股票API接口测试.json
至此,工程基础环境搭建完毕!
我们可借助mybatisX工具生成基础代码,步骤如下:
第一步:通过idea自带的database组件连接数据库:
全选11张表 点击第一张表 按住Shist 在点击最后一张表
右击
第二步:配置pojo实体类选项
目的:我们通过一个简单的web接口访问数据库,验证工程搭建情况
接口功能说明:查询所有上市公司主营业务数据
接口url:/api/quot/stock/business/all
StockBusinessMapper接口和xml定义查询所有股票业务信息的接口方法:
List findall();
定义服务接口:
package com.itheima.stock.service;import com.itheima.stock.pojo.StockBusiness;
import java.util.List;/*定义股票服务接口*/
public interface StockService {/*查询所有主营业务信息*/List findAll();}
定义服务接口实现:
Alt+Enter
package com.itheima.stock.service.impl;import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.pojo.StockBusiness;
import com.itheima.stock.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service("stockService")
public class StockServiceImpl implements StockService {@Autowiredprivate StockBusinessMapper stockBusinessMapper;@Overridepublic List findAll() {return stockBusinessMapper.findAll();}
}
package com.itheima.stock.controller;import com.itheima.stock.pojo.StockBusiness;
import com.itheima.stock.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/api/quot")
public class StockController {@Autowiredprivate StockService stockService;@GetMapping("/stock/business/all")public List findAllBusiness(){return stockService.findAll();}}
成功启动
至此,后台基本开发环境构建完毕!
前端node版本:
详见资料:
资料:day01\资料\前端资料\stock_front_admin
使用vscode打开工程:
效果如下:
npm run dev
这里面是8080 但是我们后端是8081 所以这里面要注意一下
注意事项:如果启动报错,重新npm install 或者cnpm install
在前面的知识中,我们已经了解到项目进行前后端分离后,存在跨域问题,只需在前端进行简单配置,即可解决该问题;
在stock_front_admin\src\settings.js文件下配置跨域:
devServer: {port: 8080,host: '127.0.0.1',// 开发hostopen:true,// 是否启动时打开浏览器disableHostCheck: true, // 映射外网时,需要设置为true/*** 域名,他将会基于 window.location来链接服务器,需要使用public配置* dev-server被代理到nginx中配置的 itheima.com*/public: "127.0.0.1:8080",//itheima.compublicPath:'/',compress:true,overlay: {// 是否在浏览器全屏显示错误与警告warnings: false,errors:true},proxy: {// 跨域请求配置"/api": {secure: false,// 关闭安全检测,默认请求 https//target: "http://192.168.188.131:8081",target: "http://localhost:8081",changeOrigin: true,// pathRewrite: {"^/api" : ""},}},},
前端与后端使用json格式进行交互。
sys_user表如下:
请求接口:/api/login
请求方式:POST
请求数据示例:{username:'zhangsan',//用户名password:'666',//密码code:'1234' //校验码}
响应数据:{"code": 1,//成功1 失败0"data": {"id":"1237365636208922624","username":"zhangsan","nickName":"xiaozhang","phone":"1886702304"}}
请求vo封装:
package com.itheima.stock.vo.req;import lombok.Data;/*用户登录请求vo*/@Data
public class LoginReqVo {/*** 用户名*/private String username;/*** 密码*/private String password;/*** 前端发送的验证码*/private String code;}
}
响应vo:
把资料中的LoginRespVo复制到idea中
package com.itheima.stock.vo.resp;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author by itheima* @Date 2021/12/24* @Description 登录后响应前端的vo*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LoginRespVo {/*** 用户ID*/private String id;/*** 电话*/private String phone;/*** 用户名*/private String username;/*** 昵称*/private String nickName;}
定义公共响应vo:
把资料中的R复制过来
package com.itheima.stock.vo.resp;import com.fasterxml.jackson.annotation.JsonInclude;import java.io.Serializable;/*** 返回数据类* @param */
//保证序列化json的时候,如果是null的对象,key也会消失
@JsonInclude(JsonInclude.Include.NON_NULL)
public class R implements Serializable {private static final long serialVersionUID = 7735505903525411467L;// 成功值private static final int SUCCESS_CODE = 1;// 失败值private static final int ERROR_CODE = 0;//状态码private int code;//消息private String msg;//返回数据private T data;private R(int code){this.code = code;}private R(int code, T data){this.code = code;this.data = data;}private R(int code, String msg){this.code = code;this.msg = msg;}private R(int code, String msg, T data){this.code = code;this.msg = msg;this.data = data;}public static R ok(){return new R(SUCCESS_CODE,"success");}public static R ok(String msg){return new R(SUCCESS_CODE,msg);}public static R ok(T data){return new R(SUCCESS_CODE,data);}public static R ok(String msg, T data){return new R(SUCCESS_CODE,msg,data);}public static R error(){return new R(ERROR_CODE,"error");}public static R error(String msg){return new R(ERROR_CODE,msg);}public static R error(int code, String msg){return new R(code,msg);}public int getCode(){return code;}public String getMsg(){return msg;}public T getData(){return data;}
}
定义响应状态枚举:
把资料中的ResponseCode复制到idea中
package com.itheima.stock.common.enums;/*** @author by itheima* @Date 2021/12/21* @Description*/
public enum ResponseCode{ERROR(0,"操作失败"),SUCCESS(1,"操作成功"),DATA_ERROR(0,"参数异常"),NO_RESPONSE_DATA(0,"无响应数据"),SYSTEM_VERIFY_CODE_NOT_EMPTY(0,"验证码不能为空"),SYSTEM_VERIFY_CODE_ERROR(0,"验证码错误"),SYSTEM_USERNAME_NOT_EMPTY(0,"账号不能为空"),SYSTEM_USERNAME_NOT_EXISTS(0,"账号不存在"),SYSTEM_USERNAME_EXPIRED(0,"账户过期"),SYSTEM_USERNAME_LOCKED(0,"账户被锁"),SYSTEM_USERNAME_DISABLED(0,"账户被禁用"),SYSTEM_PASSWORD_ERROR(0,"账号或密码错误"),SYSTEM_PASSWORD_EXPIRED(0,"密码过期"),SYSTEM_USERNAME_OFFLINE(0,"已下线,请重新登录"),SYSTEM_ERROR(0,"系统异常请稍后再试"),ACCOUNT_EXISTS_ERROR(0,"该账号已存在"),TOKEN_ERROR(2,"用户未登录,请先登录"),NOT_PERMISSION(3,"没有权限访问该资源"),TOKEN_NOT_NULL(-1,"token 不能为空"),TOKEN_NO_AVAIL(-1,"token无效或过期"),TOKEN_PAST_DUE(-1,"登录失效,请重新登录"),TOKEN_EXISTS(-1,"账号异地登录,你已被迫退出"),OPERATION_MENU_PERMISSION_CATALOG_ERROR(0,"操作后的菜单类型是目录,所属菜单必须为默认顶级菜单或者目录"),OPERATION_MENU_PERMISSION_MENU_ERROR(0,"操作后的菜单类型是菜单,所属菜单必须为目录类型"),OPERATION_MENU_PERMISSION_BTN_ERROR(0,"操作后的菜单类型是按钮,所属菜单必须为菜单类型"),OPERATION_MENU_PERMISSION_URL_NOT_NULL(0,"菜单权限的url不能为空"),OPERATION_MENU_PERMISSION_URL_PERMS_NULL(0,"菜单权限的标识符不能为空"),OPERATION_MENU_PERMISSION_URL_METHOD_NULL(0,"菜单权限的请求方式不能为空"),OPERATION_MENU_PERMISSION_URL_CODE_NULL(0,"菜单权限的按钮标识不能为空"),OPERATION_MENU_PERMISSION_UPDATE(0,"操作的菜单权限存在子集关联不允许变更"),ROLE_PERMISSION_RELATION(0, "该菜单权限存在子集关联,不允许删除"),OLD_PASSWORD_ERROR(0,"旧密码不匹配");private int code;private String message;ResponseCode(int code, String message) {this.code = code;this.message = message;}public int getCode() {return 0;}public String getMessage() {return null;}
}
说明:上述的vo对象直接在:今日指数\day01\资料\vo导入即可;
org.apache.commons commons-lang3
org.springframework.security spring-security-crypto
com.google.guava guava
package com.itheima.stock.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;/*定义公共配置类*/@Configuration
public class CommonConfig {/*** 密码加密器 定义密码加密器和解密器 bean* BCryptPasswordEncoder方法采用SHA-256对密码进行加密* @return*/@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}}
密码加密测试:
package com.itheima.stock.controller;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.resp.LoginRespVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api")
public class UserController {/* @GetMapping("/test")public String getName(){return "itheima";}*/@Autowiredprivate UserService userService;/*** 用户登录功能实现* @param vo* @return*/@PostMapping("/login")public R login(@RequestBody LoginReqVo vo){return userService.login(vo);}}
服务接口:
Alt+Enter 选择以下图上所示
接口服务实现:
Alt+Enter
package com.itheima.stock.service.impl;
import com.google.common.base.Strings;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.SysUser;
import com.itheima.stock.service.UserService;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.resp.LoginRespVo;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {@Autowiredprivate SysUserMapper sysUserMapper;@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic R login(LoginReqVo vo) {//1.判断vo是否存在 或者用户名是否存在或都密码是否存在if (vo == null || Strings.isNullOrEmpty(vo.getUsername()) || Strings.isNullOrEmpty(vo.getPassword())) {return R.error(ResponseCode.DATA_ERROR.getMessage());}//2. 根据用户名判断用户是否存在SysUser userInfo = sysUserMapper.findUserInfoByUserName(vo.getUsername());if (userInfo == null) {return R.error(ResponseCode.DATA_ERROR.getMessage());}//3.判断密码,不匹配if (!passwordEncoder.matches(vo.getPassword(), userInfo.getPassword())) {return R.error(ResponseCode.SYSTEM_PASSWORD_ERROR.getMessage());}//4.属性赋值 两个类之间属性名称一致LoginRespVo respVo = new LoginRespVo();BeanUtils.copyProperties(userInfo,respVo);return R.ok(respVo);}}
测试
package com.itheima.stock;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.password.PasswordEncoder;@SpringBootTest
public class TestPasswordEncoder {@Autowiredprivate PasswordEncoder passwordEncoder;@Testpublic void test1(){String pwd ="123456";//加密String enPwd1 = passwordEncoder.encode(pwd);String enPwd2 = passwordEncoder.encode(pwd);System.out.println(enPwd1);System.out.println(enPwd2);//验证密码是否正确boolean r1 = passwordEncoder.matches(pwd, enPwd1);System.out.println(r1);boolean r2 = passwordEncoder.matches(pwd, enPwd2);System.out.println(r2);}}
上一篇:自有APP上如何运行小游戏?
下一篇:「3」线性代数(期末复习)