MVC 是 Model View Controller 的缩写,它是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。
二话不多说,直接老规矩先看一张图:
- Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
- View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
- Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
下面我们着手见一个Spring MVC项目,感受一下:
- 创建项目:
- 创建一个 UserController 类,实现用户到 Spring 程序的互联互通,具体实现代码如下:
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller// 让 spring 框架启动时,加载
@ResponseBody // 返回一个 text/html 信息
@RequestMapping("/user") // 路由器规则注册
public class UserController {
// 路由器规则注册
@RequestMapping("/hi")
public String sayHi() {
return "Hi,Spring MVC.
";
}
}
- 运行后,结果如下图(浏览器输入http://localhost:8080/user/hi)
嗯。。就是这么神奇,下面我们来看看细节:
@RequestMapping 是 Spring Web 应用程序中最常被用到的注解之一,它是用来注册接口的路由映射的。
嗯?你问我路由映射时什么?
路由映射:当用户访问一个 url 时,将用户的请求对应到程序中某个类的某个方法的过程。
给大家瞅一下源码:
我们可以看到内部有很多方法,那么。。。方法介绍如下图:
废话不多说直接上代码举个栗子:
其实前面已经看过了
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller// 让 spring 框架启动时,加载
@ResponseBody // 返回一个 text/html 信息
@RequestMapping("/user") // 路由器规则注册
public class UserController {
// 路由器规则注册
@RequestMapping("/hi")
public String sayHi() {
return "Hi,Spring MVC.
";
}
}
当然这玩意也不一定这些都要修饰,他也可以只修饰类或方法,当然只修饰类的话嗯。。。页面是不是就没用了。。。
==@RequestMapping 默认是两种方式的请求都可访问(post和get都可)==你问我怎么知道?嗯。。。我们测试一下,怎么测试?安利一款软件:ApiPost6(跟Postman差丘不多)
有什么办法只用一种呢?
很明显method,那怎么用呢,举个栗子:
我们给之前的代码改个参数如下图所示:
当然我们也可以直接使用 @GetMapping 和 @PostMapping
截止目前我们已经了解了创建和连接,那我们怎么获取参数呢:
直接看:
@RequestMapping("/m1")
public Object method_1(String name) {
System.out.println("参数 name:" + name);
return "/index.html";
}
看明白了,其实是直接获取方法中的参数
Spring MVC 可以自动实现参数对象的赋值,所以和传参数一样方法中就获取了
重要说明:当有多个参数时,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置是不影响后端获取参数的结果。
某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了一个 time给后端,而后端又是有 createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用@RequestParam 来重命名前后端的参数值。
举个:
@RequestMapping("/m4")
public Object method_2(@RequestParam("time") String createtime) {
System.out.println("时间:" + createtime);
return "/index.html";
}
回顾上一个,如果我们传入time参数会访问成功,如果没有传入呢?我们来观察一下:
很明显报了400错误。
嗯?为什么?我们来看看他的源码:
懂了吧,他的默认值是true,所以。。。
可是我们如果想让某个参数可以不传怎么办呢:
是的没错只需要加入required参数,之后我们再进行测试:
@RequestBody 可用来接收JSON对象,@PathVariable获取URL中参数,上传文件@RequestPart
@RequestMapping("/p4")
public String param10(HttpServletResponse response, HttpServletRequest request) {
String name = request.getParameter("name");
// 获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
return name + " 你好.";
}
@RequestMapping("/p5")
@ResponseBody
public String param5(HttpServletResponse response, HttpServletRequest request) {
String name = request.getParameter("name");
// 获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
String userAgent = request.getHeader("User-Agent");
return name + ":" + userAgent;
}
@RequestMapping("/cookie")
@ResponseBody
public String cookie(@CookieValue("bite") String bite) {
return "cookie:" + bite;
}
@RequestMapping("/header")
@ResponseBody
public String header(@RequestHeader("User-Agent") String userAgent) {
return "userAgent:" + userAgent;
}
Session 存储和 Servlet 类似,是使用 HttpServletRequest 中获取的,如下代码所示:
@RequestMapping("/setsess")
@ResponseBody
public String setsess(HttpServletRequest request) {
// 获取 HttpSession 对象,参数设置为 true 表示如果没有 session 对象就创建一个 session
HttpSession session = request.getSession(true);
if (session != null) {
session.setAttribute("username", "java");
}
return "session 存储成功";
}
读取 Session 可以使用 HttpServletRequest,如下代码所示:
@RequestMapping("/sess")
@ResponseBody
public String sess(HttpServletRequest request) {
// 如果 session 不存在,不会自动创建
HttpSession session = request.getSession(false);
String username = "暂无";
if (session != null && session.getAttribute("username") != null) {
username = (String) session.getAttribute("username");
}
return "username:" + username;
}
获取 Session 更简洁的方式:
@RequestMapping("/sess2")
@ResponseBody
public String sess2(@SessionAttribute(value = "username", required = false) String username) {
return "username:" + username;
}
转发vs重定向
forward 和 redirect 区别如下:
- 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
- 请求重定向地址发生变化,请求转发地址不发生变化。
- 请求重定向与直接访问新地址效果一直,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问
举个:
forward(请求转发)和 redirect(请求重定向)的区别,举例来说,例如,你告诉你妈妈,你想吃辣条,如果你妈妈,说好,我帮你去买,这就是 forward 请求转发;如果你妈妈让你自己去买,那么就是请求 redirect 重定向。
说明:
@ResponseBody 返回的值如果是字符会转换成 text/html,如果返回的是对象会转换成 application/json 返回给前端。
@ResponseBody 可以用来修饰方法或者是修饰类,修饰类表示类中的所有方法都会返回 html 或者json,而不是视图。
@RestController = @Controller + @ResponseBody