项目(今日指数之环境搭建)

news2024/9/23 17:25:34

一 项目架构


1.1 今日指数技术选型

【1】前端技术

【2】后端技术栈

【3】整体概览

1.2 核心业务介绍

【1】业务结构预览

【2】业务结构预览

1.定时任务调度服务
    XXL-JOB通过RestTemplate+多线程动态拉去股票接口数据,刷入数据库;
2.国内指数服务
3.板块指数服务
4.涨幅榜展示功能
5.涨停跌停数展示功能
6.成交量对比展示功能
7.个股涨停服务展示功能
8.个股详情展示功能
       包含分时行情、日k线、周K线图等
9.个股描述服务;
10.报表导出服务

二 后端开发环境搭建


开发工具版本要求:

2.1 数据库环境搭建

【1】表结构介绍

注意事项:后期股票相关的数据量非常庞大,表与表之间尽量不要构建外键约束(提升数据库性能),同时也为后期分库分表准备!

【2】数据导入

因为我边的CentOS7连接不上 所以在这里面 用本地(windoms)运行

数据库可视化选用 SQLyog - 64 bit mysql用的是5.7.24

2.2后端工程搭建

【1】构建stock_parent父工程

创建stock_parent  maven工程:

接下来 复制以下maven到pom.xml

 <packaging>pom</packaging>
    <properties>
                <!--工程构建的代码格式为UTF-8-->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
           <!--编译-->
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
          <!--编译原文件-->
        <maven.compiler.source>8</maven.compiler.source>
          <!--生成的编译目录-->
        <maven.compiler.target>8</maven.compiler.target>
         <!--打包时跳过测试-->
        <maven.test.skip>true</maven.test.skip>
        <!--mybatis整合spring-boot场景依赖-->
        <mybatis-spring-boot-starter.version>2.1.4</mybatis-spring-boot-starter.version>
          <!--pagehelper版本-->
        <pagehelper-spring-boot-starter.version>1.2.12</pagehelper-spring-boot-starter.version>
          <!--mysql驱动包-->
        <mysql-driver.version>5.1.49</mysql-driver.version>
             <!--fastjson工具-->
        <fastjson.version>1.2.71</fastjson.version>
          <!--依赖的版本-->
        <springfox-swagger2.version>2.9.2</springfox-swagger2.version>
            <!--druid的场景依赖-->
        <druid-spring-boot-starter.version>1.1.22</druid-spring-boot-starter.version>
        <!--druid的核心依赖-->
        <druid-core-version>1.2.8</druid-core-version>
        <!--分库分表对应的版本-->
        <sharding-jdbc.version>4.0.0-RC1</sharding-jdbc.version>
           <!--jwt-->
        <jjwt.version>0.9.1</jjwt.version>
           <!--easyExcel  报表导入导出-->
        <easyExcel.version>3.0.4</easyExcel.version>
           <!--xxl-job-->
        <xxl-job-core.version>2.3.0</xxl-job-core.version>
           <!--spring-boot版本-->
        <spring-boot.version>2.5.3</spring-boot.version>
            <!--日期小插件-->
        <joda-time.version>2.10.5</joda-time.version>
             <!--google.guava-->
        <google.guava.version>30.0-jre</google.guava.version>
    </properties>
    <!--定义依赖版本锁定-->
    <dependencyManagement>
        <dependencies>
            <!--引入springboot依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--引入mybatis场景依赖-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis-spring-boot-starter.version}</version>
            </dependency>
            <!--pageHelper场景依赖-->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper-spring-boot-starter.version}</version>
            </dependency>
            <!--mysql驱动包-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql-driver.version}</version>
            </dependency>
            <!--shardingjdbc分库分表-->
            <dependency>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
                <version>${sharding-jdbc.version}</version>
            </dependency>
            <!--json工具包-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
            <!--druid-boot依赖-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid-spring-boot-starter.version}</version>
            </dependency>
            <!--druid core-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid-core-version}</version>
            </dependency>
            <!--swagger文档依赖-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>${springfox-swagger2.version}</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>${springfox-swagger2.version}</version>
            </dependency>
            <!--引入jwt依赖-->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jjwt.version}</version>
            </dependency>
            <!-- 导出 excel -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <version>${easyExcel.version}</version>
            </dependency>
            <!--xxl-job定义任务框架支持-->
            <dependency>
                <groupId>com.xuxueli</groupId>
                <artifactId>xxl-job-core</artifactId>
                <version>${xxl-job-core.version}</version>
            </dependency>
            <!--时间小工具-->
            <dependency>
                <groupId>joda-time</groupId>
                <artifactId>joda-time</artifactId>
                <version>${joda-time.version}</version>
            </dependency>
            <!--引入google的工具集-->
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>${google.guava.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <!--Springboot核心插件-->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <configuration>
                        <excludes>
                            <!--插件运行时排除依赖-->
                            <exclude>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-configuration-processor</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
                <!--打包跳过test -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <skip>${maven.test.skip}</skip>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

注意事项:

1.打包方式:pom
2.通过dependencyManagement、pluginManagement锁定开发中的依赖和插件的版本;

接下来 删除父工程的src

【2】构建stock_backend基础工程

创建stock_parent的maven子工程stock_backend:

【2.1】引入依赖

stock_backend工程被stock_parent父工程聚合,pom配置如下:

<packaging>jar</packaging>
    <artifactId>stock_backend</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- 基本依赖   web的场景依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
         <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

          <!--mybatis整合spring-boot-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
            <!--分页-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>

        <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        
        <!--配置提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!--时间小工具-->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
        </dependency>
    </dependencies>

    <build>
        <!--打包名称-->
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- 打包跳过test -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
【2.2】创建公共包结构

找到资料中的公共包结构

复制com

进入到项目的物理路径(IntelliJ IDEA 2020.1.3 x64)

不同的idea进行项目物理环境的选项不同

把刚才复制过来的com复制到main/java下面

这样就能得到目录结构(里面为空目录) 这样做的目的是不能一次次创建目录结构

【2.3】快速生成yml和main启动类的插件JBL SpringbootAppGen

安装

使用

生成效果

【2.4】配置yml
# web定义
server:
  port: 8081   #指定当前端口号

spring:
  # 配置mysql数据源
  datasource:
    druid:
      username: root
      password: root
      url: jdbc:mysql://127.0.0.1:3306/stock_db?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
      driver-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 DUAL
      validationQuery: SELECT 1 FROM DUAL
      # 建议配置为 true,不影响性能,并且保证安全性。申请连接的时候检测,
      # 如果空闲时间大于 timeBetweenEvictionRunsMillis,执行 validationQuery 检测连接是否有效。
      testWhileIdle: true
      # 申请连接时执行 validationQuery 检测连接是否有效,做了这个配置会降低性能。
      testOnBorrow: false
      # 归还连接时执行 validationQuery 检测连接是否有效,做了这个配置会降低性能。
      testOnReturn: false
      # 是否自动回收超时连接
      poolPreparedStatements: true
      maxPoolPreparedStatementPerConnectionSize: 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/*.xml
  configuration:
    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接口参数来传递分页参数,默认false
  params: 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版本复制路径写法

然后把复制过来的路径给放在下图所示

【2.5】定义main启动类
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);
    }
}
【2.6】定义web测试接口
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

至此,工程基础环境搭建完毕!

2.3 快速构建mybatis业务开发环境

【1】安装插件mybatisX工具

我们可借助mybatisX工具生成基础代码,步骤如下:

第一步:通过idea自带的database组件连接数据库:

全选11张表 点击第一张表 按住Shist 在点击最后一张表

右击

第二步:配置pojo实体类选项

【2】集成mybatis的工程结构

【3】环境整体测试

目的:我们通过一个简单的web接口访问数据库,验证工程搭建情况
接口功能说明:查询所有上市公司主营业务数据
接口url:/api/quot/stock/business/all
【3.1】定义mapper接口方法

StockBusinessMapper接口和xml定义查询所有股票业务信息的接口方法:

   List<StockBusiness> findall();

  <select id="findall" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from stock_business
    </select>
【3.2】定义服务接口及实现

定义服务接口:

package com.itheima.stock.service;

import com.itheima.stock.pojo.StockBusiness;
import java.util.List;
   /*定义股票服务接口*/
public interface StockService {
   /*查询所有主营业务信息*/
    List<StockBusiness> 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 {

    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    @Override
    public List<StockBusiness> findAll() {
        return stockBusinessMapper.findAll();
    }
}
【3.3】定义web访问接口

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 {

    @Autowired
    private StockService stockService;

    @GetMapping("/stock/business/all")
    public List<StockBusiness> findAllBusiness(){
        return stockService.findAll();
    }

}

【3.4】启动项目测试

成功启动

至此,后台基本开发环境构建完毕!

3.前端开发环境搭建


3.1 前端环境准备

【1】node安装

前端node版本:

详见资料:

【2】vs导入前端代码

资料:day01\资料\前端资料\stock_front_admin

使用vscode打开工程:

效果如下:

【3】前端工程启动

npm run dev

这里面是8080 但是我们后端是8081 所以这里面要注意一下

注意事项:如果启动报错,重新npm install 或者cnpm install

【4】页面效果

3.2 前后端分离跨域问题

在前面的知识中,我们已经了解到项目进行前后端分离后,存在跨域问题,只需在前端进行简单配置,即可解决该问题;

【1】前后端跨域配置

在stock_front_admin\src\settings.js文件下配置跨域:

    devServer: {
        port: 8080,
        host: '127.0.0.1',// 开发host
        open:true,// 是否启动时打开浏览器
        disableHostCheck: true, // 映射外网时,需要设置为true
        /**
         * 域名,他将会基于 window.location来链接服务器,需要使用public配置
         * dev-server被代理到nginx中配置的 itheima.com
         */
        public: "127.0.0.1:8080",//itheima.com
        publicPath:'/',
        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" : ""},
            }
        },
    },

