您现在的位置是:首页 >技术教程 >Spring MVC网站首页技术教程
Spring MVC
日升时奋斗,日落时自省
目录
1、MVC
Spring MVC全称叫做 Spring Web MVC 是基于Servlet API构建的原始Web框架
通常叫做:“Spring MVC”
Spring MVC是一种基于Java的web框架,它是Spring Framework的一部分。
1.1、MVC定义
Spring MVC基于Model-View-Controller(MVC)软件架构模式,它通过前端控制器DispatcherServlet将HTTP请求转发给控制器Controller,然后控制器处理请求并返回对应的响应视图View,再由视图渲染器(View Resolver)将响应视图渲染为HTML文件返回给浏览器进行展示。在这个过程中,模型对象Model可以在控制器和视图之间传递数据
整个过程前后端都是在一起的
但是现在不同了,前后端都是分开的,为的就是部分功能可以再其后进行加载,不需要上来就把所有的东西都加在出来(慢)
1.2、MVC和 Spring MVC的关系
MVC是一种思想,而,Spring MVC是对MVC思想的具体实现
可以认为Spring MVC是MVC的一种实现方式,Spring MVC是MVC架构在Web应用程序开发中的一种实现方式,是基于MVC设计模式的一种Web框架
Spring的核心就是Spring MVC ,Spring Boot是Spring的脚手架
在创建Spring Boot项目时,勾选Spring Web 框架其实就是Spring MVC框架,Spring,Spring Boot项目基本都是基于Spring MVC的
2、Spring MVC
从以下三个功能进行解释:
<1>连接的功能:用户与Java程序连接起来,访问一个地址能够调用到Spring程序
<2>获取参数的功能:用户访问的时候会带一些参数,在程序中要想办法获取参数
<3>输出数据的功能:执行了业务逻辑后,要把程序执行结果返回给用户
2.1、Spring MVC创建和连接
Spring MVC项目创建和Spring Boot创建项目相同(Spring MVC 使用Spring Boot的方式创建),在创建的时候选择Spring Web 就相当于创建了Spring MVC的项目
在Spring MVC中使用,注解来时先URL路由映射
2.1.1、创建Spring MVC项目
Spring MVC可以基于Spring Boot创建,也就是创建一个Spring Boot项目,勾选上Spring Web模块即可
Spring boot项目创建好以后 ,在demo包下创建controller层,controller层内写一个类,启动项目访问路由看看出现页面说明创建成功
@RestController //让spring 框架启动时 加载
@RequestMapping("/user") //设置路由
public class UserController {
//路由器规则注册
@RequestMapping("/sayhi")
public String sayhi(){
return "spring mvc sayhi()";
}
}
启动成功表示:
2.1.2、设置路由
@RequestMapping是Spring MVC框架中的注解之一,它用于将一个HTTP请求映射到一个处理器方法上,告诉DispatcherServlet处理来自客户端的一种或多种请求。
@RequestMapping的使用方式非常灵活,可以在控制器类上和控制器类中的方法上使用
@RequestMapping可以修饰类,也可以修饰方法,当修饰类和方法时,访问地址就是类+方法
注:路由可以设置多级路由
2.1.3、@RequestMapping的请求类型
访问上面设置好的路由 127.0.0.1:8080/user/sayhi
@RequestMapping是post请求还是get请求这里我们就以当前写的一个代码进行访问路由看看,是什么,F12打开检查页面,点击操作如下查看请求方法
那post请求行不行,那我们来试一下就知道了,现在项目仍然是启动状态,这里拿postman测试一下(当然是可以的)
如果我这里规定只能接受post或者get方法其中一个呢???
@RequestMapping本身就支持这里请求方法,同时也可以设定
2.1.3、设置请求方法
以下所有设置方法的代码仅此修改一行代码
I、只针对get请求的两种写法:
<1>@RequestMapping注解设置参数
method请求方法参数设置为RequestMethod.GET,后缀为点GET 就表示只接收GET请求
@RequestMapping(value = "/sayhi",method = RequestMethod.GET)
这里设置以后我们重启项目(使用postman)尝试一下,看看会有什么结果,
post方法已经不被允许了
<2>@GetMapping注解,只允许接收get方法
该注解也是可以实现只接收get请求的
@GetMapping("/sayhi")
II、只针对post请求的两种写法:
<1>@RequestMapping注解设置参数
@RequestMapping(value = "/sayhi",method = RequestMethod.POST)
这里设置以后我们重启项目(使用postman)尝试结果:
get请求就不行了
<2> @PostMapping注解
@PostMapping("/sayhi")
3、获取参数
3.1、传递单个参数
Spring MVC可以直接用方法中的参数实现传参
@RestController //让spring 框架启动时 加载
@RequestMapping("/user") //设置路由
public class UserController {
//路由器规则注册
@RequestMapping("/sayhi")
public String sayhi(String name){
return "name 的 参数 :"+name;
}
}
使用postman访问方法:
注:传递过程中,如果其中的参数没有给值,那就是null(但是如果这参数是基础类型,就会报错,需要使用其包装类进行获取)
这里演示一个基础类型的情况:
3.2、Servlet传递单个参数
在Spring boot中也可以使用Servlet方式进行接收和传递请求,这里只是片段代码展示
@RequestMapping("/sayhi4")
public String sayhi4(HttpServletRequest request, HttpServletResponse response){
return "Servlet接收 queryString :"+request.getParameter("name");
}
postman中访问:
同样也可以调用Servlet中的其他方法,使用方式和Servlet一样
3.3、传递对象
并且Spring MVC可以自动实现参数对象的赋值
这里我们需要写一个实体类,存储对象属性
涉及到一个新的注解:@Data注解 是Lombok提供的是一个复合注解
注解 | 作用 |
@Data | @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor |
@Data
public class User {
private int userId;
private String username;
private int password;
private int age;
}
这里我们没有使用User类去定义方法,而是Object因为User如果是个null的话能强转吗,不能,所以防止null情况,这里直接用Object接收
@Controller
@ResponseBody
@RequestMapping("/user2")
public class UserController2 {
@RequestMapping("/index")
public Object sayhi(User user){
System.out.println(user.toString());
return user;
}
}
3.4、传递多个参数(非对象)
能传一个参数,也就能传递多个参数
@Controller
@ResponseBody
@RequestMapping("/user2")
public class UserController2 {
@RequestMapping("/index2")
public String sayhi(String name ,String password){
return "name:"+name+" | password "+password;
}
}
进行路由访问:
3.5、设置参数必传
上面的所有例子,都没有设置传参类型,如果没有传值的情况下都为null,@RequestParam注解设置参数必传,可以将要紧的参数传值设为必须,提高了数据的连贯性
同时也可以更改需要接收的参数的名称
@RequestParam内部:
注:默认状态下,只要使用@RequestParam注解,参数就必须有(下面附加的代码required设置为true其实是灰色的,默认状态)
在原来的访问中,我这里都使用的是name传输数据和接收数据,但是现在前端就不想用name传,那不争的情况下就使用如下操作(这里required其实可以不写因为是默认值):
@Controller
@ResponseBody
@RequestMapping("/user2")
public class UserController2 {
@RequestMapping("/index2")
public String sayhi(@RequestParam(value = "username",required = true) String name , String password){
return "name:"+name+" | password "+password;
}
}
注:这里required设置参数为false,就可以不穿参数,并且也不会报错
postman路由访问:
注:使用别名之后就不能再使用原来的名称
如果此时不传username的参数,会报错
注:如果不想让这个值是必传值,只是想改一个名称,这里required参数设置为false就可以了
3.6、接收JSON对象
普通方法是接收不了JSON对象,此处需要对应的注解来接收JSON格式的数据
这里我们先写一个实体类,我们这里接收一个对象(还是前面的创建过的User类对象)
@Data
public class User {
private int userId;
private String username;
private int password;
private int age;
}
注:设置形参的前面加上该注解(此处注解设置required设置false就是可以不传值也不会报错)
@Controller
@ResponseBody
@RequestMapping("/user3")
public class UserController3 {
@RequestMapping("/method")
public Object method_5(@RequestBody(required = false) User user){
System.out.println("user:"+user);
return user;
}
}
postman测试代码:
postman功能比较多,这里大体简述下面的这节选择
3.7、获取URL中参数
@PathVariable注解,在参数较少的特殊情况下可以给路径中加入参数,直接从路径中获取
该注解有点类似于queryString,但是比queryString更快,直接将参数放在路径中,在访问路径的时候参数已经被拿到了,相比获取访问路径后,再获取url后面的请求参数更快
代码:
@Controller
@ResponseBody
@RequestMapping("/user3")
public class UserController3 {
@RequestMapping("/method2/{name}/{password}")
public Object method2(@PathVariable String name,@PathVariable String password){
return "name:"+name+" | password:"+password;
}
}
这里注解中路径涵盖参数 是需要与我们写的参数一样的,形参是什么,这里就需要写什么(用大括号抱起来)
postman测试结果:
如果参数不一样,那就获取不到了,也会直接报错,因为没有参数传递进来,默认必传参数
如果真的不想写一样的,那就需要我们亲自去设置了(注解中参数设置一个需要的别名)
注解参数中取一个别名(路径中和别名一样就行)
3.8、上传文件
@RequestPart针对上传文件一个注解,同时也对应这定义的类是MultipartFile(这里需要注意)
代码(注释比较详细):
@RestController
@RequestMapping("/file")
public class FileController {
//第一个参数其实没有啥实际意义, 第二个参数需要使用@RequestPart注解修饰
//形参定义 也必须是 MultipartFile类型 才能被接收
@RequestMapping("/param")
public Object param(String name, @RequestPart("myfile")MultipartFile file){
//获取文件名后缀 文件名这里我们只取点 后面的部分
String fileNamelast=file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
//新的文件名 文件名 + 后缀
String filename= UUID.randomUUID()+fileNamelast;
//这里存放的就是路径了 路径 + 文件名
File savefile=new File("E:\Test\"+filename);
//将选择文件传到 我们选择的路径下
try {
file.transferTo(savefile);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
postman测试结果:
启动类后路径下实现操作:
3.9、注解获取Cookie/Session/header
<1>传统方式获取Cookie
Spring MVC就是在Web应用程序开发中的一种实现方式,所以同样能使用原来的方式进行操作
@Controller
@ResponseBody
@RequestMapping("/user3")
public class UserController3 {
@RequestMapping("/param10")
public String param10(HttpServletRequest request, HttpServletResponse response){
String name=request.getParameter("name");
//获取cookie信息
Cookie[] cookies=request.getCookies();
String userAgent=request.getHeader("User-Agent");
return name+" : "+ userAgent;
}
}
注:当前cookie是什么都没有的,所以这里也看见啥(下面使用注解时候给友友们展示cookie)
<2>使用@CookieValue注解获取Cookie
代码很简单,@CookieValue注解传参就是cookie名称,
@RequestMapping("/cookie")
public String method(@CookieValue(value = "bite",required = false) String bite){
return "cookie:"+bite;
}
F12设置以下cookie的名称和值,刷新一下网页
再次刷新的结果:
<3>@RequestHeader注解获取header值
一级路由:还是user3
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent")String userAgent){
return "User-Agent:"+userAgent;
}
访问路由结果:
<4>@SessionAttribute注解获取Session值
注:没有注解设置Session值,只能使用注解获取,所以这里再写获取Session值时还需要写设置Session值
//这里设置一个 Session的键 其实也可以不用设定,就是为了好看
private static final String SESSION_KEY="USERINFO_SESSION_KEY";
//Session 设置
@RequestMapping("/setsession")
public String setsession(HttpServletRequest request){
//获取 HttpSession 对象的参数 参数true
HttpSession session=request.getSession(true);
if(session!=null){
//给session设置一个哈希值
session.setAttribute(SESSION_KEY,hashCode());
}
return "session 设置成功";
}
//获取session
@RequestMapping("/getsession")
public Object getSession(@SessionAttribute(value =SESSION_KEY,required = false)String content){
return "session ->"+content;
}
首先 要先 访问 设置Session的路由,然后才是访问获取Session路由
设置session路由:
获取session路由:
4、访问页面与跳转
4.1、访问静态页面
在访问静态页面的时候一定记得把依赖带上,否则会访问不了
在pom.xml文件中导入依赖,我们在开始的时候一般都会导入的
代码:
//不能使用该注解@ResponseBody,该注解是将显示内容转化为字符串的,这里为了显示静态页面
@Controller
@RequestMapping("/user4")
public class UserController4 {
@RequestMapping("/index")
public Object method(){
return "/index.html";
}
}
访问路由结果:
4.2、请求转发与请求重定向
return不能返回视图,但是可以通过跳转到视图,跳转方式这里涉及到两个关键词(forward,redirect)
<1>forward:针对请求转发
举个例子:请求转发是当前请求需要去一个地方交给了另一个人来跑腿(转发过去),但是这件事情还是我的(url还是我的),前面提到访问静态页面的方法就是一个请求转发,注意到细节的友友们应该会看见其实url是没有改变的,但是页面发生了变化
这里来看一下演示代码预期结果:
@Controller
@RequestMapping("/user4")
public class UserController4 {
@RequestMapping("/index")
public String method(){
return "forward:/index.html";
}
}
<2>redirect:针对请求重定向
请求重定向是资源重新定位,我需要去一个地方,我们没有请人去,我亲自去的(指哪到哪url会改变跳转到我们要去的位置)
@RequestMapping("/index2")
public String method2(){
return "redirect:/index.html";
}
<3>forward和redirect区别
I、请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发
II、请求重定向地址发生变化,请求转发地址不发生变化
III、请求重定向与直接访问新地址的效果一样,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问
注:请求转发forward诱发问题:请求转发毕竟不是自己亲自移动到对应的url,资源和转发页面不在同一目录下,导致资源不可访问