建立SpringBoot项目

一开始选择 Spring Initializr 并next,填写Group以及项目名。下一步,选择最高版本的SpringBoot稳定版,选择Web项目。接着,填写项目名称以及路径后建立项目。

  1. 新建HelloController的java类文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    package com.delaunay.luckymoney;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;

    import java.math.BigDecimal;

    // @RestController = @Controller + @ResponseBody
    @RestController
    public class HelloController {

    // @Autowired
    // private LimitConfig limitConfig;

    // 旧版本
    // @RequestMapping(value = "/hello", method = RequestMethod.GET)
    @GetMapping("/hello")
    public String say() {
    return "SpringBoot";
    // return "index";
    }
    }
  2. 此时,运行项目,就已经可以可以从/hello地址看到界面。

项目使用cmd命令运行

cd到项目根目录下,运行如下命令:
mvn spring-boot:run
这样就可以不用打开idea运行项目了

项目属性配置

有两种项目属性配置方式

  1. application.properties
    1
    2
    server.port=8080
    server.servlet.context-path=/luckymoney
  2. application.yml
    1
    2
    3
    4
    5
    6
    7
    8
    server:
    port: 8080
    servlet:
    context-path: /luckymoney

    minMoney: 1
    maxMoney: 999
    description: 红包最小金额${minMoney}元,最大金额${maxMoney}元
    推荐采用第二种写法,较为直观清晰。
    此时,我们定义了红包的最小金额与最大金额,回到controller层进行输出。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @RestController
    public class HelloController {

    @Value("${minMoney}")
    private BigDecimal minMoney;

    // 旧版本
    // @RequestMapping(value = "/hello", method = RequestMethod.GET)
    @GetMapping("/hello")
    public String say() {
    return "minMoney" + minMoney;
    }
    }
    这时,已经可以输出minMoney了。但是大量的value注解不适合进行复杂版本的开发,我们改变一些yml配置文件以及controller的注解。
    application.properties
    1
    2
    3
    4
    5
    6
    7
    8
    9
    server:
    port: 8080
    servlet:
    context-path: /luckymoney

    limit:
    minMoney: 0.1
    maxMoney: 999
    description: 红包最小金额${limit.minMoney}元,最大金额${limit.maxMoney}元
    新建一个LimitConfig文件,将limit里的属性对象化
    LimitConfig
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    package com.delaunay.luckymoney;

    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;

    import java.math.BigDecimal;

    // componet是为了之后可以进行autowired
    // ConfigurationProperties是对应配置里的limit,prefix为前缀
    @Component
    @ConfigurationProperties(prefix = "limit")
    public class LimitConfig {

    private BigDecimal minMoney;

    private BigDecimal maxMoney;

    private String description;

    public BigDecimal getMinMoney() {
    return minMoney;
    }

    public void setMinMoney(BigDecimal minMoney) {
    this.minMoney = minMoney;
    }

    public BigDecimal getMaxMoney() {
    return maxMoney;
    }

    public void setMaxMoney(BigDecimal maxMoney) {
    this.maxMoney = maxMoney;
    }

    public String getDescription() {
    return description;
    }

    public void setDescription(String description) {
    this.description = description;
    }
    }
    我们再更改一下controller文件,这样效率会高一点
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @RestController
    public class HelloController {

    @Autowired
    private LimitConfig limitConfig;

    // 旧版本
    // @RequestMapping(value = "/hello", method = RequestMethod.GET)
    @GetMapping({"/hello", "/hi"})
    public String say() {
    return "minMoney: " + limitConfig.getMinMoney() + ", 说明:" + limitConfig.getDescription();
    }
    }

区分开发环境与生产环境

将配置文件复制粘贴两份在原来位置,命名分别为
application.yml
application-dev.yml
application-prod.yml
dev代表开发环境,prod代表生产环境,将原本的application.yml内容改变一下,使用开发花环境配置

1
2
3
spring:
profiles:
active: dev

项目打包

进入项目的根目录下,使用cmd命令
mvn clean package
然后使用java -jar命令启动项目
java -jar target/luckymoney-0.0.1-SNAPSHOT.jar
因为此时的环境依然是开发环境,所以我们用命令启动项目时修改一下
java -jar -Dspring.profiles.active=prod target/luckymoney-0.0.1-SNAPSHOT.jar
实际上时启动项目时传入参数进去