【2】前后端交互数据格式

前端与后端使用json格式进行交互。

4.登录功能实现


4.1 需求分析

1)页面原型效果

2)相关的表结构

sys_user表如下:

3)访问接口定义

      请求接口:/api/login
请求方式:POST
请求数据示例:
    {
       username:'zhangsan',//用户名
       password:'666',//密码
       code:'1234' //校验码
    }
响应数据:
    {
        "code": 1,//成功1 失败0
        "data": {
        "id":"1237365636208922624",
        "username":"zhangsan",
        "nickName":"xiaozhang",
        "phone":"1886702304"
        }
    }

4)封装请求和响应vo

请求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 <T>
 */
//保证序列化json的时候,如果是null的对象,key也会消失
@JsonInclude(JsonInclude.Include.NON_NULL)
public class R<T> 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 <T> R<T> ok(){
        return new R<T>(SUCCESS_CODE,"success");
    }
    public static <T> R<T> ok(String msg){
        return new R<T>(SUCCESS_CODE,msg);
    }
    public static <T> R<T> ok(T data){
        return new R<T>(SUCCESS_CODE,data);
    }
    public static <T> R<T> ok(String msg, T data){
        return new R<T>(SUCCESS_CODE,msg,data);
    }

    public static <T> R<T> error(){
        return new R<T>(ERROR_CODE,"error");
    }
    public static <T> R<T> error(String msg){
        return new R<T>(ERROR_CODE,msg);
    }
    public static <T> R<T> error(int code, String msg){
        return new R<T>(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导入即可

4.2 登录功能开发实现

  1. stock_backend导入依赖资源

<!--apache工具包-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>
<!--密码加密和校验工具包-->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-crypto</artifactId>
</dependency>
<!--工具包-->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

  1. 配置密码加密服务

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
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }



}

