@RequestMapping注解的作用就是将请求的 URL 地址和处理请求的方式(handler方法)关联起来,建立映射关系。
SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的方法来处理这个请求。
@Controller
public class UserController {
/**
* 精准设置访问地址 /user/login
*/
@RequestMapping(value = {"/user/login"})
@ResponseBody
public String login(){
System.out.println("UserController.login");
return "login success!!";
}
在@RequestMapping注解指定 URL 地址时,通过使用通配符,匹配多个类似的地址。
@Controller
public class ProductController {
/**
* 路径设置为 /product/*
* /* 为单层任意字符串 /product/a /product/aaa 可以访问此handler
* /product/a/a 不可以
* 路径设置为 /product/**
* /** 为任意层任意字符串 /product/a /product/aaa 可以访问此handler
* /product/a/a 也可以访问, /product/a/a/a还可以访问
*
* 将来的配置拦截器也遵循这个规则
*/
@RequestMapping("/product/*")
@ResponseBody
public String show(){
System.out.println("ProductController.show");
return "product show!";
}
}
@RequestMapping
注解可以设置在控制器类上,用于映射整个控制器的通用请求路径。这样,如果控制器中的多个方法都需要映射同一请求路径,就不需要在每个方法上都添加映射路径。@RequestMapping
注解也可以单独设置在控制器方法上,用于更细粒度地映射请求路径和处理方法。当多个方法处理同一个路径的不同操作时,可以使用方法级别的 @RequestMapping
注解进行更精细的映射。//1.标记到handler方法
@Controller
public class UserController {
@RequestMapping(value = {"/user/login"})
@ResponseBody
public String login(){
System.out.println("UserController.login");
return "login success!!";
}
@RequestMapping(value = {"/user/register"})
@ResponseBody
public String register(){
System.out.println("UserController.register");
return "register success!!";
}
}
//2.优化标记类+handler方法
//类上定位到/user
@RequestMapping("/user")
@Controller
public class UserController {
//handler方法上再进一步指明
@RequestMapping(value = {"/login"})
@ResponseBody
public String login(){
System.out.println("UserController.login");
return "login success!!";
}
@RequestMapping(value = {"/register"})
@ResponseBody
public String register(){
System.out.println("UserController.register");
return "register success!!";
}
}
HTTP 协议定义了八种请求方式,在 SpringMVC 中封装到了下面这个枚举类:
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
@Controller
public class UserController {
/**
* 精准设置访问地址 /user/login
* method = RequestMethod.POST 可以指定单个或者多个请求方式!
* 注意:违背请求方式会出现405异常!
*/
@RequestMapping(value = {"/user/login"} , method = RequestMethod.POST)
@ResponseBody
public String login(){
System.out.println("UserController.login");
return "login success!!";
}
/**
* 指定多种请求方式
*/
@RequestMapping(value = {"/user/register"},method = {RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public String register(){
System.out.println("UserController.register");
return "register success!!";
}
}
@RequestMapping
的 HTTP 方法特定快捷方式变体:
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
注意:进阶注解只能添加到handler方法上,无法添加到类上!
@RequestMapping(value="/login",method=RequestMethod.GET)
||
@GetMapping(value="/login")
出现原因:多个 handler 方法映射了同一个地址,导致 SpringMVC 在接收到这个地址的请求时该找哪个 handler 方法处理。
There is already ‘demo03MappingMethodHandler’ bean method com.atguigu.mvc.handler.Demo03MappingMethodHandler#empGet() mapped.
在 HTTP 请求中,我们可以选择不同的参数类型,如 param 类型和 JSON 类型。下面对这两种参数类型进行区别和对比:
参数编码:
param 类型的参数会被编码为 ASCII 码。例如,假设 name=john doe
,则会被编码为 name=john%20doe
。而 JSON 类型的参数会被编码为 UTF-8。
参数顺序:
param 类型的参数没有顺序限制。但是,JSON 类型的参数是有序的。JSON 采用键值对的形式进行传递,其中键值对是有序排列的。
数据类型:
param 类型的参数仅支持字符串类型、数值类型和布尔类型等简单数据类型。而 JSON 类型的参数则支持更复杂的数据类型,如数组、对象等。
嵌套性:
param 类型的参数不支持嵌套。但是,JSON 类型的参数支持嵌套,可以传递更为复杂的数据结构。
可读性:
param 类型的参数格式比 JSON 类型的参数更加简单、易读。但是,JSON 格式在传递嵌套数据结构时更加清晰易懂。
总的来说,param 类型的参数适用于单一的数据传递,而 JSON 类型的参数则更适用于更复杂的数据结构传递。根据具体的业务需求,需要选择合适的参数类型。在实际开发中,常见的做法是:在 GET 请求中采用 param 类型的参数,而在 POST 请求中采用 JSON 类型的参数传递。
@Controller
@RequestMapping("param")
public class ParamController {
/**
* 前端请求链接 : localhost:8080/param/value?name=你好age=18
* 利用形参列表,直接接收前端传递的param参数!
* 要求: 参数名 = 形参名
*
* 类型相同
* 出现乱码正常,json接收具体解决!!
* @return 返回前端数据
*/
@GetMapping(value="/value")
@ResponseBody
public String setupForm(String name,int age){
System.out.println("name = " + name + ", age = " + age);
return name + age;
}
}
直接传值有一个显然的缺点 , 形参和传递参数并不一定同名也一一对应(例如用户干脆就不填age)
@RequestParam
使用场景:
/**
* 前端请求: http://localhost:8080/param/data?name=xx&stuAge=18
*
* 使用@RequestParam注解标记handler方法的形参
* 指定形参对应的请求参数@RequestParam(请求参数名称)
*/
@GetMapping(value="/data")
@ResponseBody
//通过@RequestPararm注解,指定传递参数name赋给形参name ,
// 指定stuAge传给age , 且修改为不必须传递 , 设定默认值18
public Object paramForm(@RequestParam(value = "name") String name,
@RequestParam(value = "stuAge",required = false,defaultValue = "18") int age){
System.out.println("name = " + name + ", age = " + age);
//
return name+age;
}
默认情况下,使用@RequestPararm注解的方法参数是必需的,但可以通过将 @RequestParam
注解的 required
标志设置为 false
!
a. 一名多值
需求 : 多选框,提交的数据的时候一个key对应多个值,我们可以使用集合进行接收!
/**
* 前端请求: http://localhost:8080/param/mul?hbs=吃&hbs=喝
* 一名多值,可以使用集合接收即可!但是需要使用@RequestParam注解指定
*/
@GetMapping(value="/mul")
@ResponseBody
public Object mulForm(@RequestParam List<String> hbs){
System.out.println("hbs = " + hbs);
return hbs;
}
b. 实体接收
优点 : 可以在方法内部直接使用对象的属性来访问请求参数,而不需要每个参数都写一遍。
缺点 : 由于是通过对象传值 , 无法采用@RequestParam绑定形参和传递参数 , 因此二者的属性名必须要相同 . 即User类内部定义的是name和age,那么传递参数的名也必须是name和age.
定义一个用于接收参数的实体类:
public class User {
private String name;
private int age = 18;
// getter 和 setter 略
}
在控制器中,使用实体对象接收,示例代码如下:
@Controller
@RequestMapping("param")
public class ParamController {
@POSTMapping(value = "/user")
@ResponseBody
public String addUser(User user) {
// 在这里可以使用 user 对象的属性来接收请求参数
System.out.println("user = " + user);
return "success";
}
}
在上述代码中,将请求参数name和age映射到实体类属性上!要求属性名必须等于参数名!否则无法映射!
使用postman传递参数测试:
public class Person {
private String name;
private int age;
private String gender;
// getter 和 setter 略
}
{
"name": "张三",
"age": 18,
"gender": "男"
}
@PostMapping("/person")
@ResponseBody
public String addPerson(@RequestBody Person person) {
// 在这里可以使用 person 对象来操作 JSON 数据中包含的属性
return "success";
}
Java原生只支持param传参和路径传参 , json是前端定义的格式 .因此需要做两件事.
a. 导入json依赖
b.handlerAdapter配置json转化器(即在config类上增加@EnableWebMvc)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
此时运行程序 , 可以接收到传来的json。
插播一条@EnableWebMvc注解:
原本,MvcConfig类中,我们需要重写handlerMapping,handlerAdapter两个方法,上例中又加入了一个新需求即配置一个json转化器。然而这一切只需要MvcConfig上声明一个@EnableWebMvc注解即可实现。
先理解是什么:
http://localhost:8080/user/login?account=root&password=12345
||
http://localhost:8080/user/root/12345
即将每个参数视为路径 , 这就是路径传参
@PathVariable
注解来处理路径传递参数 , 该注解允许将 URL 中的占位符映射到控制器方法中的参数。例如,如果我们想将 /user/{id}
路径下的 {id}
映射到控制器方法的一个参数中,则可以使用 @PathVariable
注解来实现。
/**
* 动态路径设计: /user/{动态部分}/{动态部分} 动态部分使用{}包含即可! {}内部动态标识!
* 形参列表取值: @PathVariable Long id 如果形参名 = {动态标识} 自动赋值!
* @PathVariable("动态标识") Long id 如果形参名 != {动态标识} 可以通过指定动态标识赋值!
* 和RequestParama一样 , 通过value属性绑定两个属性(@PathVariable(value="stuAge") int age)
*/
//动态路径设计, 可在形参列表获取传入的参数
@GetMapping("/user/{id}/{name}")
@ResponseBody
//形参列表获取参数, 分别传入上头的GetMapping和下面的方法
public String getUser(@PathVariable Long id,
@PathVariable("name") String uname) {
System.out.println("id = " + id + ", uname = " + uname);
return "user_detail";
}
//访问测试: /param/user/1/root 可得结果: id = 1 uname = root