文章目录
- 一、Spring MVC 是什么
- 二、Spring MVC 具体使用
- 2.1 Spring MVC 创建
- 2.2 Spring MVC 连接
- 2.3 如何获取参数
- 2.3.1 通过 URL 传递参数
- 2.3.2 通过表单传递参数
- 2.3.3 传递对象
- 2.3.4 补充
- 后端参数的重命名
- 设置参数必传/非必传
- 2.3.5 接收 JSON 对象
- 2.3.6 获取 URL 中的参数
- 2.3.7 文件上传
- 2.3.8 获取 Cookie/Session/header
- 2.4 如何返回参数
- 2.4.1 返回静态页面
- 2.4.2 返回 text/html
- 实例:计算机加法实现
- 2.4.3 返回 JSON
- 实例:实现登录操作
- 2.4.4 请求转发/请求重定向
一、Spring MVC 是什么
Spring MVC 全称 “Spring Web MVC” 是一个基于 Servlet API
构建的原始 Web 框架
,从一开始就包含在 Spring 框架中
Web 框架
在之前学习 Servlet 的时候就已经接触到 Web 。所谓的 Web 框架,就是当用户输入一个 URL 地址后,将 URL 地址和程序进行映射,然后通过程序获取到用户的请求,经过请求的处理后,服务器发送的响应能够返回到客户端,将结果展示给用户
Servlet API
有关 Servlet API 的介绍文章
MVC 含义
MVC 是一种软件工程中的一种软件架构模式,将软件系统分成了模型、视图、控制器三部分
M(Model)
:指的是模型
,用于处理应用程序数据逻辑部分
V(View)
:指的是视图
,用于处理数据显示部分
C(Controller)
:指的是控制器
,用于处理用户交互的部分
解释
用户通过浏览器去访问程序的时候,请求会先到 Controller(控制层),控制层验证参数的合法性,如果没有问题的话,就会将请求转发给 Model(模型)进行业务的处理,然后将结果(业务数据)响应给控制层,然后控制层再将数据发送给 View(视图),视图最后做合并和整理工作,组装成了一个 HTML 页面,最后将页面响应给用户
总的来说,MVC 就是一种思想, Spring MVC 就是对 MVC 这一种思想的具体实现
二、Spring MVC 具体使用
2.1 Spring MVC 创建
Spring MVC 使用 Spring Boot 的方式创建的,创建 Spring Boot 项目过程中有勾选依赖这一环节,勾选的 Spring Web 框架
就是 Spring MVC 框架,将该依赖给勾选上了,其余的就是正常的创建 Spring Boot 项目的步骤
2.2 Spring MVC 连接
Spring MVC 连接即将用户和 Java 程序进行连接,用户通过一个地址就可以调用到 Spring 程序
@RequestMapping 注解
在 Spring MVC 中常常使用 @RequestMapping
注解实现路由映射
路由映射就是用户访问 URL 时,能够将用户的请求和程序中的某个类中的某个方法对应起来
@RestController@RequestMapping("/index")public class UserController {@RequestMapping("/hello")public String func() {return "Hello Spring MVC
";}}
解释
- 当启动项目后,访问地址 http://127.0.0.1:8080/index/hello 是就能获取到返回的内容 “Hello Spring MVC”
@RestController 注解是 @Controller 和 @ResponseBody 这两个注解的合体
。添加 @Controller 注解是为了项目启动后,该类放在了 Spring 容器中,被加载,方才能被访问到。添加 @RequestBody 注解是因为默认情况下回会返回一个静态页面,但是此时只是返回一个数据,因此需要添加- @RequestMapping 注解是可以修饰类,也可以修饰方法,一定要在方法上添加该注解,类上面不一定需要
- 默认情况下,@RequestMapping 接收
GET 方式
的请求,但是也可以接收POST 方式
的请求
显示指定方法
@RestController@RequestMapping("/index")public class UserController {@RequestMapping(value = "/hello",method = RequestMethod.POST)public String func() {return "Hello Spring MVC
";}}
通过 method 参数
内容就可以指定具体的接收方法,此时该方法只接收 POST 请求
@GetMapping 和 @PostMapping
除了在 @RequestMapping 注解中指定接收的方法之外,也可以直接使用 @GetMapping
和 @PostMapping
注解,前者使得方法只能接收 GET 请求,后者使得方法只能接收 POST 请求
2.3 如何获取参数
2.3.1 通过 URL 传递参数
例如URL:http://127.0.0.1:8080/index/getUser” />@RestController@RequestMapping(“/index”)public class UserController {@RequestMapping(“/getUser”)public String getUser(String userName,String passWord) {return “userName->”+ userName + ” | passWord->” + passWord;}}
结果显示
注意
2.3.2 通过表单传递参数
通过表单进行参数的传递方法也是和上面差不多的
代码同上面的代码展示,通过 PostMan 进行提交 form 表单,也需要注意参数的对应
结果展示
2.3.3 传递对象
在参数较少的情况下,会使用直接传参的方式,如果参数较多时,使用对象进行传参会更好
代码展示
@Datapublic class User {private String userName;private String passWord;}
@RestController@RequestMapping("/index")public class UserController {@RequestMapping("/getUser1")public String gerUser1(User user) {String name = user.getUserName();String word = user.getPassWord();return "对象中的userName:" + name + " | 对象中的passWord:" + word;}}
结果显示
代码参数是一个 User 对象,说明待会需要接收的就是一个对象,然后就会拿着这个对象中的所有属性,在请求中匹配参数
2.3.4 补充
后端参数的重命名
后端参数名未必一定要和前端参数名一模一样,可以通过 @RequestParam
注解来重命名前后端的参数值
@RequestMapping("/getUser")public String getUser(@RequestParam("userName") String name,String passWord) {return "userName->"+ name + " | passWord->" + passWord;}
前端的参数 key 是 userName 和 passWord ,后端的参数 key 是 name 和 passWord
设置参数必传/非必传
同样是上面的代码,如果参数中只传了 userName 参数会怎样,只传了 passWord 参数会怎样
结果显示
如果没有传递 passWord 参数,影响不大
如果没有传递 userName 参数,就会报 400 错误
原因就是 @RequestParam 中的 required 参数默认值为 true
,表示为必传参数
如果有参数需要使用 @RequestParam 注解且该参数是非必传参数,就需要将 required 参数值设置为 false
@RequestMapping("/getUser")public String getUser(@RequestParam(value = "userName",required = false) String name,String passWord) {return "userName->"+ name + " | passWord->" + passWord;}
2.3.5 接收 JSON 对象
使用 @RequestBody
来接收 JSON 对象
代码展示
@RestController@RequestMapping("/index")public class UserController {@RequestMapping("/loginByJson")public String loginByJson(@RequestBody User user) {return "userName:" + user.getUserName() + " | passWord:" + user.getPassWord();}}
结果显示
2.3.6 获取 URL 中的参数
一般来说,获取 URL 中的参数一般是指获取 query String 中的参数值,但还有一种特殊的,就是从 URL 的 PATH 中获取参数
需要通过 @PathVariable
注解
代码展示
@RestController@RequestMapping("/index")public class UserController {@RequestMapping("/loginByPath/{userName}/{passWord}")public String loginByPath(@PathVariable("userName") String name,@PathVariable String passWord) {return "userName:" + name + " |passWord:" + passWord;}}
注意
- 路径中的参数需要用花括号包裹
- @PathVariable 中传入参数也可以实现重命名
- 注意参数名的一一对应(不可少参数)
结果显示
2.3.7 文件上传
使用 @RequestPart
注解上传图片
代码展示
@RestController@RequestMapping("/index")public class UserController {@RequestMapping("/upLoad")public String upLoadFile(String userName, @RequestPart("picture")MultipartFile file) throws IOException {//获取文件后缀String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));//文件路径String filePath = System.getProperty("user.dir")+ "/src/main/resources/picture/" + UUID.randomUUID().toString();//拼接路径String finallyPath = filePath + suffix;file.transferTo(new File(finallyPath));return userName + "上传了一张图片";}}
注意
- RequestPart 注解里对应的是上传图片的参数名
- 通过 file.getOriginalFilename() 方法获取图片的完整名,然后通过查找最后一个 “.” ,来截取出后缀名
- System.getProperty(“user.dir”) 为获取当前工程目录
- 拼接完路径后,file.transferTo(new File(finallyPath)),创建文件实例并保存
- 为了生成独一无二的文件名,这里使用了 UUID
结果显示
2.3.8 获取 Cookie/Session/header
获取 Cookie
通过 @CookieValue
注解
@RequestMapping("/getCookie")public String getCookie(@CookieValue("newCookie") String value) {return "cookie:" + value;}
最一开始访问该方法时结果为 404 ,因为此时没有 key 为 newCookie 这样的 Cookie
通过浏览器端模拟该 Cookie 后,就可以获取到 Cookie 的值
获取 Header
通过 @RequestHeader
注解
@RequestMapping("/getHeader")public String getHeader(@RequestHeader("User-Agent") String content) {return "User-Agent:" + content;}
获取 Session
通过 @SessionAttribute
注解
按照以前的方法来创建 Session
@RequestMapping("/setSession")public String setSession(HttpServletRequest req) {HttpSession session = req.getSession(true);if(session != null) {session.setAttribute("userName","Spring MVC");}return "session 设置完成";}
获取 Session 对象中的 key 为 userName 的值
@RequestMapping("/getSession")public String getSession(@SessionAttribute(value = "userName",required = false) String userName) {return "userName:" + userName;}
2.4 如何返回参数
2.4.1 返回静态页面
默认请求下,Spring Boot 返回的是静态页面
代码展示
@Controller@RequestMapping("/index")public class UserController {@RequestMapping("/getView")public String getView() {return "/index.html";}}
index.html 中主要内容为
Hello Spring MVC~
2.4.2 返回 text/html
在之前的各种例子中都是返回 text/html 类型,当方法返回值为 String 时
,并且有加上 @ResponseBody
注解,返回的就是 text/html
类型
实例:计算机加法实现
前端代码展示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>计算机</title><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script></head><body><div><div>数字1:<input type="text" id="one"></div><div>数字2:<input type="text" id="two"></div><div><input type="button" value="提交" onclick="submit()"></div></div><script>function submit() {jQuery.ajax({url:"calc",method:"POST",data:{one:jQuery('#one').val(),two:jQuery('#two').val()},success:function(data) {alert(data);}});}</script></body></html>
后端代码展示
@RestControllerpublic class CalcController {@RequestMapping("/calc")public String calc(Integer one, Integer two) {if(one == null || two == null)return "不可为空";return String.format("%d 加上 %d 等于 %d",one,two,one+two);}}
结果显示
2.4.3 返回 JSON
通过 HashMap
返回数据或者返回一个对象
,返回的数据类型就是 JSON
代码展示(Map)
@RestController@RequestMapping("/index")public class UserController {@RequestMapping("/getUserByJson")public HashMap<String,String> getUserByJson(String userName,String passWord) {HashMap<String,String> map = new HashMap<>();map.put("userName",userName);map.put("passWord",passWord);return map;}}
结果显示(Map)
代码展示(对象)
@RestController@RequestMapping("/index")public class UserController { @RequestMapping("/getUserByJson1")public User getUserByJson1(String userName,String passWord) {User user = new User();user.setUserName(userName);user.setPassWord(passWord);return user;}}
结果显示(对象)
实例:实现登录操作
要求:
- 用户提交数据为 json 类型,返回结果为 json 类型
- 指定用户名为 “Json”,用户密码为 “123”为登录成功
前端代码展示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>用户登录</title><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script></head><body><div style="margin-left: 500px;margin-top:100px"><h1 style="padding-left: 120px;">登录</h1><div>用户姓名:<input type="text" id="userName"><p></p></div><div>用户密码:<input type="password" id="passWord"><p></p></div><div style="padding-left: 120px;"><input type="button" value="提交" onclick="mysubmit()" style="height: 30px; width: 80px;"></div></div><script>function mysubmit() {let userName = jQuery('#userName');let passWord = jQuery('#passWord');if(jQuery.trim(userName.val())=="") {alert("请填写用户名");userName.focus();return;}if(jQuery.trim(passWord.val())=="") {alert("请填写密码");passWord.focus();return;}jQuery.ajax({url:'login',method:'POST',contentType:'application/json',data:JSON.stringify({userName:userName.val(),passWord:passWord.val()}),success:function(result) {if(result!=null && result.succ==200) {if(result.message=="") {alert("恭喜登录成功");return;}else {alert(result.message);} }else {alert("未知错误");}}});}</script></body></html>
后端代码展示
@RestControllerpublic class LoginController {@RequestMapping("/login")public HashMap<String,Object> login(@RequestBody User user) {HashMap<String,Object> map = new HashMap<>();String message = "";//用户名和密码判断,不得为null或""if (StringUtils.hasLength(user.getUserName())&&StringUtils.hasLength(user.getPassWord())) {if (user.getUserName().equals("Json")&&user.getPassWord().equals("123")) {message = "";}else {message = "用户名或者密码有误,登录失败";}}else {message = "请将信息填写完整";}map.put("succ",200);map.put("message",message);return map;}}
结果展示
2.4.4 请求转发/请求重定向
forward(请求转发)
- 服务器进行转发;
- 请求转发地址不会发生变化;
- 请求转发由于是服务器转发的原来的外部资源可能访问不到
redirect(请求重定向)
- 请求重新定位到资源;
- 请求的地址发生变化;
- 请求重定向和直接访问新地址效果是一样的,原来的外部资源可以顺利访问到
代码展示
前端代码展示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="css/login.css"></head><body><h1>Hello Spring MVC~</h1></body></html>
CSS代码展示
h1 {color: red;}
后端代码展示
@Controllerpublic class UserController { //请求转发@RequestMapping("/forward")public String forward() {return "forward:/index.html";}//请求重定向@RequestMapping("/redirect")public String redirect() {return "redirect:/index.html";}}
结果显示
可以看出转发的 URL 是不变的,重定向的 URL 是会变的
如果在类上也添加路由映射会发现请求转发获取不到资源了
后端代码展示
@Controller@RequestMapping("/index")public class UserController { //请求转发@RequestMapping("/forward")public String forward() {return "forward:/index.html";}//请求重定向@RequestMapping("/redirect")public String redirect() {return "redirect:/index.html";}}
结果展示
此时转发的页面路径多了 index, 和资源没有在同一级目录下,导致资源获取的失败
完~~~