文章目录
- 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注解就自动加了
@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里属性名字一样
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 "<h1>用户名:" +name+" | 密码:"+password+"</h1>";}
}
用对象来获取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 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 对象就创建sessionHttpSession 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;改成请求重定向就能获取到