密码加密测试:

  1. 登录接口方法定义

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";
    }*/

    @Autowired
    private UserService userService;

    /**
     * 用户登录功能实现
     * @param vo
     * @return
     */
    @PostMapping("/login")
    public R<LoginRespVo> login(@RequestBody LoginReqVo vo){

        return userService.login(vo);
    }

}

4)定义登录服务接口和实现

服务接口:

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 {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public R<LoginRespVo> 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 {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Test
    public  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);

    }

}

5)Postman测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/342715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

清晰理解并解决二分问题

文章目录二分问题常规解法&#xff1a;使用CSTL自带算法解决二分问题&#xff1a;小数二分二分问题常规解法&#xff1a; 二分问题注意事项&#xff1a; 题目可能无解&#xff0c;但二分一定有解&#xff08;也就是二分问题会得到一个结果&#xff0c;但是该结果可能不符合题目…

RabbitMQ-集群

一、搭建1、创建三个虚拟机2、修改三台主机的hostname,分别为node1,node2,node3,分别重启vi /etc/hostname reboot3、配置各个主机的hosts文件&#xff0c;让各个节点都能互相识别对方vi /etc/hosts #添加下面配置 192.168.xxx.165 node1 192.168.xxx.167 node2 192.168.xxx.16…

Django by Example·第三章|Extending Your Blog Application@笔记

