SpringMVC全称Spring Web MVC,Spring Web MVC又简称Spring Web或Spring MVC,它是一个基于Servlet API的框架
一个经典问题:Spring/SpringBoot/SpringMVC的区别
答:我们说的Spring就是Spring farmework ,Spring farmework它里面包含很多模块,它的最早核心功能就是IOC容器,能够去除代码的一个耦合性,SpringBoot在创建之初的目的就是为Spring服务的,就是为了快速开发Spring框架嘛,相比于Spring来说,SpringBoot有很多优点,比如说它内置了tomcat容器,可以更容易地添加依赖,发布也很简单,可以摆脱xml文件,它将Spring的功能升上了一个层次,所以后面大家都很喜欢SpringBoot了,都用SpringBoot了,后面很多插件也都是专门为SpringBoot去做的,但是SpringBoot底层还是基于Spring实现的;SpringMVC全称Spring Web MVC,Spring Web MVC又简称Spring Web或Spring MVC,它是一个基于Servlet API的框架,SpringMVC是随着Spring的诞生而诞生的,它最早是Spring里的一个外部模块而已,就是说Spring它有很多很多模块,其中就有一个是基于http协议,那些request,response这些http请求,这个就是SpringMVC
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分 为模型、视图和控制器三个基本部分。
Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据, 控制⽤户输⼊,并向模型发送数据。
最早SpringMvc设计时是返回一个视图,所以默认是返回一个静态页面; 现在前后端分离了,要返回数据了,现在要加注解才能返回数据,
MVC和SpringMVC的联系
MVC是一种思想,SpringMVC是对MVC思想的具体实现,总结来说SpringMVC是一个实现了MVC模式并继承了Servlet API的web框架。
在创建 Spring Boot 项⽬时,我们勾选的 Spring Web 框架其实就是 Spring MVC 框架,如下图所 示:
学习 Spring MVC 是因为它是⼀切项⽬的基础,我们以后创建的所有 Spring、Spring Boot 项⽬基本都是基于 Spring MVC 的。
连接的功能:将⽤户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调⽤到我们的 Spring 程序。
获取参数的功能:⽤户访问的时候会带⼀些参数,在程序中要想办法获取到参数。
输出数据的功能:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤户。
对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC。
在 Spring MVC 中使⽤ @RequestMapping 来实现 URL 路由映射,也就是浏览器连接程序的作⽤。 接下来要实现的功能是访问地址:http://127.0.0.1:8080/web/hi,能打印“Hi springMvc”信息。
代码如下:
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")//路由注册,当使用/web可以访问到当前类
public class WebController {
@RequestMapping("/hi")//路由注册,当使用/web/hi可以访问到当前方法
public Object sayHi() {
return "Hi springMvc";
}
}
@RequestMapping 是 Spring Web 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的路由映射的。
路由映射:所谓的路由映射指的是,当⽤户访问⼀个 url 时,将⽤户的请求对应到程序中某个类 的某个⽅法的过程就叫路由映射。
@RequestMapping 即可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类 + ⽅ 法。
@ResponseBody 表示当前类返回的是非静态页面,而是数据
@Controller 表示是一个控制器,要在spring启动时加载并注册
@ResponseBody和@Controller有一个组合注解@RestController,使用@RestController可以代替@ResponseBody和@Controller
如果没有指定请求方式,@RequestMapping将接收GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT所有的HTTP请求方式。
下面展示 @RequestMapping设置只接收post请求
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping(value = "/hello" ,method = RequestMethod.POST)
public Object sayHello() {
return "Hi SpringMVC";
}
}
@RequestMapping(value = “/hello” ,method = RequestMethod.POST),这个是关键
GET请求三种写法
// 写法1
@RequestMapping("/index")
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.GET)
// 写法3
@GetMapping("/index")
Post请求两种写法
// 写法1
@RequestMapping(value = "/index",method = RequestMethod.POST)
// 写法2
@PostMapping("/index")
写法一:基于servlet的request来获取参数(不推荐这么写)
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/get1_0")
public Object getParam1_0(HttpServletRequest request, HttpServletResponse response) {
return "Hi" + request.getParameter("name");//通过servlet里的request获取参数,但是不推荐这样用
}
}
特殊说明:在Spring MVC中默认内置隐藏了两个参数,一个是Request(HttpServletRequest),一个是Response(HttpServletResponse)对象,所以如果想要使用这两个参数,只需要在方法中申明即可获取到
写法二:在 Spring MVC 中可以直接⽤⽅法中的参数来实现传参(推荐写法)
⽐如以下代码:
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/get1")
public Object getParam1(Integer age) {
return "value: "+age;
}
}
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/get2")
public Object getParam2(String name,Integer age) {
return "name:: "+name + " | age:"+ age;
}
}
Spring MVC中当传递多个参数的时候,传递参数的顺序是不影响程序的执行的,获取参数结果和参数的名称有关,和顺序无关
Spring MVC 可以⾃动实现参数对象的赋值,但是要设置getter和setter方法,但是只要加@Data注解就自动加了
@Data
public class Student {
private Integer id;
private String name;
private Integer age;
private String sex;
}
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/get3")
public String getParam3(Student student) {
return student.toString();
}
}
在没有其他注解下,传的参数要和Student里属性名字一样
参数请求的类型:
这里以form表单传参为例
用参数来接收form表单的参数
<form method="get" action="web/login">
<div>
<h1>登录</h1>
用户:<input name="name"><br>
密码:<input name="password"><br>
<input type="submit" value="提 交">
</div>
</form>
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/login")
public String login(String name,String password) {
return "用户名:"
+name+" | 密码:"+password+"";
}
}
用对象来获取form表单的参数
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/req")
public String req(User user) {
return user.toString();
}
}
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/login3")
public Map<String,Object> login3(@RequestBody User user) {
Map<String,Object> result = new HashMap<>();
result.put("name",user.getName());
result.put("password",user.getPassword());
return result;
}
}
@RequestBody可以用来获取JSON对象
后端写代码来接收
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/req2")
public String req2(String name, @RequestPart("myfile")MultipartFile file) throws IOException {
//保存文件
file.transferTo(new File("D:/1/img.pong"));
return "success";
}
}
浏览器会默认将当前网站的所有cookie发送给后端
原因:http协议无状态
传统获取 header/cookie
@RequestMapping("/param10")
@ResponseBody
public String param10(HttpServletResponse response, HttpServletRequest requ
est) {
String name = request.getParameter("name");
// 获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
String userAgent = request.getHeader("User-Agent");
return name + ":"+userAgent;
}
使用注解获取 Cookie—@CookieValue
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
@RequestMapping("/cookie")
public String cookie(@CookieValue("name") String name) {
return "cookie"+name;
}
}
获取Header——@RequestHeader
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String userAgent) {
return "userAgent:"+userAgent;
}
Session 存储和获取
Session 存储和 Servlet 类似,是使⽤ HttpServletRequest 中获取的,如下代码所示:
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request) {
// 获取 HttpSession 对象,参数设置为 true 表示如果没有 session 对象就创建session
HttpSession session = request.getSession(true);
if(session!=null){
session.setAttribute("username","小卢");
}
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;
}
也可以使用注解@SessionAttribute
@RequestMapping("/getSession")
public String getSession(@SessionAttribute(value = "username",required = false) String name) {
return "username: " + name;
}
**@SessionAttribute(value = “username”,required = false **:required不设置它,默认是true,如果这个session不存在会报错;如果设置为false,session没有就没有了,不会去报错
@RequestMapping("/gettime")
public String getTime(@RequestParam(value = "t",required = false)String time) {
return "time: "+time;//此时只能识别t参数,并将参数t的值,设置给time变量,此时即使使用time参数,也是读取不到前端的参数的,它现在只认参数名为t的参数
}
required设置参数是否必传,如果是true就需要必传,不然就会报错;设置为false不传不会报错
从url中获取参数
@RequestMapping("/login4/{name}/{password}")
public String login4(@PathVariable("name") String name,@PathVariable("password") String password) {
return "name: "+name+" | password"+ password;
}
返回数据比较简单,基本上上面获取完代码后都会返回,这里就不展开,主要讲请求重定向和请求转发
forward VS redirect
return 不但可以返回⼀个视图,还可以实现跳转,跳转的⽅式有两种:
// 请求重定向
@RequestMapping("/index")
public String index(){
return "redirect:/index.html";
}
// 请求转发
@RequestMapping("/index2")
public String index2(){
return "forward:/index.html";
}
举个例子说明一下forward和redirect吧
比如说,小卢同学告诉他妈妈说我想要买新键盘,如果小卢他妈妈说好,我帮你去买,这就是forward请求转发;如果他妈妈给他个地址让他自己去买,这就是请求redirect重定向
也就是说,转发是服务器帮转的,而重定向是让浏览器重新请求另一个地址
forward和redirect具体区别:
举个例子forward不能访问到外部资源
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/index")
public String sayHi(){
return "forward:/index.html";
}
}
在目录中当请求转向到index.html后,因为hello.js和index.html不在同一个目录,所以会导致获取不到hello.js;改成请求重定向就能获取到