当前位置: 首页 > news >正文

详解Spring MVC

  前言👀~

上一章我们介绍了JavaEE进阶的一些基础知识点,今天来讲解在Spring中的一个重要知识点Spring Web MVC,看完学不会Spring MVC来揍我

什么是 MVC?

什么是SpringWeb?

什么是 Spring Web MVC?

学习Spring MVC

1.建立连接

2.请求

1.传递单个参数

2.传递多个参数

3.传递对象

后端参数重命名

4.传递数组/集合

5.传递JSON数据(重要)

6.获取URL中的参数

7.上传文件

8.Cookie和Session

Session

Cookie和Session的区别

9.获取Cookie

10.获取Session

11.获取Header

3.响应

1.返回静态页面

2.返回数据

3.返回html代码片段

4.返回JSON

5.设置状态码

6.设置Header

开发中程序报错,如何定位问题?

lombok工具包

应⽤分层

软件设计原则

Spring全家桶总结

Spring

SpringBoot

SpringWeb

Spring MVC


如果各位对文章的内容感兴趣的话,请点点小赞,关注一手不迷路,讲解的内容我会搭配我的理解用我自己的话去解释如果有什么问题的话,欢迎各位评论纠正 🤞🤞🤞

47497722484f4d519a7e014f8100ec05.png

个人主页:N_0050-CSDN博客

相关专栏:java SE_N_0050的博客-CSDN博客  java数据结构_N_0050的博客-CSDN博客  java EE_N_0050的博客-CSDN博客


什么是 MVC?

MVC 就是 Model View Controller 的缩写,属于一种软件架构设计模式一种思想,把我们的项目分为控制器(Controller)、模型(Model)、视图(view)三个部分model就是处理业务逻辑处理数据的controller就是接受请求丢给对应的model进行处理的view就是展示数据的也就是界面

举个例子:如果客户来公司要做一个软件先问前台view,然后前台知道后跟它说去某部门controller,然后某部门在把这个人带给对应的负责人啊等等去进行处理沟通也就是我们的model,最后结果原路返回。注意一下MVC 和 Spring  MVC还是有点区别的

什么是SpringWeb?

Spring Web是Spring框架中专注于Web应用开发的部分,包含了Spring MVC及其他Web相关的功能。我们使用Spring框架来开发web网站,在创建一个Spring Boot项目的时候在加依赖的时候我们会选择Spring Web,其实也就是Spring MVC依赖

什么是 Spring Web MVC?

Spring Web MVC是基于Servlet API构建的一个web框架,一开始在Spring框架中,正式名叫Spring Web MVC。MVC是一种思想,Spring对其进行了实现称为Spring MVC,通常我们叫的Spring MVC也就是Spring Web MVC,都是用于构建web应用。Spring MVC是对MVC思想的具体实现,此外Spring MVC还是一个web框架

上个文章中我们在创建Spring Boot项目的时候其实我们就涉及到了Spring MVCSpring Boot是创建Spring MVC项目的一种方式,也可以通过其他方式创建Spring MVC项目,只要包含了web这个模块,我们就可以认为这是一个Spring MVC项目。一个项目可能是Spring Boot项目也可能是Spring MVC项目,Spring Boot是帮助我们快速搭建项目的,Spring MVC是其中的一个模块

此时Spring MVC整个流程是如下图所示

浏览器发送请求由我们的controller进行接收用户的请求,然后将请求传给对应的model进行处理,接着model进行处理后返回给controller,controller再把处理的结果传给view,注意这里view和MVC返回的还是有区别的之前返回的是视图现在返回的是视图所需要的数据,把这个返回的数据认为是view

总结来说,Spring MVC 是⼀个实现了 MVC 模式的 Web 框架


学习Spring MVC

如何通过浏览器和服务器进⾏交互?

1.建立连接

使用 @RequestMapping 注解来实现 URL 路由映射,此时浏览器和服务器就建立了连接,英文翻译也可以按这样理解请求映射

什么是路由映射呢?

用户访问⼀个 URL 时, 将用户的请求对应到程序中某个类的某个⽅法的过程就叫路由映射

@RequestMapping就类似一个门牌号可修饰方法也可修饰类修饰方法时如果类没有修饰的话我们可以直接通过你在RequestMapping中写的路径搭配上URL进行访问如果是修饰了类也修饰了方法,此时访问地址为URL+类的路径+方法路径就是都要写上。建议都修饰并且建议路径名最好和方法名一样

