We can’t avoid bias at any time, even when we’re talking about technology, and no technology is really absolute.

British author swift in gulliver’s travels in a playful tone described the lion’s share of the pie and little head (the contention is eating eggs really should be from bulk cracked when peeling or small head broken) had been intended to sarcasm in the British parliament that points due to make a mountain out of a molehill party made absurd mp, but in fact each of us is a member of the set big or small head, Just big heads on some issues and small heads on others. We must admit that swift’s allegory reveals a much deeper meaning than the author’s intention.

Define the Web API specification

API development is familiar to programmers in Web development, and there are several options for building Web apis using SpringBoot. You can either build RESTful Web apis using Spring-boot-starter-Jersey, Either opt for spring-boot-starter-Hateoas to build a more relevant and relatively “smart” Web API, but there is a learning cost to introducing either framework, which is fine if developed by one person, and high communication costs if developed by a team.

Therefore, we can choose the relatively loose RPC over HTTP approach to building Web apis. Let’s start by defining a simple JSON response format:

{
    "code" : 0."msg" : "XXXXX"."data": {... }}Copy the code

Where code represents the status of the call result, 0 indicates success, and non-0 indicates failure, and fields that need to be prompted can be passed in according to the status. The data field is used to define the Web API-specific response content in the specification.

In actual combat

Create a Spring Boot project

We can then build our API from the specification by referring to boot-start, or build a new project using start.spring. IO and rely on the spring-boot-starter-Web module.

The sample service

Here we create a simple query service, QueryUserService, with the following code:

@Service
public class QueryUserService {
    public List<Man> query(a){
        Man man1 = new Man("mickjoust"."1"."111111");
        Man man2 = new Man("mia"."1"."6666666");
        Man man3 = new Man("max"."1"."33333333");
        List<Man> manList = new ArrayList<>();
        manList.add(man1);
        manList.add(man2);
        manList.add(man3);
        returnmanList; }}Copy the code

POJO objects to query:

public class Man {

    private String name;
    private String age;
    private String phone;

    public Man(String name, String age, String phone) {
        this.name = name;
        this.age = age;
        this.phone = phone;
}
// also omit get, set
Copy the code

Provides the API

Using the Spring stack, we can quickly build a Web API. Here we create an API Controller:

@RestController
@SpringBootApplication
public class QueryUserController {

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

    @Autowired
    private QueryUserService queryUserService;

    @RequestMapping("/query1")
    public List<Man> getUsers(a){
        returnqueryUserService.query(); }}Copy the code

Where @restController indicates that this is a REST style API.

Strengthen the constraints

By the last section, we were able to provide a Web API with the ability to query user services, but wait, the response data doesn’t seem to have the specification we defined earlier, so we extend the code like this:

@RequestMapping("/query2")
public Map<String,Object> getUsersExt(a){
    Map<String,Object> resultMap = new HashMap<>();
    if (null! = queryUserService.query() || ! queryUserService.query().isEmpty()){ resultMap.put("code".0);
        resultMap.put("msg"."sucess");
        resultMap.put("data",queryUserService.query());
    } else {
        resultMap.put("code".1);
        resultMap.put("msg"."error");
        resultMap.put("data"."");
    }
    return resultMap;
}
Copy the code

However, this is the easiest and most wrong thing to do, because the next developer will look at the code and rave about how hard this one-off code is to maintain.

To develop a Web API that conforms to our Web API specification, there are two options —

  1. Explicit strong type wrapper
  2. Implicit conversion

According to the first point, the spring – the boot – starter – web has provided MappingJackson2HttpMessageConverter type conversion for object types to JSON, but considering a lot of people like to use fastjson, Refer to the article “Custom Configuration, Extend Spring MVC Configuration and Use FastJSON” for Converter configuration. Therefore, we only need to provide a response class, such as:

public class ApiResponse<T> {

    public static final int SUCCESS_CODE = 0;
    public static final int ERROR_CODE = 1;
    private int code; //0- success, 1 error
    private String msg;
    private T data;

    public static <T> ApiResponse<T> success(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(SUCCESS_CODE);
        response.setData(data);
        response.setMsg("sucess");
        return response;
    }

    public static <T> ApiResponse<T> error(String error,T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(ERROR_CODE);
        response.setData(data);// What should I do about this? For mobile terminals, throwing null will directly cause the app to exit
        response.setMsg((null==error||"".equals(error)?"error":error));
        return response;
    }
// I just don't write get, set
Copy the code

Then, all Web API processes are uniformly defined to return ApiResponse as the result type:

@RequestMapping("/query3")
public ApiResponse<List<Man>> getUsers3(){
    return ApiResponse.success(queryUserService.query());
}
Copy the code

However, this pattern is not developer-friendly with its heavy emphasis on canonical governance (although architects like it because it is manageable), but it is not optimal from an API user’s point of view, and the best approach would be implicit automatic conversion.

Abstracthttpmessage-converter is an abstracthttpmessage-converter , which is an abstracthttpmessage-Converter . If you want to support a view, you will have a problem.

Under implicit automatic conversion, the user’s Web API method definition remains unchanged and returns the original value type (for example: List of WebMvcConfigurerAdapter configurerAdapter configurerAdapter configurerAdapter configurerAdapter configurerAdapter configurerAdapter WebMvcConfigurer in java8, interfaces can provide the default implementation method, do not need to wrap a separate layer.

An API conundrum

Although it is convenient to write native API, especially with Spring Boot, there is also a core problem that is not solved: API documentation. One of the functions of API is not only to provide corresponding functions, but also to tell users how to use it. (For many developers, faced with a large number of tedious documentation, Hands up if you’ve ever been hurt!)

One of the challenges is that designing for synchronization of interface changes and document changes can be a headache when apis are used by different teams.

To alleviate this problem, there are a number of API Doc and API Mock libraries that can be easily used, such as Swagger. Build RESTful API Documentation with Swagger 2.

summary

This article mainly introduces the method of building Web API according to a certain specification. This method is not necessarily optimal, but provides a “stupid way” to build API, while practicing a simple boot application, as well as the shortcomings and shortcomings of API and mitigation methods. How to strike a balance between constraint and convenience is a problem worth thinking about.

Finally, with regards to MVC configuration in boot, spring-boot-starter-web will automatically configure some of our spring MVC essential components by default, as follows:

1, the necessary ViewResolver, such as ContentNegotiatingViewResolver and Bean – NameViewResolver. -2. Register the necessary Converter, GenericConverter, and Formatter beans with the IoC container. -3. Add a series of HttpMessageconverters to support Web requests and corresponding type conversions. -4. Automatically configure and register MessageCodesResolver.

Remember, any time we build a project, we have a choice. For example, if we are not happy with the SpringMVC component Settings provided by default, we can register a new bean definition of the same type in the IoC container to replace it. You can either provide a bean definition based on the WebMvcConfigurerAdapter type, or you can provide an @Configuration class annotated with @EnableWebMVC to take over all SpringMVC Configuration and completely reconfigure it yourself.

The resources

2. Spring Boot Revealed


Keep doing it, and we’ll go all the way. If you have more thoughts on thinking, welcome to find me in another place, Jane Book Search: Mickjoust