Conteoller层的使用

注解 作用
@Controller 处理http请求
@RestController Spring4之后新加的注解,原来返回json需要@ResponseBody与@Controller的配合
@RequestMapping 配置url映射(新版使用@GetMapping)

注解@Controller的使用

  1. 当我们将@RestController改成@Controller的时候,为了能够成功返回数据,需要在pom中添加依赖
    spring-boot-starter-thymeleaf
    然后重新import一下pom
  2. 接着在templates下面建立命名为index的html文件,然后将controller方法中的return改为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @RestController
    public class HelloController {

    @Autowired
    private LimitConfig limitConfig;

    // 旧版本
    // @RequestMapping(value = "/hello", method = RequestMethod.GET)
    @GetMapping({"/hello", "/hi"})
    public String say() {
    // eturn "minMoney: " + limitConfig.getMinMoney() + ", 说明:" + limitConfig.getDescription();
    return "index";
    }
    }
    这样子就可以使用了,了解一下就可以。

访问hello或hi进入同一界面

@GetMapping({"/hello", "/hi"})

访问hello下一级say

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping("/hello")
public class HelloController {

@Autowired
private LimitConfig limitConfig;

// 旧版本
// @RequestMapping(value = "/hello", method = RequestMethod.GET)
@GetMapping({"/say", "/hi"})
public String say() {
return "minMoney: " + limitConfig.getMinMoney() + ", 说明:" + limitConfig.getDescription();
// return "index";
}
}

这样,运行项目之后,浏览器需要输入/hello/say才会返回上述值。

get与post方式返回值

@GetMapping("/say")
@PostMapping("/say")
@RequestMapping("/say")

get与post根据机制选择合适的方式,一般不选择第三个两种都可以返回的方式。

返回参数

注解 作用
@PathVariable 获取url中的数据
@RequestParam 获取请求参数的值
  1. url中获取数据第一种方式

    1
    2
    3
    4
    @GetMapping("/say/{id}")
    public String say2(@PathVariable("id") Integer id) {
    return "id: " + id;
    }

    这样可以获取url中/say/后面的数据,即定义的id

  2. url中获取数据第二种方式

    1
    2
    3
    4
    5
    6
    // url中获取数据第二种方式 /hello/say?id=100
    // 使用此方式时需要删除say方法,url不能重复
    @GetMapping("/say")
    public String say3(@RequestParam("id") Integer id) {
    return "id: " + id;
    }

    但是此时url中如果没有id就会报错(400),因此我们修改一下,此时为非必传,没有id也可以访问。改为

    1
    2
    3
    4
    @GetMapping("/say")
    public String say3(@RequestParam(value = "id", required = false, defaultValue = "0") Integer id) {
    return "id: " + id;
    }
  3. 使用post方式很多样,在url中或者写在body里都可以,一般建议使用RequestParam。

操作数据库

Spring-Data-Jpa

JPA定义了一系列对象持久化的标准,目前实现这一规范的产品有Hibernate、TopLink等等。

REDTful API设计

请求类型 请求路径 功能
GET /luckymoneys 获取红包列表
POST /luckymoneys 创建一个红包
GET /luckymoneys/id 通过id查询红包
PUT /luckymoneys/id 通过id更新红包

首先,在pom加入两个依赖

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

然后,编写数据库的配置,将以下内容添加在application-dev中

1
2
3
4
5
6
7
8
9
10
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/luckymoney
username: root
password: root
jpa:
hibernate:
ddl-auto: create
show-sql: true

命令行操作数据库

因为我navicat试用期过了,因此直接用命令行操作,顺便记一下操作命令。

使用命令行的前提时将数据库的bin加入环境变量path

cd到上述bin文件下启动数据库

mysql -h localhost -u root -p

然后输入密码,下述命令查看数据库

show databases;

我们建立数据库采用

create database luckymoney default character set utf8mb4 collate utf8mb4_general_ci;

之后我们建立实体类Luckymonry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.math.BigDecimal;