@RequestMapping既支持get请求也支持post请求,比较全能支持很多请求,并且可以限制请求方式使用method属性下面使用postman进行演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m1")public String m1() {return "Hello RequestMapping";}
}

GET请求演示

POST请求演示

限制请求后,如果没有使用指定的请求方式会报405表示请求的方式错误!!下面限制为GET请求

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping(value = "/m1", method = RequestMethod.GET)public String m1() {return "Hello RequestMapping";}
}

补充:如果类加了注解@RestControllerSpring才会去看这个类里面的方法有没有加 @RequestMapping 这个注解这只是简单理解后面就会明白什么意思了

Postman下载链接:https://www.filehorse.com/download-postman/68966/


2.请求

访问不同的路径, 就是发送不同的请求。在发送请求时,可能会带⼀些参数,所以学习Spring的请求,主要是学习如何传递参数到后端以及后端如何接收

请求主要是学习如何传参大白话就是前端的参数传入后端进行处理,处理后返回一个响应。我们可以使用postman工具进行校验,不限这个工具。不管使用哪种方式发送请求,对于我们后端来说没啥区别,我们就像厨师,管你客户是桌上二维码下单还是叫服务员点单,我们都还是一样的做法,我们只要负责接收订单即可

1.传递单个参数

传参数的时候我们在URL中应该这样写,http://127.0.0.1:8080/method/m2在m2后面加上?参数名=你要参的参数,下面会进行演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m2")public String m2(String name) {return "接收到的名字:" + name;}
}

注意:参数名需要一样,参数顺序不一样没事。以及还要注意如果参数类型是基本数据类型的话必须要传值不然会报错!!!,所以在开发时建议使用包装类,它可以区分0和null。下面进行演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m2")public String m2(int id) {return "接收到的id:" + id;}
}

然后是使用包装类型,下面进行演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m2")public String m2(Integer id) {return "接收到的id:" + id;}
}


2.传递多个参数

下面直接进行演示,和传递单个参数差不多,只是参数的个数增加了,唯一注意的是参数之间使用&这个符号拼接

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m2")public String m2(Integer id, String name) {return "接收到的id:" + id + " " + "接收到的名字:" + name;}

注意:还是一样如果使用基本数据类型不传参会报错,参数的顺序可以调换不会报错


3.传递对象

开发中,接口的参数通常都定义为对象,高内聚低耦合,参数多了封装在一个对象中进行传递代码看起来优雅并且高内聚低耦合

先创建一个对象,属性如下

public class Student {private Integer id;private String name;private String sexy;
}

接着传递对象,我们看看效果

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(Student student) {return "接收到的Student:" + student;}
}


后端参数重命名

@RequestParam("参数名"),通过这个注解进⾏参数重命名注意这个参数是必传参数!并且如果后端进行了重命名,还是必须使用@RequestParam注解里的参数名返回,注意无论是否改了名字,在URL中还是要写@RequestParam注解里的参数名传递值

下面代码中把name赋值给这个userName,name属于前端传来的参数,userName属于后端的参数

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(@RequestParam("name") String userName) {return "接收到的名字:" + userName;}
}

注意看参数名!

如果你不按@RequestParam注解里的参数名传递值,看下面的效果

但是我们可以手动设置参数不是必传参数@RequestParam(value = "name", required = false,默认是true代表name是必传参数请求中必须包含它这样写了之后就不是必传参数,是可选的,下面进行演示,即使不传或者使用后端参数名称都没事

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(@RequestParam(value = "name", required = false) String userName) {return "接收到的名字:" + userName;}
}


4.传递数组/集合

默认情况下,当我们请求中有同类型多个参数的时候,浏览器会帮我们封装成一个数组如果要封装到集合,要使⽤@RequestParam 绑定参数关系

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(String[] name) {return "接收到的名字:" + Arrays.toString(name);}
}

补充:参数之间还可以使用逗号分割,使用的是Chrome浏览器会自动进行转码urlencode

接下来是传递集合的演示,首先是错误演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(List<String> name) {return "接收到的名字:" + name;}
}

正确的应该使用@RequestParam 绑定参数关系,下面是演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(@RequestParam List<String> name) {return "接收到的名字:" + name;}
}

