1. Spring Initializr

Spring-boot脚手架

 

2. 项目结构

Spring-boot SSM金融股票市场实践 详解_Spring-boot

desciption
config 配置类
controller 控制器
entity 实体类
intercept 拦截器
mapper MyBatis映射类
service 服务类
utils 工具类

 

 

 

 

 

 

 

 

 

 

 

desciption
mapper MyBatis XML映射类
static js, css, images
templates thymeleaf模板
application.properties springboot xml配置
jdbc.properties mysql 配置
schema.sql sql 初始化

 

 

 

 

 

 

 

 

 

 

3. Starter

    






desciption
spring-boot-starter-web Spring框架
spring-boot-starter-test /
spring-boot-starter-thymeleaf 渲染模板
mysql-connector-java mysql
mybatis-spring-boot-starter mybatis持久层

 

 

 

 

 

 

 

 

 

4. xml配置

 AiApplication.java

package com.kenny.ai;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.PropertySource;

@SpringBootApplication
@ComponentScan(basePackages = {"com.kenny.ai.*"})
@MapperScan(basePackages = {"com.kenny.ai.mapper"})
@PropertySource(value={"classpath:jdbc.properties"}, ignoreResourceNotFound=true)public class AiApplication {    public static void main(String[] args) {
        SpringApplication.run(AiApplication.class, args);
    }
}
LabelDescription
@SpringBootApplicationSpring框架
@ComponentScan扫描根目录
@MapperScanMybatis映射层
@PropertySource数据库xml配置

 

 

 

 

 

 

 

application.properties

server.port=8080mybatis.mapper-locations=classpath:mapper/*.xml

jdbc.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_boot?useSSL=false&useUnicode=true&characterEncoding=UTF-8spring.datasource.username=user002
spring.datasource.password=123456spring.datasource.sql-script-encoding=utf-8spring.datasource.initialization-mode=always
  1. 项目端囗配置
  2. mybatis映射xml
  3. mysql配置

重点:mysql必须有useUnicode=true&characterEncoding=UTF-8,否则会编码错误。

 

 

5. mybatis持久层

spring.datasource.initialization-mode=always,这句会自动扫描resources/schema.sql。

5.1 schema.sql

Spring-boot SSM金融股票市场实践 详解_Spring-boot_02

DROP TABLE IF EXISTS `stock`;
CREATE TABLE stock
(
  id        INT PRIMARY KEY auto_increment,
  ucode     VARCHAR(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  uname_tc  VARCHAR(512) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  uname_en  VARCHAR(512) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE utf8_general_ci;
INSERT INTO `stock`(`id`,`ucode`,`uname_tc`,`uname_en`) values
(1,'0700','騰訊控股','Tencent Holdings Ltd.'),
(2,'1810','小米集團','Xiaomi Singapore Pte. Ltd.'),
(3,'3690','美團','Meituan Corp'),
(4,'9988','阿里巴巴','Alibaba Group'),
(5,'2800','盈富基金','Tracker Fund of Hong Kong'),
(6,'3033','南方東英恒生科技指數ETF','CSOP Hang Seng TECH Index ETF HKD');

5.2 java.com.kenny.ai.entity.Stock.java 实体类

package com.kenny.ai.entity;import org.springframework.stereotype.Component;

@Component("stock")public class Stock {    private Long id;    private String ucode;    private String uname_tc;    private String uname_en;    public Long getId() {        return id;
    }    public void setId(Long id) {        this.id = id;
    }    public String getUcode() {        return ucode;
    }    public void setUcode(String ucode) {        this.ucode = ucode;
    }    public String getUname_tc() {        return uname_tc;
    }    public void setUname_tc(String uname_tc) {        this.uname_tc = uname_tc;
    }    public String getUname_en() {        return uname_en;
    }    public void setUname_en(String uname_en) {        this.uname_en = uname_en;
    }

    @Override    public String toString() {        return "Stock{" +
                "id=" + id +
                ", ucode='" + ucode + '\'' +
                ", uname_tc='" + uname_tc + '\'' +
                ", uname_en='" + uname_en + '\'' +
                '}';
    }
}

5.3 java.com.kenny.ai.mapper.StockMapper.java

mapper映射层,注入Stock实体类。实现增删改查。

package com.kenny.ai.mapper;import com.kenny.ai.entity.Stock;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import org.apache.ibatis.annotations.Select;import org.springframework.stereotype.Component;import java.util.List;

@Mapper
@Componentpublic interface StockMapper {    /***
     * 查詢所有正股
     * @return 正股列表     */
    @Select({"select id, ucode, uname_tc, uname_en from stock"})
    List listAll();    /***
     * 根據ucode查詢正股
     * @param ucode 正股編號
     * @return 当前ucode的正股,不存在则是 {@code null}     */
    @Select({"SELECT id, ucode, uname_tc, uname_en from stock WHERE ucode = #{ucode}"})
    Stock findByUcode(@Param("ucode") String ucode);    /***
     * 保存正股
     * @param stock 正股
     * @return 成功 - {@code 1} 失败 - {@code 0}     */
    int saveStock(@Param("stock") Stock stock);    /***
     * 更新正股
     * @param stock 正股
     * @return 成功 - {@code 1} 失败 - {@code 0}     */
    int updateStock(@Param("stock") Stock stock);    /***
     * 删除正股
     * @param ucode 正股編號
     * @return 成功 - {@code 1} 失败 - {@code 0}     */
    int deleteByUcode(@Param("ucode") String ucode);
}

