携手创作,共同成长!这是我参与「掘金日新计划 · 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将类初始化前,进行访问路径的匹配并设置新的访问路径
结论
原理这一块并没有深入去讲,主要是将使用方式交代清楚,后续还要听油你自行琢磨使用场景!继续做抛砖引玉的好手,加油!