补充:@GetMapping注解是@RequestMapping的一个特化形式,专门用于处理GET请求@PostMapping同样是@RequestMapping的一个特化形式,专门用于处理POST请求,这两者主要是用于简化代码和提高可读性,日常工作中也比较少用,用的多的还是@RequestMapping

上述传递参数扩展性差(除了传递对象),需求一变,就需要改接口的定义。我们常说的接口指API(和interface不是一个东西),然后应用程序提供了哪些服务,接口对应到代码上,通常是指方法,注意是通常所以接口也可以指一个类接口可以理解为客户端和服务器的一个约定如果一端变另外一端也要变


5.传递JSON数据(重要)

JSON就是⼀种数据格式,使⽤⽂本表示一个对象或数组的信息本质是一个字符串(不是一个普通的字符串)表示对象的字符串,通常称为JSON字符串,JSON字符串和对象是可以进行互相转换的JSON负责在不同的语⾔中数据传递和交换,在工作中或写项目用的最多!

传递JSON数据,下面是演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(Student student) {return "接收到的Student:" + student.toString();}
}

注意JSON数据要像下面这样传!输出结果如下,全是null没接收到?

使用fiddler观察,会发现请求参数在请求正文中,为什么全是null?请求中的请求参数默认是key-value型,根据key进行匹配

接收JSON对象, 需要使用 @RequestBody 注解使得Spring MVC能够将客户端发送的请求正文中的数据自动映射到Java对象上大白话就是使用这个注解接收请求会将请求正文中的数据转为java对象

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(@RequestBody Student student) {return "接收到的Student:" + student.toString();}
}

注意:客户端的请求参数必须放在请求正文中,而不是URL或请求头中@RequestBody注解通常用于方法参数上,而不是方法本身,所以你可以将请求正文中的数据绑定到方法参数上,而不是整个方法


6.获取URL中的参数

使用@PathVariable获取URL中的参数,可获取一个也可获取多个

此时我们在 @RequestMapping("m3/{参数名}"),应该这样写,一对花括号+参数名

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3/{name}")public String m3(@PathVariable String name) {return "接收到的名字:" + name;}
}

可以获取URL中的多个参数注意获取多个参数的时候,请求格式必须和后端定义的URL格式匹配例如后端定义的URL格式有两个参数你请求中也得带两个参数不能只带一个参数不然会报错

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3/{id}/{name}")public String m3(@PathVariable Integer id, @PathVariable String name) {return "接收到的id:" + id + " " + "接收到的名字:" + name;}
}

 可以重命名,但是括号里的参数要一致!!!

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3/{id}/{name}")public String m3(@PathVariable(value = "id") Integer MyId, @PathVariable(value = "name") String UserName) {return "接收到的id:" + MyId + " " + "接收到的名字:" + UserName;}
}


7.上传文件

使用@RequestPart("参数名")注解上传文件

使用postman可以上传文件,记得键也要写参数!

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(@RequestPart MultipartFile file) {return "接收到的文件名:" + file.getOriginalFilename();}
}

搭配file.transferTo方法可以将文件上传到指定路径file.transferTo(new File("E:/Nan/" + file.getOriginalFilename()))。这里是写死的固定的,注意要带上文件名 

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m3")public String m3(@RequestPart MultipartFile file) throws IOException {file.transferTo(new File("E:/" + file.getOriginalFilename()));return "success";}
}


8.Cookie和Session


为什么要有Cookie和Session?

如果没有Cookie和Session的话,例如在登录的时候需要发送账号和密码给后端进行校验,校验成功返回账号和密码维持登录的状态信息,后续用户在请求任何页面的时候都要带上账号和密码,这样做又不安全又很麻烦。所以需要使用Cookie和Session来帮助客户端和服务器之间维持状态信息

"无状态" 的含义指的是:默认情况下 HTTP 协议的客户端和服务器之间的这次通信, 和下次通信之间没有直接的联系,可以理解为渣男的意思玩一次就不认识了

首先我们知道HTTP 协议⾃⾝是属于 "⽆状态" 协议,但是在实际开发很多时候我们是需要知道请求之间的关联关系的,我们需要服务器能够识别用户登录后发起的下一次请求和之前的请求有没有关联关系,所以我们可以使用cookie在用户登录过后,服务器返回一些用户相关的数据,然后浏览器将这些数据保存在本地,后续所有的请求会自动带上cookie服务器就能识别了这样就能维持用户的登录状态,好比"校园码"一样。Cookie是存储在浏览器的,并且Cookie是可以篡改的,然后就是服务器进行重启浏览器中的Cookie还是依然存在的

