Spring Boot基础功能: 路由

基于@RequestMapping注解的路由

package com.sniucom.controller

import org.springframework.stereotype.RequestController;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod

@RestController
@RequestMapping("/user")
public class UserController {
   @RequestMapping(value="/{id}", method=RequestMethod.GET)
   public String single(@PathVariable Long id) 
   {
      ...
   }

   @RequestMapping(method=RequestMethod.GET)
   public String lists()
   {
     ...
   }

   @RequestMapping(value="{id}", method=RequestMethod.DELETE)
   public String destory(@PathVariable Long id)
   {
     ....
   }
}

可用HTTP方法包含

  • RequestMethod.GET
  • RequestMethod.POST
  • RequestMethod.PUT
  • RequestMethod.PATCH
  • RequestMethod.DELETE
  • RequestMethod.HEAD
  • RequestMethod.TRACE

对Controller类使用注解@RequestMapping("/user"),可设置URL前缀

方法注解

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @PathMapping
  • @DeleteMapping
  • @HeadMapping
  • @TraceMapping

较为简单方便

接口路由的版本控制

对controller增加

@RequestMapping("/v2/user")

全局路径配置

server:
  servlet:
    context-path: /prefix

自定义注解实现前缀

先撞见一个自定义注解

package com.juhedao.nosocomium.application.common;

import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RestController
@RequestMapping
public @interface ApiRestController {
    /**
     * Alias for {@link RequestMapping#name}.
     */
    @AliasFor(annotation = RequestMapping.class)
    String name() default "";

    /**
     * Alias for {@link RequestMapping#value}.
     */
    @AliasFor(annotation = RequestMapping.class)
    String[] value() default {};

    /**
     * Alias for {@link RequestMapping#path}.
     */
    @AliasFor(annotation = RequestMapping.class)
    String[] path() default {};
}

添加一个配置

package com.juhedao.nosocomium.application.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.juhedao.nosocomium.application.common.ApiRestController;

@Configuration
public class ApiConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api", c -> c.isAnnotationPresent(ApiRestController.class));
                  //.addPathPrefix("/api/v2", c -> c.isAnnotationPresent(ApiV2RestController.class));
    }
}

使用

package com.juhedao.nosocomium.application.controller.api;

import com.juhedao.nosocomium.application.common.ApiRestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@ApiRestController(value={"/administrator"})
public class Administrator {
    @GetMapping("")
    public String index()
    {
        return "爱吃鱼的大脸猫";
    }

    @GetMapping("/{id}")
    public String show(@PathVariable Integer id)
    {
        return "采蘑菇的小姑娘";
    }
}

按照目录结构包名添加前缀

配置 application.yml

# 需要添加路径前缀的包名
api-package: com.example.demo.controller

AutoPrefixUrlMapping.java

package com.example.demo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * 自动补全路由前缀处理类
 */
public class AutoPrefixUrlMapping extends RequestMappingHandlerMapping {

    /**
     * 读取基础包配置
     */
    @Value("${api-package}")
    private String bathApiPackagePath;

    /**
     * 重写方法路由获取
     *
     * @param method
     * @param handlerType
     * @return
     */
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo mappingInfo = super.getMappingForMethod(method, handlerType);

        if (Objects.nonNull(mappingInfo)) {
            String prefix = this.getPrefix(handlerType);

            if (prefix != null) {
                String[] paths = mappingInfo.getPatternValues()
                        .stream()
                        .map(path -> prefix + path)
                        .toArray(String[]::new);

                return mappingInfo.mutate()
                        .paths(paths)
                        .build();
            }
        }

        return mappingInfo;
    }

    /**
     * 获取方法路由前缀
     *
     * @param handleType
     * @return
     */
    private String getPrefix(Class<?> handleType) {
        String packageName = handleType.getPackage().getName();

        // 如果包含指定的包则返回前缀
        if (packageName.startsWith(this.bathApiPackagePath)) {
            return packageName.substring(this.bathApiPackagePath.length())
                    .replace(".", "/");

        } else {
            return null;
        }
    }

}

控制器

package com.example.demo.controller.v1;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class IndexController {

    @GetMapping("/index")
    public String index() {
        return "Hello";
    }
}

发表回复

您的电子邮箱地址不会被公开。