@Entity
public class Luckymoney {

@Id
@GeneratedValue
private Integer id;

private BigDecimal money;

/**
* 发送方
*/
private String producer;

/**
* 接收方
*/
private String consumer;

public Luckymoney() {
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public BigDecimal getMoney() {
return money;
}

public void setMoney(BigDecimal money) {
this.money = money;
}

public String getProducer() {
return producer;
}

public void setProducer(String producer) {
this.producer = producer;
}

public String getConsumer() {
return consumer;
}

public void setConsumer(String consumer) {
this.consumer = consumer;
}
}

同时更改数据库配置文件,create变为update

1
2
3
4
5
6
7
8
9
10
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/luckymoney?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true

接着新建LuckymoneyController文件以及书写接口文件,和书写返回红包列表方法

1
2
public interface LuckymoneyRespository extends JpaRepository<Luckymoney, Integer> {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
public class LuckymoneyController {

@Autowired
private LuckymoneyRespository respository;

/**
* 获取红包列表
*/
@GetMapping("/luckymoneys")
public List<Luckymoney> list() {
return respository.findAll();
}
}

运行之后,就可以返回红包列表的json格式数据。

接着完成其他方法,以下是完整的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.delaunay.luckymoney;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;

@RestController
public class LuckymoneyController {

@Autowired
private LuckymoneyRespository respository;

/**
* 获取红包列表
*/
@GetMapping("/luckymoneys")
public List<Luckymoney> list() {
return respository.findAll();
}

/**
* 创建红包(发红包)
*/
@PostMapping("/luckymoneys")
public Luckymoney create(@RequestParam("producer") String producer,
@RequestParam("money") BigDecimal money) {
Luckymoney luckymoney = new Luckymoney();
luckymoney.setProducer(producer);
luckymoney.setMoney(money);

return respository.save(luckymoney);
}

/**
* 通过id查询红包
*/
@GetMapping("/luckymoneys/{id}")
public Luckymoney findById(@PathVariable("id") Integer id) {
return respository.findById(id).orElse(null);
}

/**
* 更新红包(领红包)
*/
@PutMapping("/luckymoneys/{id}")
public Luckymoney update(@PathVariable("id") Integer id,
@RequestParam("consumer") String consumer) {
Optional<Luckymoney> optional = respository.findById(id);
if (optional.isPresent()){
Luckymoney luckymoney = optional.get();
luckymoney.setConsumer(consumer);

return respository.save(luckymoney);
}
return null;
}
}

遇到的问题

报错:java.sql.SQLException: The server time zone value ‘�й���׼ʱ��’ is unrecognized or represents more tha。。。。
原因:因为mysql-connection-java版本导致时区的问题。
解决方法:更改数据库的配置,在url中更改为亚洲/上海时区

1
2
3
4
5
6
7
8
9
10
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/luckymoney?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true

事务

数据库事务,是指作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么完全的不执行。

例如,我们需要插入两条红包记录时,一条成功,一条失败,但是一旦失败,两条均不能插入。这时,需要加入事务注解。
新建service文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.delaunay.luckymoney;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;

@Service
public class LuckeymoneyService {

@Autowired
private LuckymoneyRespository respository;

/**
* 事务 是指数据库事务,需要数据库引擎支持事务
*/
@Transactional
public void createTwo() {
Luckymoney luckymoney1 = new Luckymoney();
luckymoney1.setProducer("delaunay");
luckymoney1.setMoney(new BigDecimal("520"));
luckymoney1.setConsumer("lover");
respository.save(luckymoney1);

Luckymoney luckymoney2 = new Luckymoney();
luckymoney2.setProducer("delaunay");
luckymoney2.setMoney(new BigDecimal("1314"));
luckymoney2.setConsumer("lover");
respository.save(luckymoney2);
}
}

同时,controller文件中添加方法

1
2
3
4
@PostMapping("/luckymoneys/two")
public void createTwo() {
service.createTwo();
}

总结

项目配置

  1. 单个配置 @Value
  2. 对象配置 @ConfigurationProperties
  3. 区分环境(开发 生产)

Controller使用

方式

  1. @Controller
  2. @ResponseBody
  3. RestController

获取参数

  1. @PathVariable
  2. @RequestParam

数据库

使用Spring-Data-Jpa
定义一个接口,继承JpaRepository
extends JpaRepository

事务

特指数据库事务

@Transactional