Session

服务器同⼀时刻收到的请求是很多的, 服务器需要清楚的区分每个请求是从属于哪个用户,也就是属于哪个会话(会话就好比我们在购物时和客服进行沟通的时候,如果一段时间没沟通就会提示你很久没有后续的回复将断开本次的连接了,不同用户在和客服进行沟通的时候都会建立一个会话),就需要在服务器这边记录每个会话以及与用户的信息的对应关系Session是服务器为了保存用户信息⽽创建的⼀个特殊的对象默认情况Session是保存在内存的,所以重启服务器后Session数据就丢失了。并且Session可以保存对象

Session的本质就是⼀个 "哈希表", 存储了⼀些键值对结构,Key 就是SessionID,Value 就是用户信息SessionID是由服务器生成的一个"唯一性字符串",Session 机制的⻆度来看这个"唯一性字符串"可以称为SessionID,但是站在整个登录流程中看,这个"唯一性字符串"称为"token"

流程:

1. 用户发起登陆请求把账号密码传到服务器,服务器验证成功后在 Session 中新增⼀个新记录(存入当前用户信息),并把 sessionId返回给客户端(通过HTTP 响应中(响应头)的 Set-Cookie 字段返回),然后客户端会自动在cookie当中存入当前的sessionId

2. 客户端后续再给服务器发送请求的时候会在请求中(请求头)自动带 sessionId(通过 HTTP 请求中的Cookie 字段带上)

3. 服务器收到请求之后,根据请求中的 sessionId在 Session 信息中获取到对应的用户信息,再进行后续操作,找不到则重新创建Session,并把SessionID返回

Cookie和Session的区别

1.Cookie是客户端保存用户信息的一种机制,Session是服务器端保存用户信息的一种的机制,所以Cookie安全性不如Session,因为Cookie存储在客户端用户可以进行篡改。通常情况两者会搭配使用,但不是必须

2.Cookie 和 Session之间主要是通过 SessionId 关联起来的,SessionId 是 Cookie 和 Session 之间的桥梁

3.Session容量比Cookie 大,所以比较占用服务器内存资源,需要依赖cookie,并且分布式以及前后端分离的架构下会有跨域问题,比如有两台服务器用户发起一个登录请求到随机一个服务器,此时这台服务器创建了session保存了用户信息,然后用户又发起一个请求到了另外一个服务器,可是这个服务器没有保存刚才用户的信息


9.获取Cookie

通过HttpServletRequest 和HttpServletResponse获取根据需要处理的业务逻辑,如果只需要读取请求数据只写前面一个即可如果同时接收请求和响应参数,那就都写

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m5")public Boolean m5(HttpServletRequest request) {Cookie[] cookies = request.getCookies();if (cookies != null) {Arrays.stream(cookies).forEach(cookie -> System.out.println(cookie.getName() + cookie.getValue()));return true;}return false;}
}

伪造Cookie

输出结果


通过注解方式获取Cookie

使用@CookieValue("cookie的名称")必须指定cookie的名称!!!不指定的话,在你参数列表写的时候也要和你想要获取的cookie的名称一样。并且这个注解只一个一个获取cookie,选择哪个方法呢?根据需求决定如果一次要拿多个cookie选上面那个,反之选这个。实际还是上面用多些

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m6")public String m6(@CookieValue String kunkun) {return "获取到的cookie:" + kunkun;}
}

获取多个cookie

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m6")public String m6(@CookieValue String kunkun, @CookieValue String qiange) {return "获取到的cookie1:" + kunkun + " " + "获取到的cookie2:" + qiange;}
}


10.获取Session

HttpServletRequest中的getSession方法默认值是true,如果没有Session 会给你创建一个SessiongetSession方法就是根据sessionId拿到Session对象类似根据学号拿到学生的所有信息

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m7")public Boolean m7(HttpServletRequest request) {HttpSession session = request.getSession();if (session != null) {System.out.println(session);return true;}return false;}
}

接下来我们将getSession方法默认值改为false

    @RequestMapping("/m7")public String m7(HttpServletRequest request) {HttpSession session = request.getSession(false);if (session != null) {String userName = (String) request.getAttribute("userName");return "登录用户:" + userName;}return "session为空";}

