Introduction to the

DynamicApi is a tool for simplifying Controller code in SpringBoot projects by mapping Service code to accessible API addresses using @DynamicAPI annotations.

Rely on

Maven rely on

<dependency>
    <groupId>io.github.zhaord</groupId>
    <artifactId>dynamic-api-boot-starter</artifactId>
    <version>0.3</version>
</dependency>
Copy the code

Gradle rely on

compile group: 'io.github.zhaord'.name: 'dynamic-api-boot-starter'.version: '0.3'
Copy the code

Hello World

Create a service impL, such as UserService, and create a method getHello that annotates the class using DynamicApi

@DynamicApi
public class UserService {
 public String getHello(String name){
 return "hello,"+name; }}Copy the code

Run the project, through the browser to http://localhost:8080/api/service/user/getHello? name=zhaord

The mapping path

For example, the UserService class has the following code

@DynamicApi
public class UserService {
    public String getHello(String name){
        return "hello,"+name;
    }

    public String sayHello(String name){
        return "say hello,"+name;
    }

    public String addName(String name){
        return "add,"+name;
    }

    public String updateName(String name){
        return "update,"+name;
    }

    public String removeName(String name){
        return "remove,"+name; }}Copy the code

The mapping path is as follows

  • [Http Get] /api/service/user/getHello

  • [Http Post] /api/service/user/sayHello

  • [Http Post] /api/service/user/saveName

  • [Http Put] /api/service/user/updateName

  • [Http Delete] /api/service/user/removeName

Mapping rules

  • The generated accessible interface with/API /service as the fixed prefix

  • The UserService class is mapped to /user. The first letter of the class name is lowercase. The suffix Service, AppService, Application, and ApplicationService are removed.

  • Methods the mapping

    • The method name starting with get/find maps to HTTP GET

    • The method name starting with add/ INSERT/POST maps to HTTP POST

    • Update/put/ start method names are mapped to HTTP PUT

    • Methods that start with del/ delete/remove are mapped to HTTP delete

    • The default mapping is HTTP POST

The principle of

DynamicApi annotations inherit from the Service and RestController annotations

  • ServiceThe annotations automatically register the Service implementation class into the Spring container
  • RestControllerAnnotations will apply to access, matchingRequestResponseBodyMethodProcessorclass

Argument parsing

Normal Controller parameters require Requestbody or RequestParam annotations. Dynamic API to avoid these annotations, Defines the DynamicControllerHandlerMethodArgumentResolver argument parsing, this class inherits the RequestResponseBodyMethodProcessor, add DynamicApi support

@Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.getMethod().getName().startsWith("get")||
           parameter.getMethod().getName().startsWith("find")) {return super.supportsParameter(parameter); } Class<? > declaringClass = parameter.getMember().getDeclaringClass();if(declaringClass.getAnnotation(DynamicApi.class)! =null) {return true;
        }
        return super.supportsParameter(parameter);
    }
Copy the code

Registered Access address

Mainly use RequestMappingHandlerMapping registered address, the bean and method associated with path

    private void processer(DynamicApiControllerInfo controllerInfo){

        for (Map.Entry<String,DynamicApiMethodInfo> entry:
             controllerInfo.getMethodMap().entrySet()) {
            // Register the access address
            RequestMappingInfo.Builder mappingInfoBuilder =
                    RequestMappingInfo.paths(DynamicApiHelper.url("api/service",
                                    DynamicApiHelper.toCamelCase(controllerInfo.getBeanClassName()),
                            entry.getKey()))
                            .methods(DynamicApiHelper.getRequestMethod(entry.getKey()))
                            .options(this.config); requestMappingHandlerMapping.registerMapping( mappingInfoBuilder .build(), controllerInfo.getBeanName(), entry.getValue().getMethod()); }}Copy the code