目录
1.什么是 Spring MVC?
1.Spring MVC 是一个 Web 框架。
2. Spring MVC 是基于 Servlet API 构建的。
Spring MVC是基于MVC设计模式并在Servlet API基础上实现的一个Web框架。
1.1 MVC 定义
MVC 是 Model View Controller 的缩写,它是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分
- Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
- View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
- Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
1.2 MVC 和 Spring MVC 的关系
MVC 是一种思想, Spring MVC 是对 MVC 思想的具体实现。
总结来说,Spring MVC 是一个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。既然是 Web 框架,那么当用户在浏览器中输入了 url 之后,我们的 Spring MVC 项目就可以感知到用户的请求。
2.为什么要学 Spring MVC?
现在绝大部分的 Java 项目都是基于 Spring(或 Spring Boot)的, Spring 的核心就是 Spring MVC。
3.怎么学 Spring MVC?
学习 Spring MVC 我们只需要掌握以下 3 个功能:
1.连接的功能:将用户(浏览器)和 Java 程序连接起来,也就是访问一个地址能够调 到我们的 Spring 程序。
2.获取参数的功能:用户访问的时候会带一些参数,在程序中要想办法获取到参数。
3.输出数据的功能:执行了业务逻辑之后,要把程序执行的结果返回给用户。
对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC。
3.1 Spring MVC 创建和连接
3.1.1 创建 Spring MVC 项目
通常情况下所说的Spring Boot项目,大部分的时候等于Spring MVC项目的,Spring Web也等于Spring MVC项目。
3.1.2实现用户和程序的链接
@RequestMapping 注解介绍
@RequestMapping 是 Spring Web 应用程序中最常被用到的注解之一,它是用来注册接口的路由映射的。
路由映射:所谓的路由映射指的是,当用户访问一个 url 时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射。
@RequestMapping 基础使用:
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/sayhi")//实现路由映射(用户和程序连接)
@ResponseBody//当前方法返回的是一个非静态页面的数据
public String sayHi(){
return "Hello,Spring MVC";
}
}
@RequestMapping 即可修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类 + 方法。
@RequestMapping 是 post 还是 get 请求?
@RequestMapping 默认是 get 方式的请求,但也可支持POST方式的请求
需求:将一个方法只支持GET请求,不能支持POST请求
//表示此方法只支持GET类型的请求
@RequestMapping(value = "/sayhi",method = RequestMethod.GET)//实现路由映射(用户和程序连接)
@GetMapping 和 PostMapping
get 请求的 3 种写法:
// 写法1
@RequestMapping("/index")
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.GET)
// 写法3
@GetMapping("/index")
post 请求的 2 种写法:
// 写法1
@RequestMapping(value = "/index",method = RequestMethod.POST)
// 写法2
@PostMapping("/index")
3.2 获取参数
3.2.1 传递单个参数
/**
* 接受单个参数
* @param name
* @return
*/
@RequestMapping("/showname")
@ResponseBody
public String showName(String name){
return "姓名:"+name;
}
3.2.1 传递多个参数
/**
* 接受多个参数
* @param name
* @param password
* @return
*/
@RequestMapping("/login")
@ResponseBody
public boolean islogin(String name,String password){
boolean result=false;
// //非空校验
// if(name!=null&&!name.equals("")&&password!=null&&!password.equals("")){
//
// }
//非空校验
if(StringUtils.hasLength(name)&&StringUtils.hasLength(password)
&&name.equals("admin")&&password.equals("12345678")){
result=true;
}
return result;
}
3.2.3 传递对象
对象:
@Data
public class UserInfo {
private int id;
private String name;
private String password;
private String photo;
private int age;
// ....
}
传递代码:
3.2.4 表单参数传递/传递多个参数(非对象)
同3.2.3
3.2.5 后端参数重命名(后端参数映射)
某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了一个username 给后端,而后端又是有 name字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用 @RequestParam 来重命名前后端的参数值。
@RequestParam(“xxx”) String yyy 将前端的xxx重命名为后端的yyy
@RequestMapping("/login2")
@ResponseBody
public String islogin2(@RequestParam("username") String name,String password){
return "用户名"+name+"|密码:"+password;
}
3.2.6 设置参数必传@RequestParam
上面 的列 ,如果我们是前端传递一个非time 的参数,就会出现程序报错的情况,如下图所示:
这是因为后端已经声明了前端必须传递一个 time 的参数,但是前端没有给后端传递
非必传参数设置
如果我们的实际业务前端的参数是一个非必传的参数,我们可以通过设置 @RequestParam 中的 required=false 来避免不传递时报错,具体实现如下:
@RequestMapping("/login2")
@ResponseBody
public String islogin2(@RequestParam(value = "username",required = false)
String name,String password){
return "用户名"+name+"|密码:"+password;
}
3.2.7 @RequestBody 接收JSON对象
@RequestMapping("/reg")
@ResponseBody
public UserInfo reg(@ResponseBody UserInfo userInfo){
return userInfo;
}
3.2.8获取URL中参数@PathVariable
3.2.9 上传文件(图片)@RequestPart
关键实现步骤:
- 接受前端传递的文件:
@RequestPart("filename") MultipartFile file
- 将前端传递过来的文件保存在本地:
file.transferTo(new File(filepart))
@Value("${myfile.path}")
private String filePath;//从配置文件中获取图片的上传路径
/**
* 上传文件
* @param username
* @param file
* @return
*/
@RequestMapping("/upfile")
@ResponseBody
public Boolean upFile(String username, @RequestPart("myfile")MultipartFile file) {
boolean result=false;
try {
//得到源文件的名称和后缀
String fileType=file.getOriginalFilename();
fileType=filePath.substring(fileType.lastIndexOf("."));//文件的后缀(类型)
//文件的保存名称
String fileName= UUID.randomUUID().toString()+fileType;
file.transferTo(new File(filePath+fileName));
result=true;
log.info(username+":上传图片成功!");
} catch (IOException e) {
System.out.println("图片上传失败");
}
return result;
}
如果上传的是文件,不使用GET类型的请求方式,一定要使用POST。
3.2.10 获取Cookie/Session/header
获取Cookie
- 通过HttpServletRequest getCookie获取【servlet的操作方法】
/**
* 获取cookie方法1
* @param request
*/
@ResponseBody
@RequestMapping("/getck")
public void getCookie(HttpServletRequest request){
Cookie[] cookies=request.getCookies();
log.info("cookie length:"+cookies.length);
Arrays.stream(cookies).forEach(cookie -> {
log.info(cookie.getName()+":"+cookie.getValue());
});
}
@CookieValue("cookieName")String cookieValue
/**
* 获取 cookie 方法2
*
* @param bite
* @return
*/
@RequestMapping("/getck2")
public String getCookie2(@CookieValue("bite") String bite) {
return bite;
}
- 获取请求头中的数据(Spring Boot方式):
@RequestHeader("headname") String headValue
@RequestMapping("/getua")
public String getUA(@RequestHeader("User-Agent") String userAgent) {
return userAgent;
}
Session 存储和获取
Session 存储和 Servlet 类似,是使用 HttpServletRequest 中获取的,如下代码所示:
/**
* 设置 session
*
* @param request
* @return
*/
@RequestMapping("/setsess")
public boolean setSession(HttpServletRequest request) {
boolean result = false;
// 1.得到 session 对象
try {
HttpSession session = request.getSession(true);
session.setAttribute(SESSION_KEY, "Java");
result = true;
} catch (Exception e) {
log.info("出现了异常:" + e.getMessage());
}
return result;
}
读取 Session 可以使用 HttpServletRequest,如下代码所示:
/**
* 获取 session 方式1
*
* @param request
* @return
*/
@RequestMapping("/getsess")
public String getSession(HttpServletRequest request) {
String result = "";
// 1.得到 session,如果存在就查询 session 中的值,否则返回空
HttpSession session = request.getSession(false); // false=如果没有 session 就不用创建 session 对象
if (session != null && session.getAttribute(SESSION_KEY) != null)
result = (String) session.getAttribute(SESSION_KEY);
return result;
}
获取 sessionn 方式2:
/**
* 获取 sessionn 方式2
*
* @param data
* @return
*/
@RequestMapping("/getsess2")
public String getSession2(@SessionAttribute(required = false,
name = "SESSION_KEY") String data) {
return data;
}
3.3 返回数据
3.3.1 返回静态页面
@RequestMapping("/index")
public String getIndex(){
return "index.html";
}
3.3.2 返回非静态页面的数据
3.3.2.1 组合注解:@RestController
@RestController = @Controller + @ResponseBody
//@Controller
//@ResponseBody//当前类中的所有方法返回的都是一个非静态页面的数据
@RestController
public class RespController {
@RequestMapping("/index")
// @ResponseBody//当前方法返回的都是一个非静态页面的数据
public String getIndex(){
return "index.html";
}
}
3.3.3 Sping MVC跳转有以下两种方式:
- 请求转发
- 请求重定向
请求转发的实现方法1:
/**
* 请求转发的实现方法1
* @return
*/
@RequestMapping("/fw")
public Object forward(){
return "forward:hello.html";
}
请求重定向的实现方法1:
/**
* 请求重定向的实现方法1
* @return
*/
@RequestMapping("/rt")
public Object redirect(){
return "redirect:hello.html";
}
请求转发的实现方法2(了解):
/**
* 请求转发的实现方法2
* @return
*/
@RequestMapping("/fw2")
public void forward2(HttpServletResponse response, HttpServletRequest request) throws ServletException, IOException {
request.getRequestDispatcher("hello.html").forward(request,response);
}
请求重定向的实现方法2:
/**
* 请求重定向的实现方法2
* @return
*/
@RequestMapping("/rt2")
public void redirect2(HttpServletResponse response) throws IOException {
response.sendRedirect("hello.html");
}