我们手动设置一下session,客户端发起请求后,服务器返回的响应中带有Set-Cookie字段

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/setSession")public String setSession(HttpServletRequest request) {HttpSession session = request.getSession();session.setAttribute("userName", "坤坤");return "success";}
}

我们再去获取一下,看看效果

 设置后再次发起请求会自动带上cookie(包含sessionid),我们通过fiddle观察


通过注解方式获取Session

通过注解方式获取session有两种方法获取session,一种是通过@SessionAttribute注解(只能一个一个获取Session)一种是通过Spring MVC内置对象HttpSession 来获取

通过@SessionAttribute注解获取Session,此时这个参数是必传参数,和@RequestParam一样,不传就会报错如果没有session会报错因为是必传参数,以及这个参数名和设置session.setAttribute中的名要一样,下图中的userName,下面进行演示

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m9")public String m9(@SessionAttribute("userName") String userName) {return "登录用户:" + userName;}
}

我们设置session后再去获取,看看效果

    @RequestMapping("/setSession")public String setSession(HttpServletRequest request) {HttpSession session = request.getSession();session.setAttribute("userName", "坤坤");return "success";}

我们也可以设置不是必传参数把required改成false即可设置后就不是必传参数了,即使没有session也不会报错,下面看看效果

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m9")public String m9(@SessionAttribute(value = "userName", required = false) String userName) {return "登录用户:" + userName;}
}

我们还可以通过Spring MVC内置对象HttpSession 来获取Session,下面这段代码等同于HttpSession session = request.getSession();注意先设置session再获取,先演示不设置的效果

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m10")public String m10(HttpSession session) {String userName = (String) session.getAttribute("userName");return "登录坤户:" + userName;}
}

效果和HttpSession session = request.getSession();一样如果没有Session会给你设置创建一个Session,接着演示我们手动设置session再获取(写一个方法)

    @RequestMapping("/setSession")public String setSession(HttpServletRequest request) {HttpSession session = request.getSession();session.setAttribute("userName", "坤坤");return "success";}


11.获取Header

我们可以通过HttpServletRequest去获取Header中的一些信息,例如userAgent、host等等都可以获取

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m11")public String m11(HttpServletRequest request) {String userAgent = request.getHeader("User-Agent");return "获取到的User-Agent:" + userAgent;}
}

效果如下

还可以通过注解@RequestHeader("输入你要获取Header中的哪个属性")获取Header中的属性注意括号里的值要和HTTP请求中的值对应!

@RequestMapping("/method")
@RestController
public class DemoController {@RequestMapping("/m11")public String m11(@RequestHeader("User-Agent") String userAgent) {return "通过注解获取到的User-Agent:" + userAgent;}
}

效果如下


3.响应

前⾯的代码中,其实都已经设置了响应数据Http响应结果可以是数据,也可以是静态⻚⾯,也可以针对响应设置状态码,Header信息等

1.返回静态页面

如果我们使用@RestController注解去获取静态页面的时候会出现如下图的效果

@RequestMapping("/return")
@RestController
public class Demo2Controller {@RequestMapping("/login")public String login() {return "/index.html";}
}

返回的内容是一个字符串

我们试试把@RestController注解换成@Controller注解

@RequestMapping("/return")
@Controller
public class Demo2Controller {@RequestMapping("/login")public String login() {return "/index.html";}
}

效果如下,会返回一个我们预取的内容,也就是一个静态页面


@RestController 和 @Controller 有着什么样的关联和区别呢?

@RestController 和 @Controller两者都是类注解!下面是@RestController 注解的源码

看看@RestController 注解的源码中前三个注解称为元注解简单理解为可以被其他注解使用的注解叫元注解({ElementType.TYPE})TYPE表示这个注解可以修饰类具体修饰什么由@Target决定@Retention(RetentionPolicy.RUNTIME)表示注解的生命周期其中@RestController 注解包含@Controller注解@Controller注解大白话就是告诉Spring帮我们管理代码后续我们访问时才能访问到,就类似报补习班后老师对你负责一样加上这个注解就代表你报名了。准确来说是返回视图随着开发流行"前后端分离"模式,所以MVC的概念也逐渐发⽣了变化View不再返回视图⽽是返回显示视图时需要的数据(也就是前端所需要的数据),所以我们可以通过@ResponseBody注解 修饰类或方法返回数据