Django by Example第三章|Extending Your Blog Application笔记 之前已经写过两章内容了&#xff0c;继续第三章。第三章继续对博客系统的功能进行拓展&#xff0c;其中将会穿插一些重要的技术要点。 部分内容引用自原书&#xff0c;如果大家对这本书感兴趣 请支持原版Django …

基于模块联邦的微前端实现方案

一、 微前端应用案例概述 当前案例中包含三个微应用&#xff0c;分别为 Marketing、Authentication 和 Dashboard Marketing&#xff1a;营销微应用&#xff0c;包含首页组件和价格组件 Authentication&#xff1a;身份验证微应用&#xff0c;包含登录组件 Dashboard&#x…

B站发帖软件哪个好用?好用的哔哩哔哩发帖工具

B站发帖软件哪个好用?好用的哔哩哔哩发帖工具#发帖软件#哔哩哔哩发帖#视频发布软件 登录成功之后&#xff0c;进入到这样一个界面&#xff0c;默认情况下是这个样子的&#xff0c;我们在这里输入一下我们的一个文件夹的路径&#xff0c;输入到这里&#xff0c;点击添加账号&a…

kettle开发-Day36-循环驱动作业

前言&#xff1a;在日常数据处理时&#xff0c;我们通过变量传参来完成某个日期的数据转换。但可能因程序或者网络原因导致某个时间段的数据抽取失败。常见导致kettle作业失败的原因大概分为三大类&#xff0c;数据源异常、数据库异常、程序异常。因此面对这些异常时&#xff0…

Not available OpenAI s services are not available in your country.

一、准备阶段 1、邮箱账号(qq、网易、谷歌等等) 2、你能够科学上网(下边详细介绍) 3、拥有一个GW手机号&#xff0c;用于接收注册验证码。&#xff08;下边详细介绍&#xff09; 二、开始注册 1、官方注册网址https://beta.openai.com/signup&#xff08;按照步骤注册&am…

RDSDRDSPolarDBPolarDB-X的区别

RDS 阿里云关系型数据库&#xff08;Relational Database Service&#xff0c;简称RDS&#xff09;&#xff0c;是一种稳定可靠、可弹性伸缩的在线数据库服务。 基于阿里云分布式文件系统和高性能存储&#xff0c;RDS支持MySQL、SQL Server、PostgreSQL和PPAS&#xff08;Post…

在VScode终端上创建nuxtjs项目遇到的问题以及使用GitHub遇到的问题和一些个人笔记

文章目录&#x1f4cb;前言&#x1f4bb;关于GitHub打开慢或无法打开的问题&#x1f4bb;克隆GitHub的项目到本地&#x1f4bb;创建nuxtjs项目&#x1f9e9;无法加载文件的报错问题&#x1f9e9;使用vue init nuxt/starter demo出现的问题&#x1f9e9;另一种命令创建nuxtjs项目…

