听说你手写API前缀贼六

110 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

刚开发某一个模块功能时,总是为请求前缀烦恼,比方说课程模块,那么请求前缀为/course/、学期模块,那么请求前缀为/semester/,诸如此类的模块开发定义了超多的请求前缀,每当看到了其中一个请求入口类时,还有一种沾沾自喜的感觉,认为定义的还挺规范的,嗯,完美!

后边业务扩展了,从PC版本转战至App侧,对于以前的课程、学期等模块进行了复用,秉着单一职责的原则,为App侧重新定义了请求前缀/app/course/**,/app/semester/**等,行,完美!

再后来业务讲要做微信公众号了,emmm,这是不是又要重新定义一份?如果后边再加业务线呢?

按理来讲听油们都会经历如上的迭代操作,不知道你们后边有没有比较友好的解决API前缀问题,那下边我来重放下我的解决方式

目标

对于迭代的请求渠道,固定分配请求渠道访问前缀,如:App侧 ==>>

/app/,Pc侧 ==>>/admin/,小程序侧 ==>>/miniApp/**等

实现方式

通过idea创建常规Web项目,依赖引用如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>PrefixApiUri</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>PrefixApiUri</name>
    <description>PrefixApiUri</description>
    <properties>
        <java.version>18</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

\

包结构如下:

请求访问接口如下:

@RestController
@RequestMapping("/admin/course")
public class AdminCourseAction {


    @GetMapping("/?welCome")
    public String welCome(HttpServletRequest request) {
        return request.getRequestURI();
    }


}


@RestController
@RequestMapping("/app/course")
public class AppCourseAction {


    @GetMapping("/?welCome")
    public String welCome(HttpServletRequest request) {
        return request.getRequestURI();
    }


}


@RestController
@RequestMapping("/mini/app/course")
public class MiniAppCourseAction {


    @GetMapping("/?welCome")
    public String welCome(HttpServletRequest request) {
        return request.getRequestURI();
    }


}

访问接口路径如下:

小程序侧课程首页:http://localhost:8080/mini/app/course/awelCome

App侧课程首页:http://localhost:8080/app/course/awelCome

管理后台侧课程首页:http://localhost:8080/admin/course/awelCome

上边代码中可以看到,我是手写的/app、/mini/app等前缀,这种方式虽然也可以,但是会加大代码的监控难度,保不齐来个头铁开发,就搞一些幺蛾子;

再一个作为开发,我们也是熟读了一些模式的,稳定层变化层分离这也是其中之一啊,既然已经发现了一些前缀固定不变,为何不做分离的,让业务开发人员更加注焦呢;

下面看下统一前缀的方式



@Configuration
public class WebConfig implements WebMvcConfigurer {


    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/admin", clazz
                -> Objects.equals( clazz.getPackage().getName()
                , "com.example.prefixapiuri.admin"));
        configurer.addPathPrefix("/app", clazz
                -> Objects.equals( clazz.getPackage().getName()
                , "com.example.prefixapiuri.app"));
        configurer.addPathPrefix("/mini/app", clazz
                -> Objects.equals( clazz.getPackage().getName()
                , "com.example.prefixapiuri.mini.app"));
    }
}


@RestController
//@RequestMapping("/admin/course")
@RequestMapping("/course")
public class AdminCourseAction {


    @GetMapping("/welCome")
    public String welCome(HttpServletRequest request) {
        return request.getRequestURI();
    }


}


@RestController
//@RequestMapping("/app/course")
@RequestMapping("/course")
public class AppCourseAction {


    @GetMapping("/welCome")
    public String awelCome(HttpServletRequest request) {
        return request.getRequestURI();
    }


}


@RestController
//@RequestMapping("/mini/app/course")
@RequestMapping("/course")
public class MiniAppCourseAction {


    @GetMapping("/welCome")
    public String welCome(HttpServletRequest request) {
        return request.getRequestURI();
    }


}

主要增加了WebMvcConfigurer的实现方法,用来匹配符合条件的类需要增加前置访问前缀,这样我们就达到了业务人员无需重复定义请求路径的目的

实现原理

com.example.prefixapiuri.config.WebConfig#configurePathMatch会在Spring将类初始化前,进行访问路径的匹配并设置新的访问路径

结论

原理这一块并没有深入去讲,主要是将使用方式交代清楚,后续还要听油你自行琢磨使用场景!继续做抛砖引玉的好手,加油!

源码地址:github.com/a807966224/…