返回一个静态页面,下面这两个代码作用一模一样@RestController就包含@Controller和@ResponseBody。并且当存在多个注解,注解的顺序谁写谁写后没有什么关系这里返回的是数据,不是视图,除非去掉@ResponseBody或只使用@Controller

@RequestMapping("/return")
@RestController
public class Demo2Controller {@RequestMapping("/login")public String login() {return "/index.html";}
}
@RequestMapping("/return")
@Controller
@ResponseBody
public class Demo2Controller {@RequestMapping("/login")public String login() {return "/index.html";}
}

 总结:所以如果只需要返回视图就使用@Controller 注解即可如果使用@RestController 注解的话修饰类的话,这个类中所有的方法全部返回数据


补充:看看@RequestMapping注解的源码中可以看到@Target({ElementType.TYPE, ElementType.METHOD})表示这个注解可以修饰类也可以修饰接口也可修饰方法


2.返回数据

通过@ResponseBody注解返回数据前面写的代码其实都使用到这个注解去返回数据了因为使用到了@RequestMapping 注解@ResponseBody这个注解可以修饰类也可以修饰方法,在源码里可以看到@Target({ElementType.TYPE, ElementType.METHOD})这个注解修饰类的话表示这个类中的所有方法,返回的都是数据修饰方法的话表示这个方法返回的是数据所以如果一个类中的所有方法都是返回数据,直接把这个@ResponseBody注解写在类上

返回数据,如果没有这个@ResponseBody注解,使用@Controller注解就会报404的错误表示资源找不到

@RequestMapping("/method")
@Controller
public class Demo2Controller {@RequestMapping("/m1")public String m1() {return "视图所需的数据";}
}

正确的应该加上@ResponseBody注解,返回才是数据

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping("/m1")public String m1() {return "视图所需的数据";}
}


3.返回html代码片段

如果数据中带有html代码也可以通过@ResponseBody注解返回它会被浏览器解析右键网页查看源代码就知道了这用的很少

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping("/returnHtml")public String returnHtml() {return "<h1>返回html代码片段</h1>";}
}


4.返回JSON

返回JSON数据格式也可以使用@ResponseBody注解当我们的接口返回的是String时,content-type是text/plain当我们的接口返回的是对象时content-type自动设置为application/json当返回的数据是一个对象时会被自动封装成JSON数据格式

观察下面的返回类型,首先返回String类型

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping("/m2")public String m2() {return "success";}
}

返回一个对象,看看效果,会自动转为JSON数据格式

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping("/m3")public Student m3() {Student student = new Student();student.setId(1);student.setName("kun");student.setSexy("男");return student;}
}

返回一个Map,看看效果,也会自动转为JSON数据格式

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping("/m5")public Map<String, String> m5() {HashMap<String, String> map = new HashMap<>();map.put("1", "kun");map.put("2", "ji");return map;}
}


5.设置状态码

我们可以通过HttpServletResponse设置状态码

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping("/m6")public String m6(HttpServletResponse response) {response.setStatus(401);return "设置状态码";}
}

虽然我们把状态码设置成了401,但是状态码不影响页面的展示返回的数据还是照常返回根据你设置的返回注意这里是HTTP状态码不是业务状态码因为我们使用的这个HttpServletResponse接口是servlet提供的,所以设置是HTTP状态码如果想设置业务状态码,我们是在业务类进行设置的即使我们设置了401它还是返回数据了,也可以使用fiddler观察


6.设置Header

响应部分的Header用的比较少但是也有使用的场景例如鉴权,检查你是否有权限访问,对身份进行识别。我们通过@RequestMapping注解的属性来实现

@RequestMapping源码解释

补充:Consumes就是你发送过来请求的数据类型得和我这边指定的一样才会处理produces就是设置返回的数据格式

没指定返回的格式类型,就像下面这样

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping("/m2")public String m2() {return "success";}
}

设置Content-Type(指定返回的格式类型)

这块的话了解即可,Spring MVC会根据返回结果判断,然后匹配对应的数据格式类型

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping(value = "/m7", produces = "application/json;charset=utf-8")public String m7() {return "设置Content-Type";}
}

设置其他Header,效果如下在我们响应中会多了一个字段

