本文仅仅使用一个示例来说明restful的使用,是以springboot的2.0版本作为基础的。
基于springboot的示例,包含get、post、put和delete,以及使用resttemplate接收json。参数形式可以使用restful,也可以使用形如:url?id=xx,使用方式不同。
通过浏览器地址访问的都是get的请求方式,post、put和delete则可能需要专门的代码或工具访问。也就是post、put和delete不能通过浏览器的地址栏访问。
本文分为三部分,即pom.xml、代码和测试。
一、pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient-cache -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-cache</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Add typical dependencies for a web application -->
<!-- Adds Tomcat and Spring MVC, along others -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
二、源码
由于没有业务,代码比较简单,一般也不需要进行什么说明,就是实现一个CRUD。本示例没有连接数据库,直接通过方法造一些数据放在list中。
1、UserBean
package com.win.model;
import java.io.Serializable;
import lombok.Data;
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1946944818933250011L;
private long id;
private String name;
private int age;
private double salary;
public User() {
id = 0;
}
public User(long id, String name, int age, double salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
}
2、CustomErrorType
package com.win.util;
public class CustomErrorType {
private String errorMessage;
public CustomErrorType(String errorMessage){
this.errorMessage = errorMessage;
}
public String getErrorMessage() {
return errorMessage;
}
}
3、Service接口
package com.win.service;
import java.util.List;
import com.win.model.User;
public interface UserService {
User findById(long id);
User findByName(String name);
void saveUser(User user);
void updateUser(User user);
void deleteUserById(long id);
List<User> findAllUsers();
void deleteAllUsers();
boolean isUserExist(User user);
}
4、Service接口实现
package com.win.service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Service;
import com.win.model.User;
@Service("userService")
public class UserServiceImpl implements UserService {
private static final AtomicLong counter = new AtomicLong();
private static List<User> users;
static {
users = populateDummyUsers();
}
@Override
public List<User> findAllUsers() {
return users;
}
@Override
public User findById(long id) {
for (User user : users) {
if (user.getId() == id) {
return user;
}
}
return null;
}
@Override
public User findByName(String name) {
for (User user : users) {
if (user.getName().equalsIgnoreCase(name)) {
return user;
}
}
return null;
}
@Override
public void saveUser(User user) {
user.setId(counter.incrementAndGet());
users.add(user);
}
@Override
public void updateUser(User user) {
int index = users.indexOf(user);
users.set(index, user);
}
@Override
public void deleteUserById(long id) {
for (Iterator<User> iterator = users.iterator(); iterator.hasNext();) {
User user = iterator.next();
if (user.getId() == id) {
iterator.remove();
}
}
}
@Override
public boolean isUserExist(User user) {
return findByName(user.getName()) != null;
}
@Override
public void deleteAllUsers() {
users.clear();
}
private static List<User> populateDummyUsers() {
List<User> users = new ArrayList<User>();
users.add(new User(counter.incrementAndGet(), "Sam", 30, 70000));
users.add(new User(counter.incrementAndGet(), "Tom", 40, 50000));
users.add(new User(counter.incrementAndGet(), "Jerome", 45, 30000));
users.add(new User(counter.incrementAndGet(), "Silvia", 50, 40000));
return users;
}
}
5、Controller
package com.win.controller;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import com.win.model.User;
import com.win.service.UserService;
import com.win.util.CustomErrorType;
@RestController
@RequestMapping("/api")
public class RestApiController {
public static final Logger logger = LoggerFactory.getLogger(RestApiController.class);
@Autowired
UserService userService;
// -Retrieve All Users
@RequestMapping(value = "/list", method = RequestMethod.GET)
public ResponseEntity<List<User>> listAllUsers() {
List<User> users = userService.findAllUsers();
if (users.isEmpty()) {
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
// Retrieve Single User
@RequestMapping(value = "/list/{id}", method = RequestMethod.GET)
public ResponseEntity<?> getUser(@PathVariable("id") long id) {
logger.info("user id {}", id);
User user = userService.findById(id);
if (user == null) {
logger.error("user id {} not found.", id);
return new ResponseEntity(new CustomErrorType("user id " + id + " not found"), HttpStatus.NOT_FOUND);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}
// Retrieve Single User
// url形如:http://localhost:8080/api/list2?id=4
@RequestMapping(value = "/list2", method = RequestMethod.GET)
public ResponseEntity<?> getUser2(@RequestParam long id) {
logger.info("user id {}", id);
User user = userService.findById(id);
if (user == null) {
logger.error("user id {} not found.", id);
return new ResponseEntity(new CustomErrorType("user id " + id + " not found"), HttpStatus.NOT_FOUND);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}
@RequestMapping(value = "/testpostproxy/", method = RequestMethod.POST)
public ResponseEntity<String> testHttpClientPostProxy(String name, String password) {
logger.info("name : {}, password : {}", name, password);
if (name == null || password == null) {
return new ResponseEntity(new CustomErrorType("name or password is null ."), HttpStatus.NO_CONTENT);
}
return new ResponseEntity<String>("name=" + name + ",password=" + password, HttpStatus.OK);
}
// Create a User
@RequestMapping(value = "/add/", method = RequestMethod.POST)
public ResponseEntity<?> createUser(User user, UriComponentsBuilder ucBuilder) {
logger.info("创建 User : {}", user);
if (userService.isUserExist(user)) {
logger.error("不能创建. name {} 已存在", user.getName());
return new ResponseEntity(
new CustomErrorType("不能创建. name " + user.getName() + " 已存在."),
HttpStatus.CONFLICT);
}
userService.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/api/list/{id}").buildAndExpand(user.getId()).toUri());
return new ResponseEntity<String>(headers, HttpStatus.CREATED);
}
@RequestMapping(value = "/add/json/", method = RequestMethod.POST)
public ResponseEntity<?> createUserWithJson(@RequestBody User user, UriComponentsBuilder ucBuilder) {
logger.info("创建 User : {}", user);
if (userService.isUserExist(user)) {
logger.error("不能创建. name {} 已存在", user.getName());
return new ResponseEntity(
new CustomErrorType("不能创建. name " + user.getName() + " 已存在."),
HttpStatus.CONFLICT);
}
userService.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/api/list/{id}").buildAndExpand(user.getId()).toUri());
return new ResponseEntity<String>(headers, HttpStatus.CREATED);
}
// Update a User
@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT)
public ResponseEntity<?> updateUser(@PathVariable("id") long id, @RequestBody User user) {
logger.info("更新user id {}", id);
User currentUser = userService.findById(id);
if (currentUser == null) {
logger.error("不能更新. id {} not found.", id);
return new ResponseEntity(new CustomErrorType("不能更新. id " + id + " not found."),
HttpStatus.NOT_FOUND);
}
currentUser.setName(user.getName());
currentUser.setAge(user.getAge());
currentUser.setSalary(user.getSalary());
userService.updateUser(currentUser);
return new ResponseEntity<User>(currentUser, HttpStatus.OK);
}
// Delete a User
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
public ResponseEntity<?> deleteUser(@PathVariable("id") long id) {
logger.info("删除用户 id {}", id);
User user = userService.findById(id);
if (user == null) {
logger.error("不能删除, id {} not found.", id);
return new ResponseEntity(new CustomErrorType("不能删除, id " + id + " not found."),
HttpStatus.NOT_FOUND);
}
userService.deleteUserById(id);
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}
// Delete All Users
@RequestMapping(value = "/delUsers/", method = RequestMethod.DELETE)
public ResponseEntity<User> deleteAllUsers() {
logger.info("删除所有用户");
userService.deleteAllUsers();
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}
}
6、系统配置文件
server:
port: 8080
7、服务启动类
package com.win;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication(scanBasePackages = { "com.win" }) // same as @Configuration @EnableAutoConfiguration
// @ComponentScan combined
public class SpringBootRestApiApp {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SpringBootRestApiApp.class, args);
}
}
三、测试类
也可以直接使用浏览器和postman一起进行验证,或者自己如下文写个测试用例验证。
package com.win;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;
import org.springframework.web.client.RestTemplate;
import org.testng.annotations.Test;
import com.win.model.User;
public class SpringBootRestTestClient {
public static final String REST_SERVICE_URI = "http://localhost:8080/api";
/* GET */
@SuppressWarnings("unchecked")
private static void listAllUsers() {
System.out.println("Testing listAllUsers API-----------");
RestTemplate restTemplate = new RestTemplate();
List<LinkedHashMap<String, Object>> usersMap = restTemplate.getForObject(REST_SERVICE_URI + "/list",
List.class);
if (usersMap != null) {
for (LinkedHashMap<String, Object> map : usersMap) {
System.out.println("User : id=" + map.get("id") + ", Name=" + map.get("name") + ", Age="
+ map.get("age") + ", Salary=" + map.get("salary"));
}
} else {
System.out.println("No user exist----------");
}
}
/* GET */
private static void getUser() {
System.out.println("Testing getUser API----------");
RestTemplate restTemplate = new RestTemplate();
User user = restTemplate.getForObject(REST_SERVICE_URI + "/list/1", User.class);
System.out.println(user);
}
/* POST */
@Test
private static void createUser() {
System.out.println("Testing create User API----------");
RestTemplate restTemplate = new RestTemplate();
User user = new User(0, "Sarah", 51, 134);
URI uri = restTemplate.postForLocation(REST_SERVICE_URI + "/add/json/", user, User.class);
System.err.println("Location : " + uri.toASCIIString());
}
/* PUT */
@Test
private static void updateUser() {
System.out.println("Testing update User API----------");
RestTemplate restTemplate = new RestTemplate();
User user = new User(1, "Tomy", 33, 70000);
restTemplate.put(REST_SERVICE_URI + "/update/1", user);
System.out.println(user);
}
/* DELETE */
@Test
private static void deleteUser() {
System.out.println("Testing delete User API----------");
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete(REST_SERVICE_URI + "/delete/3");
}
/* DELETE */
@Test
private static void deleteAllUsers() {
System.out.println("Testing all delete Users API----------");
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete(REST_SERVICE_URI + "/delUsers/");
}
}
以上简单的使用springboot实现了restful。