Developing a RESTful service
This section describes how to develop a pure RESTful service based on Spring Boot.
1. Creating the POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.my.study.springboot</groupId>
<artifactId>restful-service</artifactId>
<version>0.0.1-RELEASE</version>
<properties>
<!-- Generic properties -->
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.14.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. Writing the Code
package com.my.study.restful;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
package com.my.study.restful.controller;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import com.my.study.restful.entity.Employee;
import com.my.study.restful.mockdb.EmployeeDB;
@RestController
@CrossOrigin(origins = "*", methods = { RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT,
RequestMethod.DELETE })
public class EmployeeController {
// Query all employees
@RequestMapping(value = "/employee/", method = RequestMethod.GET)
public ResponseEntity<List<Employee>> listAllEmployees() {
List<Employee> employees = EmployeeDB.findAllEmployees();
if (employees.isEmpty()) {
// You many decide to return HttpStatus.NOT_FOUND
return new ResponseEntity<List<Employee>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Employee>>(employees, HttpStatus.OK);
}
// Query one employee by ID
@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
public ResponseEntity<Employee> findEmployee(@PathVariable("id") int id) {
Employee employee = EmployeeDB.findEmployee(id);
if (null == employee) {
return new ResponseEntity<Employee>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Employee>(employee, HttpStatus.OK);
}
// Add one employee
@RequestMapping(value = "/employee/", method = RequestMethod.POST)
public ResponseEntity<Void> createEmployee(@RequestBody Employee employee, UriComponentsBuilder ucBuilder) {
if (null != EmployeeDB.findEmployee(employee.getId())) {
return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}
EmployeeDB.addEmployee(employee);
HttpHeaders headers = new HttpHeaders();
// This is to send client a URL of how to get added employee
headers.setLocation(ucBuilder.path("/employee/{id}").buildAndExpand(employee.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
// Update employee by ID
@RequestMapping(value = "/employee/{id}", method = RequestMethod.PUT)
public ResponseEntity<Employee> updateEmployee(@PathVariable("id") long id, @RequestBody Employee employee) {
Employee currentEmployee = EmployeeDB.findEmployee(employee.getId());
if (null == currentEmployee) {
return new ResponseEntity<Employee>(HttpStatus.NOT_FOUND);
}
EmployeeDB.updateEmployee(employee);
return new ResponseEntity<Employee>(employee, HttpStatus.OK);
}
// Delete employee by ID
@RequestMapping(value = "/employee/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Void> deleteEmployee(@PathVariable("id") int id) {
Employee currentEmployee = EmployeeDB.findEmployee(id);
if (null == currentEmployee) {
return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
}
EmployeeDB.deleteEmployee(id);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
// Delete all employees
@RequestMapping(value = "/employee/", method = RequestMethod.DELETE)
public ResponseEntity<Void> deleteAllEmployees() {
EmployeeDB.deleteAll();
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
}
package com.my.study.restful.entity;
/**
* Entity Object
*/
public class Employee {
private int id;
private String name;
private int age;
private String desc;
public Employee() {
}
public Employee(int id, String name, int age, String desc) {
this.id = id;
this.name = name;
this.age = age;
this.desc = desc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
package com.my.study.restful.mockdb;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.my.study.restful.entity.Employee;
/**
* Employee mock DB
*/
public class EmployeeDB {
private static final List<Employee> EMPLOYEES = new ArrayList<>();
static {
for (int i = 0; i < 3; i++) {
EMPLOYEES.add(new Employee(i, "user" + i, 20 + i, "desc " + i + "."));
}
}
public static Employee findEmployee(int id) {
for (Employee e : EMPLOYEES) {
if (e.getId() == id) {
return e;
}
}
return null;
}
public static List<Employee> findAllEmployees() {
return EMPLOYEES;
}
public static synchronized void addEmployee(Employee employee) {
EMPLOYEES.add(employee);
}
public static void updateEmployee(Employee employee) {
for (Employee e : EMPLOYEES) {
if (e.getId() == employee.getId()) {
e.setName(employee.getName());
e.setAge(employee.getAge());
e.setDesc(employee.getDesc());
return;
}
}
}
public static void deleteEmployee(int id) {
Iterator<Employee> it = EMPLOYEES.iterator();
while (it.hasNext()) {
Employee e = it.next();
if (e.getId() == id) {
it.remove();
return;
}
}
}
public static void deleteAll() {
EMPLOYEES.clear();
}
}
3. Code Structure
4. Run The RESTful service
C:\D\work\projects\sts\springboot-restful>java -jar target/restful-service-0.0.1-RELEASE.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.14.RELEASE)
2018-07-04 13:48:45.735 INFO 23120 --- [ main] com.my.study.restful.Main : Starting Main v0.0.1-RELEASE on CNENWANGS56L1C with PID 23120 (C:\D\work\projects\sts\springboot-restful\target\restful-service-0.0.1-RELEASE.jar started by wangs56 in C:\D\work\projects\sts\springboot-restful)
2018-07-04 13:48:45.747 INFO 23120 --- [ main] com.my.study.restful.Main : No active profile set, falling back to default profiles: default
2018-07-04 13:48:45.997 INFO 23120 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@69663380: startup date [Wed Jul 04 13:48:45 CST 2018]; root of context hierarchy
......
2018-07-04 13:48:53.963 INFO 23120 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-07-04 13:48:54.036 INFO 23120 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-07-04 13:48:54.037 INFO 23120 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-07-04 13:48:54.146 INFO 23120 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-07-04 13:48:54.459 INFO 23120 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-07-04 13:48:54.620 INFO 23120 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2018-07-04 13:48:54.649 INFO 23120 --- [ main] com.my.study.restful.Main : Started Main in 10.318 seconds (JVM running for 12.145)
To gracefully exit the application, press ctrl-c
.
5. Testing RESTful service