MVC
MVC:Model View Controller 的缩写,是一种软件架构模式,将软件系统分为模型、视图和控制器三个部分。
- Mode(模型):是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
- View(视图):是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
- Controller(控制器):是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据, 控制⽤户输⼊,并向模型发送数据。
MVC 是一种思想,而接下来的 Spring MVC 是对这种思想的具体实现。
Spring MVC
也叫做 Spring Web MVC,它是基于 Servlet API 构建的原始 Web 框架。
- Spring MVC 是一个 Web 框架;
- Spring MVC 是基于 Servlet API 构建的;
Spring MVC 项目该如何创建呢? 其实在前面已经介绍了 Spring Boot 项目的创建,而 Spring MVC 其实就包含在里面了,如下:
也就是说,Spring MVC 是创建 Spring Boot、Spring 项目的基础,换言之 Spring Boot 、Spring 项目是基于 Spring MVC 的。Spring Boot 是创建 Spring MVC 的一种方式。
Spring MVC 既然是 Web 框架 ,那么就可以使用它将 Java程序和浏览器连接起来,通过访问一个地址能够调用我们的项目,让我们可以见到一个可视化的页面。
Spring MVC 项目创建与连接
Spring MVC 项目与前面 Spring Boot 项目创建与连接方式相同,勾选上 Spring Web ,这样就是 Spring MVC 项目了。
鉴于方式相同,详解请转到前面的文章(Spring Boot 项目创建与连接详解),在此就不在赘述。
补充:
@RequestMapping 注解:是 Spring Web 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接口的路由映射的。
路由映射:当访问一个 URL 的时候,将用户的请求对应到程序中某个类或者某个方法的过程。简单来说,当用户通过URL 访问的时候 ,就会执行程序中对应的方法。例如如下程序:
@RestController
@RequestMapping("/test")
public class UserController {
@RequestMapping("/sayHi")
public String sayHi(){
return "[Spring Boot/MVC] 通过 URL 访问,执行对应方法!!!";
}
}
通过 URL 进行访问时:
- 对于 @RequestMapping 注解,它即可修饰类,也可修饰方法,修饰类和方法时,访问地址就是类+方法(如上述举例),单独修饰方法的话,访问地址就直接跟方法即可(也就是 http://localhost:8099/sayHi)。
- @RequestMapping 注解默认会接收 GET、POST、PUT、DELETE、HEAD、OPTIONS 等所有 HTTP 请求方法,若想指定 @RequestMapping 注解来接收别的请求可以参照下面这样做:
首先介绍接收 Get 请求的三种写法:
// 第一种
@RequestMapping("/sayHi") // 在类/方法前面这样写即可
// 第二种
@RequestMapping(value = "/sayHi",method = RequestMethod.GET) // 设置参数
// 第三种
@GetMapping("/sayHi")
接受 Post 请求的三种写法:
// 第一种
@RequestMapping(value = "/sayHi",method = RequestMethod.POST)
// 第二种
@PostMapping("/sayHi")
其余几种接收 HTTP 请求方法是类似的,如下:
获取参数
传递/获取单个参数
用户也可以通过 URL 来进行传参,从而在程序中执行。例如在 URL 中输入张三,使之在 Spring MVC 项目中显示出来。
创建一个 Service 类,实现需要传参的方法:
@Service
@ResponseBody
@RequestMapping("/getName")
public class GetService {
@RequestMapping("g")
public void setName(String name){
System.out.println("[Spring Boot/MVC] 从 URL 获取到的 name 为 " + name);
}
}
启动 Spring MVC 项目,使用 URL 进行传参:
此时,点击 Send,程序就会接收该 Get 请求,执行方法:
这样一来,就实现了用户传参与Spring MVC 项目获取/接收参数的“联动”。
传递/获取对象
用户也可以在 URL 中对对象进行传参,例如对 student 对象的 name、age等属性进行传参,Spring MVC 项目中可以自动对该对象的属性进行获取赋值。
创建 Student 对象,创建 Service 类,在类中实现获取对象的方法:
public class Student {
private String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Service
@ResponseBody
@RequestMapping("/stu")
public class StuService {
@RequestMapping("/get")
public void getNameAge(Student student){
System.out.println("name = " + student.getName());
System.out.println("age = " + student.getAge());
}
}
启动 Spring MVC 项目,在 URL 中传递参数(对象的属性):
此时程序中就会获取到传递的对象属性:
传递/获取多个非对象参数
当我们需要从 URL 中获取用户名、密码等多个内容时,就需要进行多个参数传递,方法如下:
@Service
@ResponseBody
@RequestMapping("/more")
public class TestService {
@RequestMapping("/pass")
public void getPassword(String userName,int password){ // 获取多个参数,而不是对象
System.out.println("userName = " + userName);
System.out.println("password = " + password);
}
}
发送后程序就会接收到并执行 getPassword 方法:
后端参数重命名(@RequestParam)
对于前端 URL 中传参的 key 值与后端的参数名不匹配,例如前端 URL中传递了一个 name = 张三,而后端用于接受参数的名字为 userName,这样以来就可以使用 @RequestParam 注解来重命名后端参数,将 userName 重命名为 name。具体操作如下:
代码实现:
@Service
@ResponseBody
@RequestMapping("/user")
public class UserService {
@RequestMapping("/reName")
public void reName(@RequestParam("name") String userName){ // 使用 @RequestParam 重命名后端参数(userName)
System.out.println("userName = " + userName);
}
}
若 URL 中用 userName 进行测试,就会出现问题:
若使用 name 进行测试,就不会出现问题:
这就说明了后端使用 @RequestParam 注解就要求前端必须传递一个 name 参数,否则会报错
。
对于一些业务,要求一些非必要的参数,例如买东西 app 需要上传资料,性别这一栏填不填都无所谓了,那么该怎么实现呢?
观察 @RequestParam 注解的源码其实就可以知道它还可以设置好多个参数,其中就有 required 这个参数:
更改上述代码,设置 name 为非必要传参:
@Service
@ResponseBody
@RequestMapping("/user")
public class UserService {
@RequestMapping("/reName")
public void reName(@RequestParam(value = "name" ,required = false) String userName){ // 使用 @RequestParam 重命名后端参数(userName)
System.out.println("userName = " + userName);
}
}
这样就不会出错了,使用 @RequestParam 注解设置 required 参数,就可以实现非必要传参。
使用 @RequestParam 注解还可以接收集合类
,例如前端 URL 中传递集合 List ,后端使用 @RequestParam 注解接收 List 集合;
代码实现:
@Service
@ResponseBody
@RequestMapping("/user")
public class UserService {
@RequestMapping("/list")
public String getList(@RequestParam("list")List<String> list){
if (list != null){
System.out.println(list.toString() + ",size:" + list.size());
return list.toString() + ",size:" + list.size();
}
System.out.println("list 为空");
return "list 为空";
}
}
使用 URL 传递 List:
若不使用 @RequestParam 注解重命名 List,那么就会报错:
所以当前端传递集合类的时候,必须使用 @RequestParam 注解进行重命名,Spring MVC 项目才能接收到,否则会报错
。
对于非集合类,如数组,就可以不设置 @RequestParam 注解来进行重命名,项目本身是能接收到的。
@RequestParam 注解小结:
- 使用 @RequestParam 注解可以重命名后端参数名称;
- 使用 @RequestParam 注解进行重命名时,默认必须传递对应参数的值,否则会报错,当设置 required 参数后就可以实现非必要传参;
- 当前端传递集合类时,例如 List 等,必须使用 @RequestParam 注解进行参数重命名来进行接收,否则会报错;
- 当前端传递非集合类时,例如数组等,可以不设置 @RequestParam 注解进行重命名,Spring MVC 本身就可以处理接收。
获取 JSON 对象(@RequestBody)
有些时候前端是以 JSON 格式进行传参的,Spring MVC 提供了 @RequestBody 注解用来接收获取 JSON 对象
代码实现:
@Service
@ResponseBody
@RequestMapping("/stu")
public class StuService {
@RequestMapping(value = "/getjson",method = RequestMethod.POST)
public void getJson(@RequestBody Student student){
System.out.println("student: " + student);
}
}
使用 JSON 类型进行传参:
结果如下:
若在代码中删掉 @RequestBody 注解,Spring MVC 项目就无法接收 JSON 等其它格式:
获取 URL 中参数(@PathVariable)
使用 @PathVariable 注解可以让我们直接从 URL 中输入张三,99,而不用像 name = 张三 & age = 99 这样写。代码实现如下:
@Service
@ResponseBody
@RequestMapping("/stu")
public class StuService {
@PostMapping("/re/{name}/{age}")
public void getUrl(@PathVariable String name, @PathVariable int age){
System.out.println("name = " + name + "; age = " + age);
}
}
使用 @PathVariable 注解可以让 Spring MVC 项目直接从 URL 中获取对应的属性
,不需要从前端输入 key = value & key = value… 这样的语句,直接输入属性的值即可。
观察 @PathVariable 注解源码还可以发现:
上传文件(@RequestPart)
当前端上传一个文件时,后端想要获取的时候,可以通过 @RequestPart 来进行获取,例如前端上传一个文件,由 Spring MVC 项目进行获取并将该文件转移到桌面的一个文件夹中;
@Service
@ResponseBody
@RequestMapping("/f")
public class FileService {
@RequestMapping("send")
public String sendFile(@RequestPart MultipartFile file) throws IOException { // 获取文件名字,将文件放到指定目录下(桌面)
String fileName = file.getOriginalFilename();
file.transferTo(new File("C:/Users/lenovo/Desktop/test/" + fileName)); // 将文件转移到桌面 test 文件中
return "获取上传的文件:" + file.getOriginalFilename(); // 获取文件名字
}
}
当点击上传文件时,这时文件就被程序转移了:
获取 Cookie/Session
获取 Cookie 一般有两种方式,一种是 Servlet 的方式,一种是 Spring MVC 的方式。
若对 Cookie 和 Session 不是很了解的,放一个传送门,可以去了解下。传送门
Servlet 方式
@Configuration
@ResponseBody
@RequestMapping("cookie")
public class CookieConfiguration {
@RequestMapping("/getCookie")
public String getCookie1(HttpServletRequest request){ // 传统方式获取 Cookie
Cookie[] cookies = request.getCookies(); // 获取 Cookie
if (cookies != null){
// 若 Cookie 不为空,将 Cookie 打印出来
for (Cookie cookie : cookies){
System.out.println(cookie.getName() + " : " + cookie.getValue());
}
return "获取 Cookie 成功!!!";
}
return "获取 Cookie 失败!!!";
}
}
当我们有 Cookie 的时候就可以打印出 Cookie 的值:
Cookie 也是可以删除和修改的,可以在如上控制里面将 Cookie 删除:
Spring MVC 注解方式(@CookieValue)
在项目中通过 @CookieValue 注解进行获取指定名称的 Cookie 值,且每次只能获取一个 Cookie 的值
。
@Configuration
@ResponseBody
@RequestMapping("cookie")
public class CookieConfiguration {
@RequestMapping("/getCookie2")
public String getCookie2(@CookieValue("test") String cookieValue){ // 通过注解方式获取 Cookie 的值一次只能获取一次,其中注解中填写的是本次想要获取 Cookie 的名字
return "获取到指定名 Cookie 的值:" + cookieValue;
}
}
上述代码指定本次获取名为 test 的 Cookie 的值,结果如下:
获取 Session 一般也有两种方式,同获取 Cookie 一样,一种是 Servlet 的方式,一种是 Spring MVC 的方式。
Servlet 方式
先设置一个 Session ,然后再对 Session 进行获取:
@Configuration
@ResponseBody
@RequestMapping("/session")
public class SessionConfiguration {
/*
* 先设置一个 Session,然后再获取这个 Session
* */
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute("userName","张三");
return "设置 Session 成功!!!";
}
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request){
HttpSession session = request.getSession();
String userName = (String) session.getAttribute("userName"); // 通过 Session 名来获取
return "获取到的登录用户为: " + userName;
}
}
获取 Session:
注解方式(@SessionAttribute)
@Configuration
@ResponseBody
@RequestMapping("/session")
public class SessionConfiguration {
/*
* 先设置一个 Session,然后再获取这个 Session
* */
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute("userName","张三");
return "设置 Session 成功!!!";
/*
* Spring Boot 注解方式
* */
@RequestMapping("/getSession2")
public String getSession2(@SessionAttribute("userName") String name){ // 通过设定 Session 名(注解里面写要获取值的名字)来获取值
return "获取到的登录用户为: " + name;
}
}
获取 Header
同样也是上述两种方式:
第一种:通过 Servlet 进行获取:
@Configuration
@ResponseBody
@RequestMapping("header")
public class HeaderConfiguration {
@RequestMapping("/getHeader")
public String getHeader(HttpServletRequest request){
String accept = request.getHeader("Accept");
return "Accept: " + accept;
}
}
这样以来就获取到了 header 中的 Accept :
第二种:通过 @RequestHeader 注解进行获取.
@Configuration
@ResponseBody
@RequestMapping("header")
public class HeaderConfiguration {
@RequestMapping("/getHeader2")
public String getHeader2(@RequestHeader("Accept") String accept){ //获取指定 Header 的值(注解括号里面为想要获取的对象)
return "Accept:" + accept;
}
}
对于 Spring MVC 的相关内容,本文介绍了如何创建,以及一些获取参数相关注解的基本用法,下文将继续介绍 Spring MVC 返回参数的一些用法,即如何使用 Spring Boot/MVC 项目将程序执行业务逻辑之后的结果返回给用户。