乐趣区

Spring笔记1——极简入门教程

环境准备

系统:MacOS
开发:IntelliJ IDEA
语言:Java8
其它:Mysql、Redis

脚手架代码
Spring 提供了一个创建项目脚手架的官网,在这里可以直接定制项目的框架代码。例如:

注意:在 Dependencies 中,添加了 Web 依赖。
点击【Generate Project】,即可下载项目框架代码。
创建工程
将框架代码包解压后放到工作目录。打开 IDEA,点击【File] ->【Open】,打开对应目录。
启动工程
找到 com.spring.demo.demo 下的 DemoApplication,右键点击运行后,console 中即可显示 Spring 启动的信息。
Controller
在传统 MVC 架构中,Controller 负责接收 Http 请求并返回相应的应答,这个应答可以是一个页面,也可以是一个 JSON 对象。方便起见,本教程使用 RestfulAPI 为例。
添加 RestController
创建一个 UserController,负责响应 User 相关的业务请求。对于纯数据的 API 接口,使用 @RestControll 进行标注,这样每一个 API 接口的返回值就会被转化为 JSON 结构的数据。
package com.spring.demo.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

@RequestMapping(“/user”)
public String find() {
return “UserA”;
}
}
重启应用,在浏览器中请求 http://localhost:8080/user,即可看到请求的返回内容:UserA。
路径参数
对于带路径参数的请求,可以通过 @PathVariable 标注来获取参数值。如:
package com.spring.demo.demo.controller;

import org.springframework.web.bind.annotation.PathVariable;

@RestController
public class UserController {

@RequestMapping(“/user/{id}”)
public String find(@PathVariable int id) {
return “ 用户 ID[” + id + “]”;
}
}
POST 请求
对于 POST 请求,可以使用 @PostMapping 来标注方法,接收的 JSON 数据需要使用 @RequestBody 来标注。

@PostMapping(“/user”)
public void create(@RequestBody UserCreateRequest user) {
System.out.println(user.getName());
}

这里的 UserCreateRequest,用来接收并转换 JSON 数据。
package com.spring.demo.demo.dto;

public class UserCreateRequest {

private String name;
private boolean gender;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public boolean isGender() {
return gender;
}

public void setGender(boolean gender) {
this.gender = gender;
}
}
在 IDEA 的 Terminal 中,使用 curl 来进行测试。
curl -XPOST ‘http://127.0.0.1:8080/user’ -H ‘Content-Type: application/json’ -d'{“name”:” 用户 A ”,”gender”:0}’
参数校验
有时我们需要对传入参数进行非空或有效值的校验,这个处理应该在正式进入 controller 前进行。
1. 添加 @Validated 标注
在 SpringMVC 中,对输入参数进行校验通常使用 @Validated 标注。

@PostMapping(“/user”)
public void create(@RequestBody @Validated UserCreateRequest user) {
System.out.println(user.getName());
}

2. 添加校验规则标注 @
在对应的字段上,加上对应的校验规则标注。
package com.spring.demo.demo.dto;

import javax.validation.constraints.NotNull;

public class UserCreateRequest {

@NotNull
private String name;

private boolean gender;

// Getters & Setters

}

添加后重启服务,发送不含 name 字段的 POST 请求,结果如下:
Service
MVC 框架中,Controller 负责接收请求和相应,Service 则负责具体的业务处理,即 Model 层。
Service 在定义是需要使用 @Service 标注,SpringBoot 在启动中将会注册该 Service 并在 Controller 通过 DI 来实例化并使用该 Service。
一般来说,我们会创建一个 Service 的接口类和一个对应的实现类。
IUserService
package com.spring.demo.demo.service;

public interface IUserService {
public String findUser(int id);
}
UserService
package com.spring.demo.demo.service;

import org.springframework.stereotype.Service;

@Service
public class UserService implements IUserService {

public String findUser(int id) {
return “ 用户 ” + id;
}
}

在调用时,Controller 会直接应用接口类,并添加 @Autowired 标签。这里的调用原理,即是 Sping 最著名的 DI(依赖注入)和 IoC(控制反转)。
package com.spring.demo.demo.controller;

import com.spring.demo.demo.dto.UserCreateRequest;

@RestController
public class UserController {

@Autowired
IUserService userService;

@RequestMapping(“/user/{id}”)
public String find(@PathVariable int id) {
return userService.findUser(id);
}

@PostMapping(“/user”)
public void create(@RequestBody @Validated UserCreateRequest user) {
System.out.println(user.getName());
}
}
此时重启 Spring,并使用 curl 进行请求,可以得到结果:
$ curl -XGET ‘http://127.0.0.1:8080/user/100’
$ 用户 100
Repository
Spring 本身集成了 Spring Data JPA,用来作为访问数据库的 ORM 工具,它采用了 Hibernate 实现。在本教程,我们将实现 User 的增和查的工作。
添加依赖
修改 pom.xml,添加对 mysql 和 jpa 的支持。

<dependencies>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
服务配置
修改 /resources/application.properties,添加相关的设置。

spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.show-sql=true
添加 Repository 和 Entity
Repository 在 DDD 中是一个非常重要的概念,字面意思来讲它就是一个仓库。它屏蔽了 SQL 和数据库操作的细节,使得业务代码无需再考虑更细节的数据处理。它和 Mybatis 可以说是两个完全相反的流派。
Spring Data JPA 中,默认实现了 Crud 操作的 Repository,可以直接继承并使用这个框架进行快速的 CRUD 实现。
package com.spring.demo.demo.repo.repository;

import com.spring.demo.demo.repo.entity.User;

@Repository
public interface UserRepository extends CrudRepository<User, Integer> {}
对应数据库中的数据表,会有一个实体 Entity 来定义它的表结构。
package com.spring.demo.demo.repo.entity;

import javax.persistence.*;

@Entity
@Table(name=”t_user”)
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer gender;

// Getter & Setter

}

在 Service 调用中,即可简单的使用 save 方法来保存新的 User 数据。
package com.spring.demo.demo.service;

import com.spring.demo.demo.repo.entity.User;

@Service
public class UserService implements IUserService {

@Autowired
UserRepository userRepo;

public String findUser(int id) {
return “ 用户 ” + id;
}

public User createUser(User user) {
return userRepo.save(user);
}
}
最后在 Controller 中,修改 Service 方法并创建 User。
package com.spring.demo.demo.controller;

import com.spring.demo.demo.dto.UserCreateRequest;

@RestController
public class UserController {

@Autowired
IUserService userService;

@RequestMapping(“/user/{id}”)
public String find(@PathVariable int id) {
return userService.findUser(id);
}

@PostMapping(“/user”)
public void create(@RequestBody @Validated UserCreateRequest userReq) {

User user = new User();
user.setName(userReq.getName());
user.setGender(userReq.getGender());

user = userService.createUser(user);
System.out.println(“ 创建用户 ID=” + user.getId() + ” 用户名 =” + user.getName());
}
}
重启 Spring 并提交创建请求。
$ curl -XPOST ‘http://127.0.0.1:8080/user’ -H ‘Content-Type: application/json’ -d'{“name”:” 用户 A ”,”gender”:0}’
可以看到,在 console 中有创建成功的提示信息。
Hibernate: insert into t_user (gender, name) values (?, ?) 创建用户 ID=1 用户名 = 用户 A

缓存
对于不常改变的数据,常常需要进行缓存以提高系统性能和增加系统吞吐量。对此,Spring Cache 提供了缓存的基本实现。
添加依赖
修改 pom.xml,添加对 cache 的支持。

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
服务配置
修改 /resources/application.properties,添加相关的设置。

spring.cache.type=simple
打开开关
需要在 Application 中,打开 Cache 开关。
package com.spring.demo.demo;

import org.springframework.boot.SpringApplication;

@SpringBootApplication
@EnableCaching
public class DemoApplication {

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

}

使用 Cacheable 标注
对于 Cache 内容,需要添加一个 key 名来保存内容。
package com.spring.demo.demo.service;

import com.spring.demo.demo.repo.entity.User;

@Service
public class UserService implements IUserService {

@Autowired
UserRepository userRepo;

@Cacheable(cacheNames = “user”)
public User findUser(Integer id) {
System.out.println(“ 取得用户操作 ID=” + id);
return userRepo.findById(id).get();
}

public User createUser(User user) {
return userRepo.save(user);
}
}
重启 Spring,发送 GET 请求后可以看到,只有第一次执行了 SQL 操作,说明缓存处理已经完成。
$ curl -XGET ‘http://127.0.0.1:8080/user/1’
$ 用户 A
$ 用户 A
> 取得用户操作 ID=1=
> Hibernate: select user0_.id as id1_0_0_, user0_.gender as gender2_0_0_, user0_.name as name3_0_0_ from t_user user0_ where user0_.id=?
Redis
Spring 的默认 Cache 处理并不使用 Redis,要使用 Redis 作为缓存应用,需要添加 Redis 的框架支持。
添加依赖
修改 pom.xml,添加对 cache 的支持。

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
服务配置
修改 /resources/application.properties,添加相关的设置。

spring.redis.host=127.0.0.1
spring.redis.password=123456
spring.redis.port=6379
spring.redis.jedis.pool.max-active=8
序列化对象
由于要保存到 redis 中,保存的实体对象需要进行序列化。
package com.spring.demo.demo.repo.entity;

import java.io.Serializable;

@Entity
@Table(name=”t_user”)
public class User implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer gender;

// Getter & Setter

}

重启 Spring,再试一遍上节的操作,仍然是一样的结果,但缓存已经换为 redis。
$ curl -XGET ‘http://127.0.0.1:8080/user/1’
$ 用户 A
$ 用户 A
> 取得用户操作 ID=1
> Hibernate: select user0_.id as id1_0_0_, user0_.gender as gender2_0_0_, user0_.name as name3_0_0_ from t_user user0_ where user0_.id=?

退出移动版