@RequestMapping("/return")
@Controller
public class Demo2Controller {@ResponseBody@RequestMapping(value = "/m7")public String m7(HttpServletResponse response) {response.setHeader("MyHeader", "MyHeader");return "设置Header";}
}


开发中程序报错,如何定位问题?

先定位是前端问题还是后端问题,前端通过F12看控制台,后端通过接口看控制台日志,还可以通过抓包

1.通过打印日志,通常写在方法的第一行方便观察,如果没输出说明请求都没有到后端,这个方法前后端都通用

2.测试接口,如果没问题那问题就是出在前端了,下图是测试接口

3.如果代码改了没生效,可能是缓存的原因,清除一下,前后端都清除一下


lombok工具包

Lombok是⼀个Java⼯具库,通过添加注解的⽅式,简化Java的开发可以使用@Data注解省去写get和set方法

先引入依赖

 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
@Data
public class Student {private Integer id;private String name;private String sexy;
}

如果有些属性不想 被获取到或被设置就对想被获取到的属性加上@Getter注解/@Setter注解即可,不想要的不添加即可,颜色就是灰色的

public class Student {@Setter@Getterprivate Integer id;@Getter@Setterprivate String name;private String sexy;
}

Java程序运行原理

lombok在其中的作用

以下是lombok提供的注解

@Data注解包含了以下很多注解,@Data = @Getter + @Setter + @ToString + @EqualsAndHashCode +@RequiredArgsConstructor+@NoArgsConstructor


应⽤分层

程序的代码有点"杂乱的时候,我们通过分层使代码更加规范以及方便管理类似TCP/IP网络五层网络模型一样进行分层,分为应用层、传输层、网络层等上面的MVC也用到了分层的思想,但现在更流行这种分层⽅式称之为"三层架构"

三层架构

1.表现层:接收请求,返回结果

2.业务逻辑层:主要处理业务逻辑,对业务的具体实现

3.数据层:处理和存储和管理与应⽤程序相关的数据

上述三个部分在Spring中的实现,都有体现有对应的

Controller:控制层接收前端发来的请求,并且验证参数是否合法,然后响应处理后的结果

Service:业务逻辑层处理具体的业务逻辑,真正干活的部分

Dao:数据访问层也称持久层负责数据访问操作,包括数据的增、删、改、查


MVC 和三层架构的区别和联系

现在说Spring MVC还是说Spring Web更合适些Spring MVC就是用来开发web功能也就是做网站,要做网站也就是需要MVC这个模块。Spring MVC之前的实现其实类似面试,首先hr(controller)接待我们,然后交给相关部门负责人(model)进行面试,然后面试完后把面试结果告诉hr),接着hr通过邮箱电话等方式(view)告诉我们,现在MVC可以理解为没有view视图了只做controller、model、dao也就是三层架构

有人认为三层架构是MVC模式的⼀种实现,也有⼈认为MVC是三层架构的替代⽅案,根据自己的理解去说即可,从概念上看两者都是软件⼯程领域中的架构模式MVC中,视图(View)和控制器(Controller)合起来对应三层架构中的表现层,模型(Model)对应三层架构中的业务逻辑层,数据层,以及实体类

MVC强调的是数据和视图分离,将数据展示和数据处理分开,通过控制器对两者进行组合。三层架构强调不同维度数据处理的高内聚和低耦合将交互界面,业务处理和数据库操作的逻辑分开

两者的目的是相同的,都是"解耦,分层,代码复⽤"并且在项目中两者也可以结合起来使用,最终的目的都是一样的,取决于你怎么想的怎么看的


软件设计原则

高内聚低耦合,这个原则讲过讲了高内聚强调的是一个模块间紧密联系共同完成一个功能低耦合强调的是模块和模块之间的依赖关系越低越好,低但是不代表没有。高内聚好比一个班级的学生互相帮助,低耦合好比举办一个运动会我们班不参加,运动会还是照常开不至于不开了


注解总结:

1. @RequestMapping: 路由映射2. @RequestParam: 后端参数重命名3. @RequestBody: 接收JSON类型的参数4. @PathVariable: 接收路径参数5. @RequestPart: 上传⽂件6. @ResponseBody: 返回数据7. @CookieValue: 从Cookie中获取值8. @SessionAttribute: 从Session中获取值9. @RequestHeader: 从Header中获取值10. @Controller: 定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理. 默认返回
视图11. @RestController: @ResponseBody + @Controller 返回数据

