SpringBoot注解@GetMapping处理Get请求
一、如何从URL中获取参数
当你想从URL中获取名为courseId
的参数时,可以使用@GetMapping("/course/{courseId}")
和@GetMapping("/course")
两种办法,主要体现在URL模式和如何获取参数上。
使用
@GetMapping("/course/{courseId}")
:这种方式表示你正在定义一个REST风格的API,其中
{courseId}
是URL的一部分,通常被称为路径变量(path variable)。你可以通过在方法的参数中加上
@PathVariable
注解来获取这个路径变量。例如:language-java 1
2
3
4
5@GetMapping("/course/{courseId}")
public String getCourse(@PathVariable String courseId) {
// 使用courseId
}这种方式适合于当
courseId
是必需的,并且每个课程的URL都是唯一的情况。
使用
@GetMapping("/course")
:这种方式下,URL不直接包含
courseId
。相反,courseId
可以作为请求参数(query parameter)来传递。你可以通过在方法的参数中加上
@RequestParam
注解来获取这个请求参数。例如:language-java 1
2
3
4
5@GetMapping("/course")
public String getCourse(@RequestParam String courseId) {
// 使用courseId
}这种方式适合于当你想要让
courseId
作为一个可选参数或者你希望从一组标准的URL中筛选特定课程的情况。
二、获取多个参数
当URL中有多个参数时,@GetMapping("/course/{courseId}")
和@GetMapping("/course")
的使用方式和它们之间的区别仍然基于路径变量(Path Variable)和请求参数(Request Parameter)的概念。这两种方法可以根据参数的性质和用途灵活组合使用。
使用路径变量(Path Variables):
当你使用
@GetMapping("/course/{courseId}")
并且URL中有多个参数时,这些参数通常是URL路径的一部分,并且每个参数都是资源定位的关键部分。例如,如果你有一个URL像这样:
/course/{courseId}/module/{moduleId}
,你可以这样使用:language-java 1
2
3
4
5@GetMapping("/course/{courseId}/module/{moduleId}")
public String getModule(@PathVariable String courseId, @PathVariable String moduleId) {
// 使用courseId和moduleId
}在这个例子中,
courseId
和moduleId
都是路径的一部分,用来定位特定的资源。
使用请求参数(Request Parameters):
当你使用
@GetMapping("/course")
并且URL中有多个参数时,这些参数通常作为URL的查询字符串(query string)。例如,URL可能是这样的:
/course?courseId=123&moduleId=456
,你可以这样使用:language-java 1
2
3
4
5@GetMapping("/course")
public String getCourse(@RequestParam String courseId, @RequestParam String moduleId) {
// 使用courseId和moduleId
}在这个例子中,
courseId
和moduleId
是作为查询字符串的一部分传递的,通常用于过滤、排序或其他非资源定位的操作。
三、用一个类接收多个参数
对于URL中包含多个请求参数(如 /course?courseId=123&moduleId=456
),你可以使用一个Java类来接收所有这些参数。这种方法可以使代码更加整洁,尤其是当处理具有多个参数的复杂请求时。
这里是如何使用一个类来接收所有请求参数的示例:
定义一个类来表示请求参数 :
首先,你需要定义一个类,其属性对应于URL中的请求参数。例如,对于参数courseId
和moduleId
,你可以定义如下类:language-java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28public class CourseQuery {
private String courseId;
private String moduleId;
// 标准的getter和setter方法
public String getCourseId() {
return courseId;
}
public void setCourseId(String courseId) {
this.courseId = courseId;
}
public String getModuleId() {
return moduleId;
}
public void setModuleId(String moduleId) {
this.moduleId = moduleId;
}
// 可以添加构造函数、toString()等
}在控制器方法中使用这个类 :
接下来,在你的控制器方法中,你可以将这个类作为参数,并使用@ModelAttribute
注解(或者不使用任何注解,因为Spring MVC会自动将请求参数绑定到类的属性上):language-java 1
2
3
4
5@GetMapping("/course")
public String getCourse(@ModelAttribute CourseQuery query) {
// 使用query.getCourseId()和query.getModuleId()
}或者,如果你不使用
@ModelAttribute
注解,Spring MVC默认也会按照相同的方式处理这个参数:language-java 1
2
3
4
5@GetMapping("/course")
public String getCourse(CourseQuery query) {
// 使用query.getCourseId()和query.getModuleId()
}
使用这种方式,你可以轻松地处理包含许多参数的复杂请求,同时保持代码的清晰和可维护性。这也让你能够在需要时对参数进行验证,比如使用Spring的验证框架来确保传入的参数满足特定条件。
四、疑问
Q:定义一个类来表示请求参数时,不需要使用@RequestParam吗?还是说@RequestParam用于简单的类型获取单个参数,比如String?
在定义一个类来表示请求参数时,通常不需要在类的属性上使用@RequestParam
注解。当你使用一个类来接收请求参数,Spring MVC的数据绑定机制会自动将请求中的参数名称映射到类的属性上。这是基于类的属性名和请求参数名的匹配来完成的。
使用类接收参数:
当你有多个请求参数,并且想要将它们组织在一个类中时,你可以定义一个类,其属性与请求参数的名称相对应。
在控制器方法中,你可以使用这个类的实例作为参数,而无需为每个属性单独使用
@RequestParam
。Spring会自动处理参数到类属性的映射。例如:
language-java 1
2
3
4
5
6
7
8
9
10
11
12
13public class CourseQuery {
private String courseId;
private String moduleId;
// getter和setter省略
}
@GetMapping("/course")
public String getCourse(CourseQuery query) {
// 使用query.getCourseId()和query.getModuleId()
}
使用@RequestParam
:
@RequestParam
通常用于获取单个请求参数,特别是当这个参数是一个简单类型(如String
、int
等)时。当你只需要从请求中获取一个或少数几个参数,而不是一个复杂对象时,
@RequestParam
是一个很好的选择。例如:
language-java 1
2
3
4
5@GetMapping("/course")
public String getCourse(@RequestParam String courseId, @RequestParam String moduleId) {
// 直接使用courseId和moduleId
}
总结来说,当处理包含多个参数的复杂请求时,使用一个类来封装这些参数可以使代码更加清晰和易于维护。而@RequestParam
适用于处理更简单或直接的参数获取需求。在实际的应用中,你可以根据具体情况选择最适合的方法。
Q:假如我已经有一个在/course上的controller了,如下
@PostMapping("/course") public CourseBaseInfoDto createCourseBase(@RequestBody AddCourseDto dto)
我还能继续写@GetMapping("/course") public String getCourse(@RequestParam String courseId, @RequestParam String moduleId)
吗?
是的,你完全可以在同一个控制器(Controller)中同时定义一个@PostMapping
和一个@GetMapping
方法,即使它们都映射到了相同的路径(如/course
)。这是因为HTTP请求的方法类型(GET、POST等)作为映射的一部分,允许区分不同的操作。在你的例子中,一个方法用于处理POST请求,另一个用于处理GET请求。
@PostMapping("/course")
用于创建课程(通常是添加新资源),接收一个请求体(RequestBody)。@GetMapping("/course")
用于获取课程信息(通常是读取资源),接收URL中的请求参数(RequestParam)。
你的控制器可能看起来像这样:
1 | @RestController |
在这种配置中,当一个POST请求发送到/course
时,createCourseBase
方法将被调用;而当一个GET请求发送到/course
时,带有请求参数的getCourse
方法将被调用。
这种方法是RESTful API设计中的常见实践,它允许你在同一路径上对资源进行不同类型的操作,同时保持了代码的清晰和逻辑的分离。