文章目录
- SpringMVC
- 1. SpringMVC是什么?
- 1.1 MVC定义
- 1.2 创建SpringMVC项目
- 3.SpringMVC的主要三个功能
- 3.1SpringMVC的连接功能
- 3.1.2注解介绍
- 3.1.3 @RequestMapping默认可以接收所有http请求
- 3.1.4@GetMapping 和 PostMapping只能默认是GET和POST
- 3.2 获取参数功能
- 3.2.1 传递单个参数
- 3.2.2 获取多个参数
- 3.2.3获取对象
- 3.2.4获取表单参数
- 3.2.5@RequestBody接收JSON对象
- 3.2.6 上传文件@RequestPart
- 3.2.7获取Cookie/Session/Header
- 3.2.8 使用参数重命名
- 3.2.9 特殊的URL地址和获取参数的方式:使用@PathVariable
- 3.3返回数据
- 3.3.1请求重定向和请求转发
SpringMVC
1. SpringMVC是什么?
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
1.1 MVC定义
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分 为模型、视图和控制器三个基本部分。
Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据, 控制⽤户输⼊,并向模型发送数据。
最早SpringMvc设计时是返回一个视图,所以默认是返回一个静态页面;现在前后端分离了,要返回数据了,现在要加注解才能返回数据,
MVC和SpringMVC的联系
MVC是一种思想,SpringMVC是对MVC思想的具体实现,总结来说SpringMVC是一个实现了MVC模式并继承了Servlet API的web框架。
1.2 创建SpringMVC项目
在创建 Spring Boot 项⽬时,我们勾选的 Spring Web 框架其实就是 Spring MVC 框架,如下图所 示:
学习 Spring MVC 是因为它是⼀切项⽬的基础,我们以后创建的所有 Spring、Spring Boot 项⽬基本都是基于 Spring MVC 的。
3.SpringMVC的主要三个功能
连接的功能:将⽤户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调⽤到我们的 Spring 程序。
获取参数的功能:⽤户访问的时候会带⼀些参数,在程序中要想办法获取到参数。
输出数据的功能:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤户。
对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC。
3.1SpringMVC的连接功能
在 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"; }}
3.1.2注解介绍
@RequestMapping 是 Spring Web 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的路由映射的。
路由映射:所谓的路由映射指的是,当⽤户访问⼀个 url 时,将⽤户的请求对应到程序中某个类 的某个⽅法的过程就叫路由映射。
@RequestMapping 即可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类 + ⽅ 法。
@ResponseBody 表示当前类返回的是非静态页面,而是数据
@Controller 表示是一个控制器,要在spring启动时加载并注册
@ResponseBody和@Controller有一个组合注解@RestController,使用@RestController可以代替@ResponseBody和@Controller
3.1.3 @RequestMapping默认可以接收所有http请求
如果没有指定请求方式,@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),这个是关键
3.1.4@GetMapping 和 PostMapping只能默认是GET和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")
3.2 获取参数功能
3.2.1 传递单个参数
写法一:基于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; }}
3.2.2 获取多个参数
@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中当传递多个参数的时候,传递参数的顺序是不影响程序的执行的,获取参数结果和参数的名称有关,和顺序无关
3.2.3获取对象
Spring MVC 可以⾃动实现参数对象的赋值,但是要设置getter和setter方法,但是只要加@Data注解就自动加了
@Datapublic 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里属性名字一样
3.2.4获取表单参数
参数请求的类型:
- URL传参
- ajax传参
- form表单传参
这里以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(); }}
3.2.5@RequestBody接收JSON对象
@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对象
3.2.6 上传文件@RequestPart
使用postman上传文件
后端写代码来接收
@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"; }}
3.2.7获取Cookie/Session/Header
浏览器会默认将当前网站的所有cookie发送给后端
原因:http协议无状态
传统获取 header/cookie
@RequestMapping("/param10")@ResponseBodypublic String param10(HttpServletResponse response, HttpServletRequest request) { 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")@ResponseBodypublic 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没有就没有了,不会去报错
3.2.8 使用参数重命名
@RequestMapping("/gettime") public String getTime(@RequestParam(value = "t",required = false)String time) { return "time: "+time;//此时只能识别t参数,并将参数t的值,设置给time变量,此时即使使用time参数,也是读取不到前端的参数的,它现在只认参数名为t的参数 }
required设置参数是否必传,如果是true就需要必传,不然就会报错;设置为false不传不会报错
3.2.9 特殊的URL地址和获取参数的方式:使用@PathVariable
从url中获取参数
@RequestMapping("/login4/{name}/{password}") public String login4(@PathVariable("name") String name,@PathVariable("password") String password) { return "name: "+name+" | password"+ password; }
3.3返回数据
返回数据比较简单,基本上上面获取完代码后都会返回,这里就不展开,主要讲请求重定向和请求转发
3.3.1请求重定向和请求转发
forward VS redirect
return 不但可以返回⼀个视图,还可以实现跳转,跳转的⽅式有两种:
- forward 是请求转发;
- redirect:请求重定向。
// 请求重定向@RequestMapping("/index")public String index(){ return "redirect:/index.html";}// 请求转发@RequestMapping("/index2")public String index2(){ return "forward:/index.html";}
举个例子说明一下forward和redirect吧
比如说,小卢同学告诉他妈妈说我想要买新键盘,如果小卢他妈妈说好,我帮你去买,这就是forward请求转发;如果他妈妈给他个地址让他自己去买,这就是请求redirect重定向
也就是说,转发是服务器帮转的,而重定向是让浏览器重新请求另一个地址
forward和redirect具体区别:
- 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务端转发
- 请求重定向地址发生变化,请求转发地址不发生变化
- 请求重定向与直接访问新地址效果一样,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问(请求转发如果资源和转发的⻚⾯不在⼀个⽬录下,会导致外部资源不可访问)
举个例子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;改成请求重定向就能获取到