Spring全家桶总结

Spring

Spring是一个框架,最开始写起来还是有点复杂,虽然帮我们解决了一些工作使我们日常开发中得到一些便利,但还是复杂,复杂的地方在于有很多的配置文件。Spring最初使用大量XML配置文件,这使得配置变得相当复杂。后续Spring引入了Java注解和基于Java的配置来简化这一过程

SpringBoot

SpringBoot的出现让我们更方便的创建Spring项目,并且进一步简化配置过程通过自动配置和starter依赖减少了大量的手动配置工作,帮助开发人员快速集成各种框架和库。SpringBoot中集成了很多框架,在创建的时候可以根据业务去进行挑选,但是注意创建SpringBoot项目的时候左侧能选择的和SpringBoot没有任何关系它们的关系是在使用SpringBoot创建这些项目的时候会更简单些SpringBoot本身就帮我们引入很多东西/框架,在写内容的时候会简单很多,帮助我们快速进行Spring开发,也就是能快速的开发一个程序了

SpringWeb

Spring Web是Spring框架中专注于Web应用开发的部分包含了Spring MVC及其他Web相关的功能

Spring MVC

Spring MVC是Spring框架的一个模块,用于创建基于MVC架构的Web应用程序。你也可以说是一个框架也可以是一个模块,很大的模块大到能自己独立成为一个框架,可以认为是一个web模块用来开发web它和SpringBoot没有太大的关系只是采用SpringBoot创建的SpringMVC项目Spring Boot本身不提供Web开发功能,但它能简化Spring MVC项目的设置和配置Spring Boot提供的“starter”依赖项(如spring-boot-starter-web)包含了Spring MVC的核心功能。但是创建SpringMVC的方式有很多我们采用SpringBoot创建,其他的也都过时了。

@RequestMapping注解就是Spring MVC的体现,也就是用于web功能,所以说Spring MVC是一个Web框架

总结:Spring是一个大型框架为了更快的写java程序Spring Boot是为了简化Spring应用开发而设计的工具为了更快的写Spring程序Spring MVC和Spring Web(MVC)则是专注于Web应用的模块和功能

以上便是本章Spring MVC的所有内容,知识点多且重要,好好消化,我们下一章再见💕

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 开源BaaS 平台介绍
  • STM32——SSD1306驱动的OLED(I2C)
  • go语言设置定时任务
  • 居住证申报系统小程序的设计
  • H7-TOOL混合脱机烧录以及1拖4不同的通道烧录不同的程序操作说明(2024-08-07)
  • 江协科技STM32学习笔记(第10章 SPI通信)
  • Redis主从哨兵模式
  • Web开发中的Cookie、Session与Token:一场身份认证之旅
  • 日期类代码实现-C++
  • windows关闭英语美式键盘
  • conda配置国内源
  • Python | Leetcode Python题解之第334题递增的三元子序列
  • c语言中比较特殊的输入函数
  • 基于Mediepipe的手势识别系统 | OpenCV | Mediapipe | C++ | QT | Python | C# | Unity
  • Doris与StarRocks
  • @jsonView过滤属性
  • 0x05 Python数据分析,Anaconda八斩刀
  • gf框架之分页模块(五) - 自定义分页
  • Intervention/image 图片处理扩展包的安装和使用
  • Joomla 2.x, 3.x useful code cheatsheet
  • js对象的深浅拷贝
  • Leetcode 27 Remove Element
  • PAT A1050
  • Python 基础起步 (十) 什么叫函数?
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 少走弯路,给Java 1~5 年程序员的建议
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 我的面试准备过程--容器(更新中)
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • 移动端高清、多屏适配方案
  • ​【已解决】npm install​卡主不动的情况
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • ## 1.3.Git命令
  • ## 基础知识
  • #vue3 实现前端下载excel文件模板功能
  • #进阶:轻量级ORM框架Dapper的使用教程与原理详解
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • (1)Jupyter Notebook 下载及安装
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (分布式缓存)Redis哨兵
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (十三)Flink SQL
  • (自用)gtest单元测试
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • .gitattributes 文件
  • .net core 管理用户机密
  • .net MySql
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .net和php怎么连接,php和apache之间如何连接
  • .NET开源、简单、实用的数据库文档生成工具
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?