5.4 resources.mapper.StockMapper.xml 

mapper映射层的xml配置。配置了较复杂的sql stmt。

重点:路径在application.properties配置。


        INSERT INTO `stock` (`ucode`, `uname_tc`, `uname_en`)
        VALUES (#{stock.ucode}, #{stock.uname_tc}, #{stock.uname_en})    
        UPDATE `stock` SET uname_tc=#{stock.uname_tc}, uname_en=#{stock.uname_en} WHERE ucode=#{stock.ucode}    
        DELETE
        FROM `stock`
        WHERE `ucode` = #{ucode}

 

 

6. Controller控制器

注入Stock实体类 和 StockMapper映射类。因业务简单,所以暂时地不用Service层。

默认使用thymeleaf模板渲染。

6.1 com.kenny.ai.controller.StockController.java

package com.kenny.ai.controller;import com.kenny.ai.entity.Stock;import com.kenny.ai.mapper.StockMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;

@Controllerpublic class StockController {
    @Autowired    private final StockMapper stockMapper;    public StockController(StockMapper stockMapper) {        this.stockMapper = stockMapper;
    }

    @RequestMapping(value={"/", "/index", "/home", "/uat/v2/home"})    public String index(Model model) {
        model.addAttribute("stocks", this.stockMapper.listAll());        return "stock/stock";
    }

    @RequestMapping({"stock/delete/{ucode}", "uat/v2/stock/delete/{ucode}"})    public String deleteStock(@PathVariable String ucode) {
        stockMapper.deleteByUcode(ucode);        return "redirect:/home";
    }

    @RequestMapping({"stock/save", "uat/v2/stock/save"})    public String stockSave(Stock stock) {
       stockMapper.saveStock(stock);       return "redirect:/home";
    }

    @RequestMapping({"stock/update", "uat/v2/stock/update"})    public String stockUpdate(Stock stock) {
        stockMapper.updateStock(stock);        return "redirect:/home";
    }
}

 

 

7. Thymeleaf模板

7.1 webapp结构

Spring-boot SSM金融股票市场实践 详解_Spring-boot_03

 spring-boot强烈推荐thymeleaf完全取代jsp,那就试用thymeleaf吧。

 

7.2 最终效果

Spring-boot SSM金融股票市场实践 详解_Spring-boot_04

 

7.3 resources/templates/fragments/header.html

<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head th:fragment="common_header(title)">
    <title th:replace="${title}">title>
    <meta charset="utf-8">meta>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">meta>
    <script th:src="@{/js/jquery.min.js}" type="text/javascript">script>
    <script th:src="@{/js/bootstrap.min.js}" type="text/javascript">script>
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet" />
    <link th:href="@{/css/kuang-style.css}" rel="stylesheet" />
    <link th:href="@{/css/style.css}" rel="stylesheet" />head>

th:fragment="common_header(title)"

fragment名称:common_header

注入叁数:title

重点:@{/} 指向根目录。

<head th:replace="fragments/header :: common_header(~{::title})">

 

7.4 resources/templates/stock/stock.html

7.4.1 渲染表格

<tr th:if="${stocks==null or stocks.isEmpty()}">
    <td colspan="4"> 沒有合適的正股 td>tr><tr th:each="stock : ${stocks}">
    <form th:action="@{/stock/update}" method="post">
        <td><span th:text="${stock.ucode}"> span>td>
        <td><input type="text" class="form-control" name="uname_tc" th:value="${stock.uname_tc}"> input>td>
        <td><input type="text" class="form-control" name="uname_en" th:value="${stock.uname_en}"> input>td>
        <td>
            <button type="submit" class="btn btn-sm btn-primary btn-update">更新button>
            <input type="hidden" class="form-control" name="ucode" th:value="${stock.ucode}"> input>
            <button type="button" th:href="@{'/stock/delete/'+${stock.ucode}}"  class="btn btn-sm btn-danger btn-delete">刪除button>
        td>
    form>tr>

7.4.2 新增数据

name=ucode
name=uname_tc
name=uname_en

会自动映射至Stock实体,并经StockMapper映射,进行数据库事务。

<form th:action="@{/stock/save}" method="post">
    <div class="form-row">
        <div class="form-group col-12 col-md-4">
            <label for="ucode">正股label>
            <input type="text" class="form-control" id="ucode" name="ucode" placeholder="0700" required />
        div>
        <div class="form-group col-12 col-md-4">
            <label for="uname_tc">中文label>
            <input type="text" class="form-control" id="uname_tc" name="uname_tc" placeholder="騰訊控股" required />
        div>
        <div class="form-group col-12 col-md-4">
            <label for="uname_en">英文label>
            <input type="text" class="form-control" id="uname_en" name="uname_en" placeholder="Tencent Holdings Ltd." required />
        div>
        <button type="submit" class="btn btn-sm btn-primary" id="submit">Submitbutton>
    div>form>