字符编码及转换

什么是字符编码字符编码&#xff08;Character encoding&#xff09;也称字集码&#xff0c;是把字符集中的字符&#xff0c;编码为指定集合中的某一对象&#xff08;例如&#xff1a;比特模式、自然数序列、8位组或者电脉冲&#xff09;&#xff0c;以便文本在计算机中存储或者…

前端控制台出现 红色 的报错信息TypeError: fn.apply is not a function

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 使用vue在原来的系统中 开发新的模块&#xff0c;开发时无意间发现 前端控制台出现 红色 的报错信息&#xff0c;但是页面依然还是正常 加载出来了 控制台一直报错 TypeError: fn.apply is not a fun…

09- 逻辑回归算法 (LogisticRegression) (机器学习)

基本概念: 逻辑回归主要逻辑是通过sigmoid函数进行分类, 当函数结果大于0时赋值1, 小于0时赋值0, 然后根据结果进行分类, 化简后求最小值的过程和线性方程类似, 该函数的特点是:分类算法 模型训练 : lr LogisticRegression() from sklearn.linear_model import LogisticRegr…

力扣39.组合总数

文章目录力扣39.组合总数题目描述方法1&#xff1a;深搜回溯力扣39.组合总数 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可…

【数据库】MySQL 单表查询,多表查询

目录 单表查询 一&#xff0c;创建表worker 1&#xff0c;创建表worker的sql代码如下&#xff1a; 2&#xff0c;向worker表中插入信息 二&#xff0c; 按要求进行单表查询 1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 …

【自学Python】Python字符大小写判断

大纲 Python字符串是否是小写 Python字符串是否是小写教程 在开发过程中&#xff0c;有时候我们需要判断一个 字符串 是否是小写形式&#xff08;即&#xff0c;所有的字符都是小写字母&#xff0c;不是英文字符的忽略不做判断&#xff09;&#xff0c;在 Python 中&#xff…

SAP ERP系统SD模块常用增强之一:VA01/VA02创建或修改SO的输入检查

在SAP/ERP项目的实施中销售管理模块&#xff08;SD&#xff09;的创建和修改销售订单必定会有输入字段校验检查的需求&#xff0c;来防止业务人员录入错误或少录入数据&#xff0c;SAP公司也考虑到这一点&#xff0c;所以这方面的配置功能也非常强大&#xff0c;通常情况下不需…

GraphQL vs REST API 架构,谁更胜一筹?

GraphQL vs REST API 架构&#xff0c;谁更胜一筹&#xff1f; Michele Moody 平川 万佳 2020 年 1 月 18 日 本文字数&#xff1a;2890 字 阅读完需&#xff1a;约 9 分钟 2015 年&#xff0c;Facebook 开源 GraphQL。此后&#xff0c;它在前端 Web 中大受欢迎。传统的 R…

一篇文章带你学会Ansible的安装及部署

目录 前言 一、什么是Ansible 二、Ansible的工作方式 三、Ansible的安装 四、构建Anisble清单 1、清单书写方式 2、清单查看 3、清单书写规则 4、主机规格的范围化操作 五、ansible命令指定清单的正则表达式 六、 Ansible配置文件参数详解 1、配置文件的分类与优先…

【C++】C/C++内存管理模板初阶

文章目录一、 C/C内存管理1. C/C内存分布2. C内存管理方式3. operator new与operator delete函数4. new和delete的实现原理5. 定位new表达式6. 常见面试题malloc/free和new/delete的区别内存泄漏二、模板初阶1. 泛型编程2. 函数模板3. 类模板一、 C/C内存管理 1. C/C内存分布 …

每天10个前端小知识 【Day 13】

前端面试基础知识题 1. Position&#xff1a;absolute绝对定位&#xff0c;是相对于谁的定位&#xff1f; CSS position属性用于指定一个元素在文档中的定位方式。top&#xff0c;right&#xff0c;bottom 和 left 属性则决定了该元素的最终位置。 absolute的元素会被移出正…