Author: liuxiaopeng https://www.cnblogs.com/paddix/p/8215245.html
In the current development process, in order to achieve the maximum separation between the front end and the back end, the back-end interface only provides the data interface. The front-end obtains the data from the back-end through the Ajax request and renders it to the user.
The most common way we use is that the back-end will return a JSON string to the front-end. The front-end will parse the JSON string to generate JavaScript objects, and then process it.
This article will demonstrate how Spring boot implements this pattern. This article will focus on how to design a Restful API and implement the relevant API through Spring boot.
However, in order to better understand Restful style API, we first design a traditional data return interface, so that you can compare and understand.
1, Support for non Restful interfaces
Here we take the article list as an example to implement an interface to return the article list. The code is as follows:
@Controller @RequestMapping("/article") public class ArticleController { @Autowired private ArticleService articleService; @RequestMapping("/list.json") @ResponseBody public List<Article> listArticles(String title, Integer pageSize, Integer pageNum) { if (pageSize == null) { pageSize = 10; } if (pageNum == null) { pageNum = 1; } int offset = (pageNum - 1) * pageSize; return articleService.getArticles(title, 1L, offset, pageSize); } }
The implementation of this ArticleService is very simple, which simply encapsulates the operation of ArticleMapper. For the content of ArticleMapper, please refer to the previous article. The implementation classes of ArticleService are as follows:
@Service public class ArticleServiceImpl implements ArticleService { @Autowired private ArticleMapper articleMapper; @Override public Long saveArticle(@RequestBody Article article) { return articleMapper.insertArticle(article); } @Override public List<Article> getArticles(String title,Long userId,int offset,int pageSize) { Article article = new Article(); article.setTitle(title); article.setUserId(userId); return articleMapper.queryArticlesByPage(article,offset,pageSize); } @Override public Article getById(Long id) { return articleMapper.queryById(id); } @Override public void updateArticle(Article article) { article.setUpdateTime(new Date()); articleMapper.updateArticleById(article); } }
function Application.java This class, and then access: http://locahost:8080/article/list.json , you can see the following results:
ArticleServiceImpl is a very common class with only one Spring annotation @Service , identified as a bean for easy management through the Spring IoC container.
Let's take a look at the ArticleController class. In fact, people who have used Spring MVC should be familiar with these notes. Here's a brief explanation:
-
@Controller Identifies a class as a controller.
-
@The request mapping URL.
-
@The result returned by ResponseBody is converted to a JSON string.
-
@RequestBody means to receive the JSON format string parameter.
Through these three annotations, we can easily realize the function of returning JSON format data to the front end through URL. But you must have some doubts. Isn't it all Spring MVC? What does Spring boot have to do with it?
In fact, the function of Spring boot is to save us the process of configuration. Other functions are indeed provided by Spring and Spring MVC. You should remember that Spring boot provides automatic configuration services for us through various starter s. We have introduced this dependency in our project before
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
This is the jar package that all Spring boot web projects need to introduce. That is to say, as long as it is a Spring boot web project, the above functions are supported by default. Here we further find that developing web projects through Spring boot really saves us a lot of configuration work.
2, Restful API design
Now let's see how to implement the Restful API. Restful is a kind of technology, not a style of design. Experience summary of architecture essential "RESTful API" design skills , take a look at this recommendation.
In the traditional http interface design, we only use get and post methods, and then use our own defined vocabulary to express different operations, such as the above query article interface, we define article/list.json It can be accessed through get or post methods.
The Restful API is designed to represent CRUD related operations through HTTP. Therefore, in addition to the get and post methods, other HTTP methods, such as PUT, DELETE, HEAD, are used to represent operations with different meanings through different HTTP methods. Here is a set of Restful API designed by me for adding, deleting, modifying and querying articles:
As you can see here, the URL is only the way to identify the resource, and the specific behavior is specified by the HTTP method.
3, Restful API implementation
Now let's take a look at how to implement the above interface. Let's not talk about the rest, but look at the code directly
@RestController @RequestMapping("/rest") public class ArticleRestController { @Autowired private ArticleService articleService; @RequestMapping(value = "/article", method = POST, produces = "application/json") public WebResponse<Map<String, Object>> saveArticle(@RequestBody Article article) { article.setUserId(1L); articleService.saveArticle(article); Map<String, Object> ret = new HashMap<>(); ret.put("id", article.getId()); WebResponse<Map<String, Object>> response = WebResponse.getSuccessResponse(ret); return response; } @RequestMapping(value = "/article/", method = DELETE, produces = "application/json") public WebResponse<?> deleteArticle(@PathVariable Long id) { Article article = articleService.getById(id); article.setStatus(-1); articleService.updateArticle(article); WebResponse<Object> response = WebResponse.getSuccessResponse(null); return response; } @RequestMapping(value = "/article/", method = PUT, produces = "application/json") public WebResponse<Object> updateArticle(@PathVariable Long id, @RequestBody Article article) { article.setId(id); articleService.updateArticle(article); WebResponse<Object> response = WebResponse.getSuccessResponse(null); return response; } @RequestMapping(value = "/article/", method = GET, produces = "application/json") public WebResponse<Article> getArticle(@PathVariable Long id) { Article article = articleService.getById(id); WebResponse<Article> response = WebResponse.getSuccessResponse(article); return response; } }
Let's analyze this code again. The difference between this code and the previous code is that:
-
We use the annotation @ RestController instead of @ Controller. However, this annotation is not provided by Spring boot, but is provided in Spring MVC4 to indicate a Controller that supports Restful.
-
Three URL mappings in this class are the same, that is, / article/, which is not allowed in the class identified by @ Controller. Here, we can distinguish by method. The purpose of produces is to indicate that the type of returned result is JSON.
-
@The annotation PathVariable is also provided by Spring MVC to indicate that the value of the variable is obtained from the access path.
So it seems that this code has little to do with spring boot. Spring boot only provides automatic configuration function, which is a very important reason why spring boot is very comfortable to use, because it is very, very small intrusive, and you can't feel its existence.
4, Testing
The code is finished, how to test it?
Except GET method, we can't access it directly through browser. Of course, we can send all kinds of http requests directly through postman.
However, I still support testing methods through unit test classes. recommend: Spring Boot unit test details + practical tutorial . Here we test each method through Junit:
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Application.class) public class ArticleControllerTest { @Autowired private ArticleRestController restController; private MockMvc mvc; @Before public void setUp() throws Exception { mvc = MockMvcBuilders.standaloneSetup(restController).build(); } @Test public void testAddArticle() throws Exception { Article article = new Article(); article.setTitle("Test article 000000"); article.setType(1); article.setStatus(2); article.setSummary("This is a test article"); Gson gosn = new Gson(); RequestBuilder builder = MockMvcRequestBuilders .post("/rest/article") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON_UTF8) .content(gosn.toJson(article)); MvcResult result = mvc.perform(builder).andReturn(); System.out.println(result.getResponse().getContentAsString()); } @Test public void testUpdateArticle() throws Exception { Article article = new Article(); article.setTitle("Update test article"); article.setType(1); article.setStatus(2); article.setSummary("This is an update test article"); Gson gosn = new Gson(); RequestBuilder builder = MockMvcRequestBuilders .put("/rest/article/1") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON_UTF8) .content(gosn.toJson(article)); MvcResult result = mvc.perform(builder).andReturn(); } @Test public void testQueryArticle() throws Exception { RequestBuilder builder = MockMvcRequestBuilders .get("/rest/article/1") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON_UTF8); MvcResult result = mvc.perform(builder).andReturn(); System.out.println(result.getResponse().getContentAsString()); } @Test public void testDeleteArticle() throws Exception { RequestBuilder builder = MockMvcRequestBuilders .delete("/rest/article/1") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON_UTF8); MvcResult result = mvc.perform(builder).andReturn(); } }
The execution results will not be posted here. If you are interested, you can experiment on your own. There are few points to explain for the whole class. The main reason for these things is that they have nothing to do with Spring boot. The reason for supporting these operations is the introduction of corresponding starter s mentioned in the previous article:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
Because the HTTP request is to be executed, MockMvc is used here. The ArticleRestController is instantiated by injection and cannot be directly new. Otherwise, the ArticleRestController cannot be managed through the Spring IoC container, and other classes it depends on cannot be injected normally. Through MockMvc, we can easily implement HTTP DELETE/PUT/POST and other methods.
5, Summary
This article explains that if you use spring boot to implement Restful API, in fact, most of the things are provided by spring and Spring MVC. Spring boot only provides the function of automatic configuration.
However, it is this kind of automatic configuration that reduces a lot of development and maintenance work for us, so that we can more easily and efficiently implement a web project, so that we can focus more on the development of the business itself, and do not need to care about the things of the framework.
Pay attention to the official account Java technology stack reply to "interview" to get 2020 of my most comprehensive questions and answers.
Recommend to my blog to read more:
1.Java JVM, collection, multithreading and new features
2.Spring MVC, Spring Boot, Spring Cloud series tutorials
3.Maven, Git, Eclipse, Intellij IDEA series tools tutorial
4.Latest interview questions of Java, backend, architecture, Alibaba and other large factories
Feel good, don't forget to like + forward Oh!