赞
踩
Spring MVC(Model-View-Controller)是Spring框架的一部分,是基于Servlet API构建的Web原始框架。用于开发基于Java的Web应用程序。它采用MVC设计模式,将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。
MVC模式遵循单一职责原则,将应用程序的不同方面分离开来,使得每个部分都可以独立进行修改和扩展,提高了代码的可维护性和可测试性。同时,它也带来了更好的代码组织和清晰的逻辑层次。
在MVC模式中,用户与视图进行交互,视图将用户的请求发送给控制器,控制器根据请求调用相应的模型进行数据处理和更新,并选择合适的视图进行展示。这种分离使得每个部分可以独立开发、测试和维护,同时也支持更好的可重用性和可扩展性。
总而言之,MVC模式通过将应用程序划分为模型、视图和控制器三个组件,实现了数据、展示和交互的分离,以提供灵活、可维护和可扩展的软件设计方案。
Spring MVC是在MVC模式的基础上实现的一种Web框架,或者说是MVC是一种思想,而SpringMVC是一种具体实现。它利用了MVC的优势并添加了更多的功能和便利性,使得开发者可以更轻松地构建和维护现代化的Web应用程序。
在创建SpringBoot项目时,我们勾选的SpringWeb框架就是SpringMVC框架,因此照着SpringBoot创建流程就可以,只需添加SpringWeb依赖。【SpringBoot创建 链接】
在SpringMVC项目中使用@RequestMapping
注解来实现URL路由映射。也就是在浏览器上连接程序的作用。接下来实现的访问地址localhost:8080/hi
打印“hello SpringMVC”信息。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody //返回非页面数据 (默认是返回静态页面的)
public class UserController {
@RequestMapping("/hi") //注册路由
public String sayHi(){
return "hello SpringMVC";
}
}
localhost:8080/hi
@RequestMapping是SpringWeb应用程序中最常被用到的注解之一,它是用来注册路由映射的。
路由映射:当用户访问一个url时,将用户的请求对应到程序中的某个类的某个方法的过程就叫做路由映射。
在使用@RequestMapping注解时,可以按照以下方式进行使用:
@RestController //@RestController = @ResponseBody + @Controller
public class MyController {
@RequestMapping("/hello")
public String hello() {
return "Hello, world!";
}
}
上述代码演示了一个简单的示例,当访问路径为localhost:8080/hello
时,将会执行hello()方法,并返回"Hello, world!"。@RequestMapp即可修饰类,也可同时修饰方法,当修饰类和方法时,访问的地址就是 “类的路由+方法的路由”。
@RestController
@RequestMapping("/user")
public class MyController {
@RequestMapping("/hello")
public String hello() {
return "Hello, world!";
}
}
上述代码演示了一个简单的示例,当访问路径为localhost:8080/user/hello
时,将会执行hello()方法,并返回"Hello, world!"。
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
return "Hello, world!";
}
可以通过method属性来指定具体的HTTP方法,例如GET、POST等。上述代码指定了只有当使用GET方法访问路径为"/hello"时,hello()方法才会被执行。【可以使用postman操作get请求】
import org.springframework.web.bind.annotation.PathVariable;
@RequestMapping("/hello/{name}")
public String hello(@PathVariable String name) {
return "Hello, " + name + "!";
}
可以通过使用@PathVariable注解来接收路径中的参数。上述代码中的{name}表示路径中的参数,该参数将会传递给hello()方法并被使用,访问http://localhost:8080/hello/zhangsan
,会把zhangsan传给name,并显示到页面。
@RequestMapping(value = {"/hello", "/greeting"})
public String hello() {
return "Hello, world!";
}
可以通过将多个路径作为数组或多个值传递给@RequestMapping注解的value属性,来支持多个路径映射,此时访问路径为localhost:8080/hello
或者localhost:8080/greeting
都可以访问到hello()方法。
@GetMapping和@PostMapping是Spring Framework中的注解,用于定义HTTP请求的处理方法的映射。
@GetMapping注解表示该方法用于处理HTTP GET请求。
@PostMapping注解表示该方法用于处理HTTP POST请求。
//1.
@RequestMapping("/hello")
//2.
@RequestMapping(value = "/hello", method = RequestMethod.GET)
//3.
GetMapping("/hello")
// 写法1
@RequestMapping(value = "/hello",method = RequestMethod.POST)
// 写法2
@PostMapping("/hello")
在SpringMVC中可以直接用方法中的参数来实现传参:
@RequestMapping("/hello")
public String sayHi(String name){
return "hello SpringMVC" + name;
}
使用postman访问方法:
@RequestMapping("/prams")
public String prams(String name,Integer id) {
return "name : "+name+" ,id:" +id;
}
前端访问:
注意:当有多个参数时,前后端进行参数匹配时,是根据参数的名称进行匹配的,并不会因为参数的顺序和位置发生变化影响后端获取参数的结果。
SpringMVC可以自动的实现对象参数的赋值,比如Person对象:
import lombok.Data;
@Data //自动生成setter和getter、toString方法
public class Person {
private int id;
private String name;
}
传递对象实现:
@RequestMapping("/person")
public String person(Person person) {
return person.getName()+ ":" + person.getId();
}
前端访问:
可以通过在@RequestParam
注解中指定value
或name
属性来实现前后端参数值重命名。
下面是使用@RequestParam
注解进行参数重命名的示例:
@GetMapping("/search")
public String search(@RequestParam(value = "q") String query) {
// ...
return "Search result for: " + query;
}
在上述示例中,通过value = "q"
将参数重命名为"q",并将其绑定到query
参数上。请求中传递的参数名称应为"q",而不是方法参数名。
另一种方式是使用name
属性,它与value
属性具有相同的效果:
@GetMapping("/search")
public String search(@RequestParam(name = "q") String query) {
// ...
return "Search result for: " + query;
}
使用postman访问:
这是因为后端声明了前端必须传递一个“q”参数,但是前端没有给后端传递,于是就报错了,我们查看以下@RequestParam的注解实现细节就可以发现问题,注解实现如下:
在未明确指定required
属性时,默认值为true
,即传递参数为必需的。如果请求中没有传递该参数,服务器将返回400 Bad Request错误。
如果我们要实现前端参数是一个非必传参数,可以通过设置@RequestParam种的required=false来避免不传递参数而报错:
@GetMapping("/search")
public String search(@RequestParam(value = "q",required = false) String query) {
// ...
return "Search result for: " + query;
}
使用postman访问:
如果将required
属性设置为false
,则查询参数变为可选,不再强制要求请求中包含该参数。此时,如果请求中没有传递该查询参数,方法参数将被设置为null
,并且方法仍然能够正常调用。
还是person类
import lombok.Data;
@Data //自动生成setter、getter等方法
public class Person {
private int id;
private String name;
}
接收代码:
import org.springframework.web.bind.annotation.*;
@RequestMapping(value = "/person",method = RequestMethod.POST)
public Person person(@ResponseBody Person person) {
System.out.println(person.getId()+": "+person.getName());
return person;
}
使用postman访问:
使用@RequestBody
注解将请求体的JSON数据绑定到方法参数上。然后,将参数声明为一个合适的Java对象类型,Spring将根据请求体的JSON数据自动进行反序列化,并将其转换为该Java对象。
为了能够正确地进行序列化和反序列化,确保Person
类拥有与JSON数据结构对应的属性以及正确的getter和setter方法。
如果去掉参数上的@ResponseBody,将接收不到JSON
对象数据。
通常有两种传参:
第一种方式的优点:
1.搜索引擎抓取关键字权重更高,比如在百度上搜索123,会先显示第一种的url数据。
2.url更简洁
@PathVariable获取参数,在文章@RequestMapping阶段有说明过。
实现代码:
@RequestMapping("/reg/{name}/{pwd}")
public String reg(@PathVariable String name,@PathVariable String pwd){
return name+ ": "+ pwd;
}
前端实现:
注意:此时参数传参位置要和后端参数顺序位置一致。
代码实现:
@RequestMapping("/load") public boolean upload(@RequestPart("file")MultipartFile file){ //构造文件名 String fileName = UUID.randomUUID()+//文件名(随机值) file.getOriginalFilename()//获取原文件名 .substring(file.getOriginalFilename()//从原文件后缀.截取 .lastIndexOf("."));//文件后缀(包含“.”) //文件保存地址 File saveFile = new File("D:\\"+fileName); try { //保存文件 file.transferTo(saveFile); return true; } catch (IOException e) { e.printStackTrace(); } return false; }
上述代码uploadFile()
方法使用@RequestPart
注解来接收名为"file"的表单项,其中MultipartFile
参数类型用于接收上传的文件内容。
文件名:UUID生成的随机值+从原文件名的后缀”.“开始截取(包含“.”),拼接成新的文件名。
使用postman上传文件:
**上传结果:**这是典型的UUID生成的
注意:上传文件是有限制大小的,默认为1M
,超过这个大小,会报错。
可以在配置文件(.properties)中进行配置:
spring.servlet.multipart.max-file-size=10MB
上述示例中,max-file-size
属性设置每个文件的最大大小限制。
使用@CookieValue注解获取Cookie
@RequestMapping("/getcok")
public String getCookie(@CookieValue("myCookie") String mk){
return "cookie :" + mk;
}
在上面的示例中,getCookie
方法使用@CookieValue
注解来接收名为"myCookie"的Cookie值,并将其存储在mk
参数中。要确保请求中包含指定名称的Cookie,否则@CookieValue
将无法获取到对应的值。
如果希望没有获取到Cookie时不报错,需要设置required = false
。
@RequestMapping("/getcok")
public String getCookie(@CookieValue(value = "myCookie",required = false) String mk){
return "cookie :" + mk;
}
运行结果:
使用@RequestHeader获取Header,使用方法和@CookieValue相似
@RequestMapping("/hd")
public String getHeader(@RequestHeader(value = "myHeader",required = false) String hd){
return "header :" + hd;
}
运行结果:
要获取Session得现有Session,所以先存储一个Session:
private static final String SESSION_KEY = "SESSION";
@RequestMapping("/setsession")
public void doPostConstruct(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute(SESSION_KEY,"zhangsan");//存储session
}
使用@SessionAttribute获取Session:
@RequestMapping("/getSe")
public String getSession(@SessionAttribute(SESSION_KEY) String mySe){
return mySe;
}
上述代码中,getSession
方法使用@SessionAttribute
注解来绑定SESSION_KEY
会话名称,并将接收到的值,赋值给mySe
中。确保会话属性的名称与@SessionAttribute
注解中指定的名称一致。
先访问路由,设置Session:
获取Session:
创建前端index.html
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>我是静态页面</h1>
</body>
</html>
创建controller
@Controller
@RequestMapping("/test")
public class IndexController {
@RequestMapping("/index")
public Object index(){
//...
return "/index.html";
}
}
上述代码中,是没有加@ResponseBody
注解的,所以默认返回是静态页面。注意,如果返回结果没有加/
是在当前目录(/test)下找index.html
,是会报400错误的,找不到。加/
代表的是在根目录下找index.html
,因为idex.html
是放在根目录(域名+端口号)下的。
运行结果:
代码:
@RequestMapping("/m")
@ResponseBody
public String method() {
return "<h1>Hello,HTML~</h1>";
}
访问结果:
@ResponseBody可以加在类或方法上,框架是会根据返回结果进行自动适配一个合适的类型。
@RequestMapping("/m8")
@ResponseBody
public HashMap<String, String> method_8() {
HashMap<String, String> map = new HashMap<>();
map.put("Java", "Java Value");
map.put("MySQL", "MySQL Value");
map.put("Redis", "Redis Value");
return map;
}
访问结果:
Forward (请求转发转发):
Redirect (请求重定向):
区别:
请求方不同:请求重定向(redirect)客户端转发;请求转发(forward)服务器端转发。
最终URL地址不同:请求重定向地址发⽣变化,请求转发地址不发⽣变化。
数据共享不同:请求转发是服务器端实现的,所以整个执行流程中,客户端(浏览器端)只需要发送一次请求,因此整个交互过程中使用的都是同一个 Request 请求对象和一个 Response 响应对象,所以整个请求过程中,请求和返回的数据是共享的;而请求重定向客户端发送两次完全不同的请求,所以两次请求中的数据是不同的。
代码:
// 请求重定向
@RequestMapping("/index")
public String index(){
return "redirect:/index.html";
}
// 请求转发
@RequestMapping("/index2")
public String index2(){
return "forward:/index.html";
}
请求转发运行结果:当返回结果啥都不写,如 return "/index.html";
相当于return "forward:/index.html";
效果是一样的。
请求重定向结果:访问http://localhost:8080/test/index
后,地址变了
具体来说,当一个控制器方法被@ResponseBody注解标记时,Spring会将方法的返回值序列化成HTTP响应的内容,并直接发送给客户端。框架会根据请求的Content-Type和适用的消息转换器将返回值转换为相应的格式,如JSON、XML等。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。