实战专车系列教程使用的 SpringBoot 版本为 2.1.6.RELEASE,所有实战示例都会经过严格测试,如果因版本问题导致错误,请自行 Google 或者咨询。
该趟专车是开往 SpringBoot Restful Web 应用的实战专车,主要讲解如何快速搭建一个 Restful 风格的 Web 应用
第一个问题:如何使用 SpringBoot 快速搭建一个 Web 应用?
第二个问题:如何让 SpringBoot 接收和响应的 json 数据字段是下划线风格而不是驼峰式风格?
首先在 Idea 中创建一个名为 boot-example 的 project,作为整个项目的父模块,然后在其下面创建一个名为 boot-example-web 的子模块
在父模块中添加管理依赖
<properties>
<spring.boot.version>2.1.6.RELEASE</spring.boot.version>
<lombok.version>1.16.10</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
在子模块中添加需要的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
依赖添加完成之后就可以开始愉快的编写代码了
第一步:既然开发一个 web 应用,那么必然要启动该 web 服务,毫无疑问,我们需要创建一个启动类
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
启动类很简单,第一点需要在我们的启动类上添加@SpringBootApplication 注解,来标注这是一个 SpringBoot 应用,第二点调用 SpringApplication.run 方法来启动 SpringBoot 应用。该方法是整个 SpringBoot 的核心,里面做了很多的初始化工作,后续有机会来具体分析下 SpringBoot 的启动原理。
第二步:创建一个 Restful 风格的控制器
@RestController
@RequestMapping("/students")
public class StudentController {
private static List<Student> studentList = new ArrayList<>();
static {
studentList.add(new Student(100001, "jack", 22));
studentList.add(new Student(100002, "lucky", 23));
studentList.add(new Student(100003, "jone", 24));
studentList.add(new Student(100004, "lucy", 25));
studentList.add(new Student(100005, "lily", 26));
}
@GetMapping("/")
public List<Student> listStudent() {
return studentList;
}
@GetMapping("id/{id}")
public Student getStudent(@PathVariable("id") Integer id) {
return studentList.stream()
.filter(student -> Objects.equals(student.getId(), id))
.findFirst()
.orElse(new Student(999999, "default", 18));
}
@PostMapping("/")
public List<Student> addStudent(@RequestBody Student student) {
studentList.add(student);
return studentList;
}
@PutMapping("/")
public List<Student> updateStudent(@RequestBody Student student) {
studentList.removeIf(stu -> Objects.equals(stu.getId(), student.getId()));
studentList.add(student);
return studentList;
}
}
控制器也很简单,第一点要在类上使用@RestController 和@RequestMapping 注解,@RestController 表示当前控制器中所有方法的返回值都是 json 格式,@RequestMapping("/students")注解来指定当前控制器的请求路径;第二点在每个方法上添加@RequestMapping,用来指定当前方法的路由。如上的@GetMapping、@PostMapping、@PutMapping 注解都是@RequestMapping 注解加上对应 method 的组合,只是使用起来更简洁罢了。
第三步:定义实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Integer id;
private String name;
private Integer age;
}
第四步:依次请求如上的路由路径
http://localhost:8080/students/ GET 请求
[
{
"id": 100001,
"name": "jack",
"age": 22
},
{
"id": 100002,
"name": "lucky",
"age": 23
},
{
"id": 100003,
"name": "jone",
"age": 24
},
{
"id": 100004,
"name": "lucy",
"age": 25
},
{
"id": 100005,
"name": "lily",
"age": 26
}
]
http://localhost:8080/students/id/2 GET 请求
{
"id": 999999,
"name": "default",
"age": 18
}
http://localhost:8080/students/ POST 请求
请求参数:
{
"id":100006,
"name":"add-student",
"age":222
}
响应结果:
[
{
"id": 100001,
"name": "jack",
"age": 22
},
{
"id": 100002,
"name": "lucky",
"age": 23
},
{
"id": 100003,
"name": "jone",
"age": 24
},
{
"id": 100004,
"name": "lucy",
"age": 25
},
{
"id": 100005,
"name": "lily",
"age": 26
},
{
"id": 100006,
"name": "add-student",
"age": 222
}
]
http://localhost:8080/students/ PUT 请求
请求参数:
{
"id":100006,
"name":"add-student2",
"age":222
}
响应结果:
[
{
"id": 100001,
"name": "jack",
"age": 22
},
{
"id": 100002,
"name": "lucky",
"age": 23
},
{
"id": 100003,
"name": "jone",
"age": 24
},
{
"id": 100004,
"name": "lucy",
"age": 25
},
{
"id": 100005,
"name": "lily",
"age": 26
},
{
"id": 100006,
"name": "add-student2",
"age": 222
}
]
到这里一个基于 Rest 风格的 Web 应用已经搭建完成。在实际的开发过程中,我们可以希望我们的 json 数据中的字段是下划线风格的,那么我们需要怎么做?
将如上实体类和控制器拷贝一下,然后将其修改为 Person、PersonController,具体代码如下
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class Person {
private Integer personId;
private String personName;
private Integer personAge;
}
@RestController
@RequestMapping("/persons")
public class PersonController {
private static List<Person> personList = new ArrayList<>();
static {
personList.add(new Person(100001, "jack", 22));
personList.add(new Person(100002, "lucky", 23));
personList.add(new Person(100003, "jone", 24));
personList.add(new Person(100004, "lucy", 25));
personList.add(new Person(100005, "lily", 26));
}
@GetMapping("/")
public List<Person> listPerson() {
return personList;
}
@GetMapping("id/{id}")
public Person getPerson(@PathVariable("id") Integer id) {
return personList.stream()
.filter(person -> Objects.equals(person.getPersonId(), id))
.findFirst()
.orElse(new Person(999999, "default", 18));
}
@PostMapping("/")
public List<Person> addPerson(@RequestBody Person person) {
personList.add(person);
return personList;
}
@PutMapping("/")
public List<Person> updatePerson(@RequestBody Person person) {
personList.removeIf(p -> Objects.equals(p.getPersonId(), person.getPersonId()));
personList.add(person);
return personList;
}
}
http://localhost:8080/persons/ GET 请求
[
{
"person_id": 100001,
"person_name": "jack",
"person_age": 22
},
{
"person_id": 100002,
"person_name": "lucky",
"person_age": 23
},
{
"person_id": 100003,
"person_name": "jone",
"person_age": 24
},
{
"person_id": 100004,
"person_name": "lucy",
"person_age": 25
},
{
"person_id": 100005,
"person_name": "lily",
"person_age": 26
}
]
http://localhost:8080/persons/ POST 请求
请求参数:
{
"person_id":100006,
"person_name":"add-student",
"person_age":222
}
响应结果:
[
{
"person_id": 100001,
"person_name": "jack",
"person_age": 22
},
{
"person_id": 100002,
"person_name": "lucky",
"person_age": 23
},
{
"person_id": 100003,
"person_name": "jone",
"person_age": 24
},
{
"person_id": 100004,
"person_name": "lucy",
"person_age": 25
},
{
"person_id": 100005,
"person_name": "lily",
"person_age": 26
},
{
"person_id": 100006,
"person_name": "add-student",
"person_age": 222
}
]
如上实现了我们提出的第二个疑问,乍一看和之前的代码除了名字之外没有什么区别,仔细观察会发现 Person 实体类上多了一个@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)注解,该注解的意思就是当前实体字段采用下滑线的风格。
@JsonNaming 注解的其它命名策略
编号 | 策略 | 示例 |
---|---|---|
1 | SnakeCaseStrategy | person_id |
2 | KebabCaseStrategy | person-id |
3 | UpperCamelCaseStrategy | PersonId |
4 | LowerCaseStrategy | personid |
创建一个 Web 应用步骤:
第一步:创建一个启动类,需要使用@SpringBootApplication 注解标注,并调用 SpringApplication.run 方法
第二步:创建控制器,使用@RestController 和@RequestMapping 标注
第三步:如果希望得到不同格式的 json 数据,可以使用@JsonNaming 注解指定命名策略
SpringBoot Restful风格Web应用