在Spring MVC 中,@RequestMapping
注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。
@RequestMapping 既可修饰类,也可以修饰方法。当修饰类时,可以使该类下的方法有统一的 URL 前缀。
浅看一下源码:
// Target 中这两个属性表示 @RequestMapping 注解可以用在方法和类上
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
String[] value() default {};
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
@RequestMapping注解中除了 name()
返回的字符串外,有七个属性。
属性名 | 属性说明 |
---|---|
value、path | 指定请求的url地址。value和path的作用相同,可以互相替换。value是默认属性,所以@RequestMapping(value=“/example”)和@RequestMapping(“/example”)是等价的。 |
method | 指定请求的method类型, GET(查)、POST(增)、PUT(改)、DELETE(删)等 |
params | 指定request中必须包含某些参数值是,才让该方法处理。 |
headers | 指定request中必须包含某些指定的header值,才能让该方法处理请求。 |
consumes | 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html; |
produces | 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回; |
回到目录…
value属性通过请求的请求地址匹配请求映射。valuel属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求,value属性必须设置。
@Controller // 必须用 Controller 注解
public class Demo1 {
// 路由规则注册:访问页面的地址
@RequestMapping("/test1")
public String sayTest1() {
// 跳转到 templates 下的 demo2.html
return "demo2";
}
}
// 访问地址: http://localhost:8080/test1
回到目录…
@ResponseBody
返回的值如果是字符会转换成 text/html
,如果返回的是对象会转换成application/json
返回给前端。
@ResponseBody
可以用来修饰方法或者修饰类,修饰类表示类中的所有方法都会返回 html
或者json
,而不是视图。
@Controller // 必须用 Controller 注解
@ResponseBody // 返回一个非视图文件
public class Demo2 {
@RequestMapping("/test2")
public String sayTest2() {
// 返回 HTML 文本
return "hello,this is Test
";
}
// URL: 127.0.0.1:8080/test2
@RequestMapping("/test3")
public String sayTest3() {
// 返回 JSON 数据
return new Cat("小猫", 3);
}
// URL: 127.0.0.1:8080/test3
}
回到目录…
1.首先你得创建一个数据实体类
import lombok.Data;
// @Data注解在lombok下,可以节省代码空间
// 有了@Data注解,我们就不需要手动写get、set、toString和构造方法了,它内置这些方法
@Data
public class Student {
private final String name;
private final String brief;
private final String birthday;
}
2.创建一个动态模板文件(view.html
),内部自定义数据对象
DOCTYPE html>
<html lang="zh-hans">
<head>
<meta charset="UTF-8">
<title>仅仅是一个视图文件 | 实际上是一个模板文件title>
head>
<body>
<h1 th:text="${person.name}">这里的内容会被替换h1>
<p th:text="${person.brief}">这里的内容会被替换p>
<p th:text="${person.birthday}">这里的内容会被替换p>
body>
html>
3.经过Controller进行Model数据渲染
@Controller
public class DemoController {
// 支持所有的 HTTP 方法,@RequestMapping 默认是 get方式的请求
@RequestMapping("/hello")
public String hello(Model model) {
Student student = new Student("张三", "我是张三,很高兴认识大家", "2000-07-26");
//往前台传数据,可以传对象,通过表达式 ${}可以获取到
model.addAttribute("person", student);
return "view";
}
}
// 访问地址: http://localhost:8080/hello
回到目录…
@RequestMapping
中的 method 用来定义接收浏览器发来的请求,@RequestMapping 默认支持所有HTTP请求方法。
Http规范定义了多种请求资源的方式,最基本的有四种,分别为:GET(查)、POST(增)、PUT(改)、DELETE(删),而URL则用于定位网络上的资源相当于地址的作用,配合四种请求方式,可以实现对URL对应的资源的增删改查操作。
@Controller
public class UserController1 {
// 只支持 GET 方法
@RequestMapping(value = "/login1", method=RequestMethod.GET)
public String login1() {
return "success";
}
// 可简写为
@GetMapping("/login2")
public String login2() {
return "success";
}
}
// 访问地址: http://localhost:8080/login1
这时,如果浏览器发来的请求不是GET的话,将收到浏览器返回的405错误提示,也就是得通过链接的方式。
@Controller
public class UserController2 {
// 只支持 POST 方法
@PostMapping("/login3")
public String login3() {
return "success";
}
}
这时,必须通过表单的方式发送请求,否则将收到浏览器返回的405错误提示。
<form action="user/login" method="post">
<input type="submit" value="使用Post发送请求"/>
form>
@Controller
public class UserController3 {
// 支持 HTTP GET 和 POST 方法
@RequestMapping(value = "/login4", method = {RequestMethod.GET, RequestMethod.POST})
public String login4() {
return "success";
}
}
回到目录…
params 属性表示请求参数,也就是追加在URL上的键值对(queryString
),多个请求参数以&隔开。
设置请求参数使用 @RequestParam
注解,也可以省略不写。
定义实体类:
@Data
public class Cat {
public final String name;
public final int age;
}
不设置请求参数的情况:
@Controller
public class ParamsController {
@GetMapping("/cat1")
@ResponseBody // 用来返回JSON数据
public Cat createCat() {
// 返回对象会被 JSON 序列后输出
return new Cat("小猫", 3);
}
}
// 访问地址: http://localhost:8080/cat1
// 网页结果:{"name":"小猫","age":3}
回到目录…
以下是省略 @RequestParam
的写法:省略条件是 queryString中的请求参数名 === 方法中的形参
,一般情况下都满足条件。
@Controller
public class ParamsController {
@GetMapping("/cat2")
@ResponseBody
public Cat createCat2(String name, Integer age) {
return new Cat(name, age);
}
// 127.0.0.1:8080/cat2?name=李白&age=6
// URL必须加 queryString, 属性值任意
@GetMapping(value = "cat3", params={"name=小米","age=4"})
@ResponseBody
public Cat createCat3(String name, Integer age) {
return new Cat(name, age);
}
// 127.0.0.1:8080/cat3?name=小米&age=4
// URL必须加 queryString, 且属性值必须和 params 中一致
}
不省略就这么写, @RequestParam
还可以设置默认值。
@Controller
public class ParamsController {
@GetMapping("/cat4")
@ResponseBody
public Cat createCat4(@RequestParam(value = "name", defaultValue = "小黑") String name,
@RequestParam(value = "age", defaultValue = "20") int age) {
return new Cat(name, age);
}
}
// 127.0.0.1:8080/cat4
// 网页结果: {"name":"小黑","age":20}
// 127.0.0.1:8080/cat4?name=小白&age=18
// 网页结果: {"name":"小白","age":18}
回到目录…
@Controller
public class ParamsController {
@GetMapping("/cat5")
@ResponseBody
public Cat createCat5(Cat cat) {
// 可以直接用对象请求。只要能正确传参,Spring内部会构造对象
return cat;
}
}
// 键入地址: http://127.0.0.1:8080/cat5?name=一诺&age=20
// 网页结果: {"name":"一诺","age":20}
回到目录…
send-json.html 前端发送POST请求,携带请求体中是JSON数据:
<!DOCTYPE html>
<html lang="zh-hans">
<head>
<meta charset="UTF-8">
<title>通过 ajax + JSON 格式的请求体发送数据</title>
</head>
<body>
<button>点一次,发送一次请求</button>
<script>
document.querySelector('button').onclick = send
function send() {
var person = {
pid: 1993,
name: '葫芦娃',
gender: '男'
}
var personJsonText = JSON.stringify(person)
var xhr = new XMLHttpRequest();
xhr.open('post', '/send-json')
xhr.onload = function() {
alert('响应状态: ' + this.status)
alert('响应正文: ' + this.responseText)
}
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(personJsonText)
}
</script>
</body>
</html>
后端获取请求数据:
@Controller
public class TestController {
// 前端请求的要求:
// 1. 有请求体,肯定是 POST 请求
// 2. 请求体格式是 JSON 格式
@PostMapping("/send-json")
@ResponseBody // 不写 @ResponseBody 的话,Spring 尝试去找 "成功" view,由于找不到会404
public String getPerson(@RequestBody Person person) {
log.info("请求体中的参数: " + person);
return "成功";
}
}
// 在浏览器访问 127.0.0.1:8080/send-json.html , 控制发送POST请求
// 在控制台可以看到后端接收到的JSON数据
回到目录…
PathVariable:路径变量。目前这种URL的设计是主流的,类似于CSDN中文章的URL。
固定格式:https://blog.csdn.net/作者用户名
/article/details/文章ID号
我的文章:https://blog.csdn.net/qq15035899256/article/details/126555706
@Controller
public class TestController {
@GetMapping("/{username}/article/details/{aid}")
@ResponseBody
public String articleDetails(@PathVariable("username") String name, @PathVariable("aid") String aid) {
log.info("username = {}, aid = {}", name, aid);
return "关于从数据库中找到的文章的详情";
}
}
// URL: 127.0.0.1:8080/zhangsan/article/details/123
回到目录…
upload.html 前端上传文件:
DOCTYPE html>
<html lang="zh-hans">
<head>
<meta charset="UTF-8">
<title>上传文件title>
head>
<body>
<form method="post" action="/upload" enctype="multipart/form-data">
文件名:<input type="text" name="name">
文件类型:<input type="text" name="type">
<input type="file" name="some-file">
<button>提交button>
form>
body>
html>
后端获取文件信息:
@Controller
public class TestController {
@PostMapping("/upload")
@ResponseBody
public String upload(String name, String type, @RequestPart("some-file") MultipartFile file) throws IOException {
log.info("name = {}, type = {}", name, type);
log.info("some-file 的信息: name = {}, 原始文件名= {}, content-Type = {}, size = {}", file.getName(), file.getOriginalFilename(), file.getContentType(), file.getSize());
// 获取文件后缀名
String fileName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
// 文件保存地址: target下的static包下 + 随机文件名.源文件后缀
String filePath = ClassUtils.getDefaultClassLoader().getResource("static").getPath() + "/" + UUID.randomUUID() + fileName;
// 由于路径中的 空格 被替换成 %20 了,所以我们需要换回去
String filePathTrue = filePath.replaceAll("%20", " ");
log.info(filePathTrue);
// 保存文件
file.transferTo(new File(filePathTrue));
return filePath + " 上传成功.";
}
}
回到目录…
传统获取 cookie
@Controller
public class CookieController {
@RequestMapping("/cookie1")
@ResponseBody
public String cookie1(HttpServletRequest request) {
String name = request.getParameter("name");
// 获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
return "成功";
}
}
简洁的获取 Cookie—@CookieValue
@Controller
public class CookieController {
@RequestMapping("/cookie2")
@ResponseBody
public String cookie2(@CookieValue("bite") String bite) {
return "cookie:" + bite;
}
}
回到目录…
Session 存储和获取
@Controller
@ResponseBody
public class SessionController {
@RequestMapping("/session1")
public String session1(HttpServletRequest request) {
// 获取 HttpSession 对象,参数设置为 true 表示如果没有 session 对象就创建一个 session
User user = new User("zhangsan", "123456");
HttpSession session = request.getSession(true);
session.setAttribute("currentUser", user);
return "session 会话成功";
}
@RequestMapping("/session2")
public String session2(HttpServletRequest request) {
// 如果 session 不存在,不会自动创建
HttpSession session = request.getSession(false);
User user = null;
if(session != null && session.getAttribute("currentUser") != null){
user = (User) session.getAttribute("currentUser");
}
return user;
}
}
获取 Session 更简洁的方式: @SessionAttribute
@Controller
public class SessionController {
@RequestMapping("/session3")
@ResponseBody
public String session3(@SessionAttribute(value = "currentUser",required = false) User currentUser) {
return "user: " + currentUser;
}
}
回到目录…
通过 @RequestMapping 中的 headers 属性,可以限制客户端发来的请求
@Controller
public class HeadersController {
// 表示只接收本机发来的请求
@RequestMapping(path = "/login", headers="Host=localhost:8080")
public String login() {
return "success";
}
}
回到目录…
produces属性指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。
public class DemoController {
// 指定输出格式为text,字库为utf-8; 也就是响应头中的 Content-Type
@RequestMapping(value = "/sayhello", produces = "text/plain; charset=utf-8")
@ResponseBody
public String sayHello(String target) {
return "你好, " + target;
}
}
// 键入地址: http://localhost:8080/sayhello
// 输出结果: 你好,null
// 键入地址: http://localhost:8080/sayhello?target=小米
// 输出结果: 你好,小米
回到目录…
开始学习Spring已经有一周了,给我的感觉就是起步比较难。框架这种东西你不需要知道原理就可以使用,这对于开发来说确实省事儿了不少。但是对于初学者来说,确实有不小的难度,因为这里面的东西太多了,如果没有时间的积累,你很难在短期内认识那么多的工具,更别说搞懂原理了。
不过也会正常,“万事开头难”。我们能做的只有慢慢努力了。这篇文章仅仅是初学的总结,后续还需要不断的补充和改进!!!
回到目录…
总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是SpringMVC的学习,又认识了一个注解@RequestMapping,并且学习了它的各种用法。之后的学习内容将持续更新!!!