文章目录
- 1 @Controller
- 2 @RequestMapping
- 2.1 介绍
- 2.2 demo
- 2.3 衍生注解
- 3 @RequestParam
- 3.1 介绍
- 3.2 demo
- 4 @InitBinder(不常用)
- 4.1 介绍
- 4.2 demo
- 4.3 补充一个注解:@DateTimeFormat
- 5 @ControllerAdvice注解
- 5.1 介绍
- 6 @RequestHeader和@CookieValue
- 6.1 介绍
- 6.2 示例
- 7 @ModelAttribute
- 7.1 介绍
- 7.2 测试
- 测试一:修饰在方法上
- 测试二:如何存取值
1 @Controller
此注解用用于修饰表现层控制器的注解,本质就是@Component 注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
// 用于指定存入IOC容器是Bean的唯一标识
@AliasFor(annotation = Component.class)
String value() default "";
}
2 @RequestMapping
2.1 介绍
- 作用:用于建立请求URL和处理请求方法之间的对应关系。
- 位置:类上和方法上
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
/***
name:给请求URL提供一个名称。
*/
String name() default "";
/**
value:用于指定请求的URL。它和path属性的作用是一样的。
*/
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
/**
method:用于指定请求的方式。它支持以下这些类型:
GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
*/
RequestMethod[] method() default {};
/**
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须和配置的一模一样。
*/
String[] params() default {};
/**
* headers:用于指定限制请求消息头的条件。
* eg:
* RequestMapping(value = "/something", headers = "content-type=text/*")
*/
String[] headers() default {};
/**
consumes:用于指定可以接收的请求正文类型(MIME类型)
eg:
consumes = "text/plain"
consumes = {"text/plain", "application/*"}
*/
String[] consumes() default {};
/**
produces:用于指定可以生成的响应正文类型。(MIME类型)
eg:
produces = "text/plain"
produces = {"text/plain", "application/*"}
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
*/
String[] produces() default {};
}
2.2 demo
- 搞一个controller
package study.wyy.spring.anno.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @author by wyaoyao
* @Description RequestMapping注解测试
* @Date 2021/2/14 12:56 下午
*/
// RequestMapping可以放在类上
@RequestMapping("requestMapping")
@Controller
public class RequestMappingTestController {
/****
* 对应的请求路径:requestMapping/test01
* 并且请求方式是get请求
* 比如带有name参数:requestMapping/test01?name
*
*/
@RequestMapping(path = "/test01",method = RequestMethod.GET,params = {"name"})
public String test01(){
return "success";
}
}
- 搞个页面发送请求测试
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>1 get请求:</h1>
<a href="${pageContext.request.contextPath}/requestMapping/test01">url:requestMapping/test01</a>
<br>
<!--携带了name参数-->
<a href="${pageContext.request.contextPath}/requestMapping/test01?name">url:requestMapping/test01?name</a>
<h1>2 post请求:</h1>
<form action="${pageContext.request.contextPath}/requestMapping/test01" method="post">
<input type="submit" value="post请求">
</form>
</body>
</html>
- 部署测试
第一个请求,没有携带name参数,直接400错误,Parameter conditions “name” not met for actual request parameters:
第二个请求,携带name参数,请求成功,返回到success页面
第三个请求,是个post请求,而我们限制了请求只能是get请求,405错误,Request method ‘POST’ not supported
2.3 衍生注解
对应不同的请求方式
- @GetMapping:指定为get请求
- @PostMapping:指定为post请求
- @PutMapping:指定为put请求
- @DeleteMapping:指定为delete请求
3 @RequestParam
3.1 介绍
- 作用:此注解是从请求正文中获取请求参数,给控制器方法形参赋值的。 当请求参数的名称和控制器方法形参变量名称一致时,无须使用此注解。 同时,当没有获取到请求参数时,此注解还可以给控制器方法形参提供默认值。
- 只能出现在形参上
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
/**
* Alias for {@link #name}.
*/
@AliasFor("name")
String value() default "";
/**
* The name of the request parameter to bind to.
* @since 4.2
*/
@AliasFor("value")
String name() default "";
/**
指定参数是否必须有值。当为true时,参数没有值会报错。
*/
boolean required() default true;
/**
在参数没有值时的默认值。
*/
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
3.2 demo
- 控制器
package study.wyy.spring.anno.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("requestParam")
@Controller
public class RequestParamTestController {
/**
1. 请求提交的参数名username,会被赋值到形参的name中
2. 形参age指定使用RequestParam注解,所以如果请求参数中带有age参数,就会被赋值到形参age中
3. 并且username参数是必须要带的,如果没有username参数,默认位置wyy
总而言之:RequestParam作用就是
1. 当请求参数和控制器中形参不一致时,可以使用该注解进行映射: name属性
2. 为请求参数设置默认值: defaultValue属性
3. 设置请求参数是否必须有值: required属性
*/
@RequestMapping(path = "/test01")
public String test01(@RequestParam(name = "username",defaultValue = "wyy",required = true) String name, Integer age) {
System.out.println("name: " + name + ";age: " + age);
return "success";
}
}
- 准备页面发送请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<span>没有携带任何参数</span><a href="${pageContext.request.contextPath}/requestParam/test01">url:requestParam/test01</a>
<br>
<span>携带了username和age参数</span><a href="${pageContext.request.contextPath}/requestParam/test01?username=韦德&age=18">url: requestParam/test01?username=韦德&age=18</a>
<br>
<span>携带了name和age参数</span><a href="${pageContext.request.contextPath}/requestParam/test01?name=韦德&age=18">url: requestParam/test01?name=韦德&age=18</a>
</body>
</html>
- 测试结果 name: wyy;age: 18
- 没有携带任何参数:
- name: wyy;age: null;
- name通过RequestParam注解指定了默认值是wyy,而age没有默认值所以是null
- 携带了username和age参数:
- name: 韦德;age: 18
- 携带了name和age参数
- name: wyy;age: 18
- 携带的是name参数,而非username参数,所以形参中依然使用的是默认值wyy
4 @InitBinder(不常用)
4.1 介绍
- 作用:用于初始化
表单请求参数
的数据绑定器,处理参数转换的
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InitBinder {
/**
指定给哪些参数进行绑定操作。
*/
String[] value() default {};
}
4.2 demo
- 准备controller
package study.wyy.spring.anno.web;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import study.wyy.spring.anno.model.User;
@Controller
@RequestMapping("initBinder")
public class InitBinderTestContoller {
@RequestMapping("/test01")
public String test01(User user){
System.out.println(user);
return "success";
}
//@InitBinder
//public void dateBinder(WebDataBinder dataBinder){
// dataBinder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
//}
}
- user,主要这里封装了一个Date类型的数据
@Data
@ToString
public class User implements Serializable {
private String username;
private Integer age;
private Date birthday;
}
- 页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/initBinder/test01" method="post">
<label>用户名:</label><input type="text" name="username">
<br>
<label>年龄:</label><input type="text" name="age">
<br>
<label>生日:</label><input type="text" name="birthday">
<br>
<input type="submit">
</form>
</body>
</html>
- 测试请求
- 发现会报400的错误,400是客户端错误,一般是由于请求参数格式有问题导致服务器无法处理当前请求
- 放开注释的代码,再次测试,请求正常,数据映射成功,控制台输出:
User(username=wyy, age=12, birthday=Sat Dec 12 00:00:00 CST 2020)
InitBinder注解用来处理参数类型转换的
4.3 补充一个注解:@DateTimeFormat
处理时间格式化的注解,使用该注解就不需要刚刚的这段代码了:
@InitBinder
public void dateBinder(WebDataBinder dataBinder){
dataBinder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
如何使用:要使用DateTimeFormat注解,需要开启springmvc注解驱动的(就是这个注解@EnableWebMvc
)
@Data
@ToString
public class User implements Serializable {
private String username;
private Integer age;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
}
5 @ControllerAdvice注解
5.1 介绍
用于给控制器提供一个增强的通知。 以保证可以在多个控制器之间实现增强共享。
它可以配合以下三个注解来用:
- @exceptionhandler
- @initbinder
- @modeltattribute
比如上面的InitBinder注解,写在某个controller,只对这个controller有效,不能在每个controller中加这么一个注解吧
这个时候就可以结合ControllerAdvice注解,为每一个controller增强这么一个数据绑定器:
@ControllerAdvice
public class DataFormatAdvice {
@InitBinder
public void dateBinder(WebDataBinder dataBinder){
dataBinder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
/**
用于指定对哪些包下的控制器进行增强
*/
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
/**
可以通过指定类的字节码的方式来指定增强作用范围。指定类所在的包下的controller
*/
Class<?>[] basePackageClasses() default {};
/**
用于指定特定的类型提供增强。
*/
Class<?>[] assignableTypes() default {};
/**
,用于指定给特定注解提供增强。
*/
Class<? extends Annotation>[] annotations() default {};
}
6 @RequestHeader和@CookieValue
6.1 介绍
RequestHeader: 此注解是从请求消息头中获取消息头的值,并把值赋给控制器方法形参。
CookieValue: 此注解是从请求消息头中获取Cookie的值,并把值赋给控制器方法形参。
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestHeader {
/**
* 用于指定请求消息头的名称。它和name属性作用一样
*/
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
/**
用于指定是否必须有此消息头。
*/
boolean required() default true;
/**
用于指定消息头的默认值。
*/
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CookieValue {
/**
*用于指定cookie的名称
*/
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
6.2 示例
@RequestMapping("test")
public String test(@RequestHeader("Accept-Language") String head, @CookieValue("JSESSIONID") String cookie){
System.out.println(head);
System.out.println(cookie);
return "success";
}
7 @ModelAttribute
7.1 介绍
它可以用于修饰方法,或者是参数。
- 当修饰方法时,表示执行控制器方法之前,被此注解修饰的方法都会执行。
- 当修饰参数时,用于获取指定的数据给参数赋值。。
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {
/**
* 当注解写在方法上,则表示存入时的名称。(值是方法的返回值)
* 当注解写在参数上,可以从ModelMap,Model,Map中的获取数据。(前提是之前存入过)
* 指定的是存入时的key。
*/
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
/**
用于指定是否支持数据绑定。它是4.3版本中新加入的属性。
*/
boolean binding() default true;
}
7.2 测试
测试一:修饰在方法上
package study.wyy.spring.anno.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("modelAttribute")
public class ModelAttributeController {
/****
* 修饰在方法上,会在当前控制器的方法执行前执行
* 可以对控制器进行一些前置处理
* @param name
*/
@ModelAttribute
public void modelAttribute(String name){
System.out.println("modelAttribute:" + name);
}
@RequestMapping("test01")
public String test01(String name){
System.out.println("controller: " + name);
return "success";
}
}
方法当前的url:modelAttribute/test01?name=wyy
发现modelAttribute方法先执行
modelAttribute:wyy
controller: wyy
测试二:如何存取值
方式一:
/****
* 修饰在方法上,会在当前控制器的方法执行前执行
* 可以对控制器进行一些前置处理
* @param name
*/
@ModelAttribute
public void modelAttribute(String name, Model model){
System.out.println("modelAttribute:" + name);
// 比如把name 给拼接上123
model.addAttribute("username",name + "123");
}
@RequestMapping("test01")
public String test01(String name, ModelMap model){
System.out.println("controller: " + name);
System.out.println("username:" + model.get("username"));
return "success";
}
modelAttribute:wyy
controller: wyy
username:wyy123
方式二:
/****
* 修饰在方法上,会在当前控制器的方法执行前执行
* 可以对控制器进行一些前置处理
* @param name
*/
// name属性或者value属性指定key
@ModelAttribute("username")
public String modelAttribute(String name, Model model){
System.out.println("modelAttribute:" + name);
// 通过返回值存数据
return name + "123";
}
@RequestMapping("test01")
public String test01(String name, @ModelAttribute("username") String username){
System.out.println("controller: " + name);
System.out.println("username:" + username);
return "success";
}
modelAttribute:wyy
controller: wyy
username:wyy123