8/30 Spring学习博客
MVC是一种思想 SpringMVC是一种实现

SpringMVC直接请求到Controller
SpringBoot 和SpringMVC 关系?SpringBoot是创建SpringMVC的一种方式
学习Spring web mvc
先要学习
1.建立连接
2.请求
3.响应
(1)建立连接
通过@RequestMapping
@RequestMapping 是Spring Web MVC应用程序中最常被用到的注解之一,它是用来注册接口的路由映射的.
表示服务收到请求时,路径为/sayHi的请求就会调用sayHi这个方法的代码.
路由映射:当用户访问一个URL时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射.
一个项目中有非常多的代码,所有的文件Spring都要去检查下有没有@RequestMapping吗程序,这样工作量太大了,所以需要告知Spirng 哪个有@RequestMapping 通过@RestController
@RequestMapping需要跟@RestController搭配使用
@RequestMapping作用范围
(1)类
(2)方法
当一个类有多个注解时,这个注解没有先后顺序
如果加在了类方法上,还需要加上类路径+方法路径
@RequestMapping("/user")
@RestController
public class UserController{
@RequestMapping(value = "/hello")
public static String hello(){
return "hello";
}

(2)请求
那请求方式是get还是post?
通过浏览器访问基本都是get
post也支持

指定请求方式
public class UserController{
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public static String hello(){
return "hello";
}
注解里双引号的值会赋值给“value”这个属性,多个对多个属性赋值需要写上,属性名,只有一个属性且属性名是value时,可以忽略
这时候我们设置了get 再post就出错了

(1)请求单个参数
@RequestMapping("/r1")
public String r1(String name){
return "接收到参数name :"+name;
}

Spring从参数里面拿到并进行转换
@RequestMapping("/r2")
public String r2(int age){
return "接收到参数age : " +age;
}
假如这时候出现错误

1.先观察HTTP状态码
如果404 确认url是否存在
500 观察后端日志
Optional int parameter 'age' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.
基本类型的默认值是0 不是null
改为
@RequestMapping("/r2")
public String r2(Integer age){
return "接收到参数age : " +age;
}

这时候不会发生错误
那这时候如果传的不是数字

这时候就是 4开头 认为是客户端传了一个错误的参数
(2)传递多个参数
@RequestMapping("/r3")
public String r3(String name,Integer age){
return "接收到参数name :"+name+"接收到参数age : " +age;
}

参数请求,不分先后

同样的多个参数也是如此,那参数过多也不好写,我们就封装成一个对象
@RequestMapping("/r4")
public String r4(UserInfo user){
return user.toString();
}
package com.bite.spring;
public class UserInfo {
private Integer id;
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "UserInfo{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
后端调用后端对象 直接调用r4方法、前端传递对象,Spring简化了开发 我们直接继续传递参数就可以了

这里需要注意:如果我们用对象的话 里面的参数就可以是基本类型的了
对参数进行重命名:
前端传的name 后端想要个username,通过@RequestParam重命名
@RequestMapping("/r5")
public String r5(@RequestParam(value = "name",required = false) String username, Integer age){
return "接收到参数username :"+ username+"接收到参数age : " +age;
}

这里看username和name是不一样的,理论上是拿不到值的,通过这个注解 ,来说明username的值是来自请求中的name,也就是 从请求中获取name的参数,并赋值给username,需要注意到是 加了这个注解 默认这个参数是必传的

如果想改成不是必传的,就加上required=false


传递数组:
@RequestMapping("/r6")
public String r6(String[] arr){
return Arrays.toString(arr)+"length="+arr.length;
}
如何传递数组 后端直接调用方法,对于前端

我们传的时候是一个字符串,那打印出来的数组是不是也是字符串?
我们通过长度来判定,如果是一个字符串长度是1

很明显这里是数组
是spring根据代码区分出来的
第二种传递数组的方式:多个名称一样的参数时,会把它变成一个数组

如何传递集合:
@RequestMapping("/r7")
public String r7(List<String> list){
return list.toString();
}
传递方式和数组一样

No primary or single unique constructor found for interface java.util.List
Spring没有帮我们把这个字符串转化成list
因为Spring默认情况下请求中参数同名的多个值是被封装到数组,如果要封装到集合,要使用@RequestParam绑定参数关系

通过看看list.size() 是不是真的是个list

那如果我们list为null 就会出现空指针异常 所以还要判空。
最后为:
@RequestMapping("/r7")
public String r7(@RequestParam(value = "list",required = false) List<String> list){
if(list!=null){
return list.toString()+"size"+list.size();
}
return "list为空";
}
如何传递JSON数据:
JSON是一种数据格式,本质字符串,主要负责在不同语言中负责数据传递和交换
JSON中两种结构 对象用{},数组用[]

SpringMVC内置了JSON转换工具,可以直接是用来完成JSON字符串和Java对象互转
public class JSONUtils {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
UserInfo userInfo = new UserInfo();
userInfo.setName("zhangsan");
userInfo.setAge(18);
userInfo.setId(12);
//对象转JSON
String s =objectMapper.writeValueAsString(userInfo);
System.out.println(s);
//JSON字符串转换Java对象
UserInfo userInfo1 = objectMapper.readValue(s, UserInfo.class);
System.out.println(userInfo1);
}
}

传递JSON需要借助@RequestBody
@RequestMapping("/r8")
public String r8(@RequestBody UserInfo userInfo){
return userInfo.toString();
}
这时候我们POST一个请求 发现

{
"timestamp": "2026-08-30T06:33:03.347+00:00",
"status": 400,
"error": "Bad Request",
"path": "/user/r8"
}
Required request body is missing:
@RequestBody它表示要从正文里面拿到信息
所以我要改成这样


这样就拿到信息了
jackson拿到json字符串构造对象 是调用无参构造,挨个解析赋值
如何获取URL中参数:

@RequestMapping("/r9/{articleId}")
public String r9(@PathVariable Integer articleId){
return "articleId"+articleId;
}
@PathVariable 这个注解获取路径里的变量,变量用{ }这个包住

变量名字和参数的要一致
多个参数时候 要按照定义的顺序来
@RequestMapping("/r10/{name}/{id}")
public String r10(@PathVariable String name,@PathVariable Integer id){
return "name:"+name+"id:"+id;
}
否则就会

当然他也可以对参数重命名
直接用@PathVariable也可以
@RequestMapping("/r10/{name}/{id}")
public String r10(@PathVariable("name") String UserName,@PathVariable("id") Integer UserId){
return "name:"+UserName+"id:"+UserId;
}
如何上传文件:
通过@RequestPart来获得文件
@RequestMapping("/r11")
public String r11(@RequestPart MultipartFile file){
return "获取上传文件:"+file.getOriginalFilename();
}

那我们获得这个文件后,可以存放
就改为
@RequestMapping("/r11")
public String r11(@RequestPart MultipartFile file) throws IOException {
String fileName=file.getOriginalFilename();
file.transferTo(new File("D:/tmp/"+fileName));
return "获取上传文件:"+file.getOriginalFilename();
}

同样这里也可以参数重命名
到这里 Springmvc的请求的基本操作就学完了
回顾Cookie
HTTP协议自身是属于"无状态”协议.
"无状态”的含义指的是:
默认情况下HTTP协议的客户端和服务器之间的这次通信,和下次通信之间没有直接的联系.
但是实际开发中,我们很多时候是需要知道请求之间的关联关系的.
例如登陆网站成功后,第二次访问的时候服务器就能知道该请求是否是已经登陆过了.

这里的令牌就储存在Cookie字段中
回顾下Session 会话
在计算机领域,会话是一个客户与服务器之间的不中断的请求响应,对客户的每个请求,服务器能够识别出请求来自于同一个客户,当一个未知的客户向Web应用程序发送第一个请求时就开始了一个会话.当客户明确结束会话或服务器在一个时限内没有接受到客户的任何请求时,会话就结束了.

Cookie&Session

学生证可以造假,但是学校教务系统的信息不能造假。
1.用户提供账号和密码,服务器进行验证
2.服务器验证通过,会把信息存储在Session中,把Sessionld返回给客户端 (通过Set-Cookie的方式)
3.客户端收到响应,把sessionlD存储在Cookie中
4.后续的请求中,客户端带着Sessionld去请求(带着Cookie信息去请求)
request.getSession 就是从Cookie中获取Sessionld,并根据Sessionld获取cookie信息
Cookie 和 Session 的区别
1.Cookie是客户端保存用户信息的一种机制.Session是服务器端保存用户信息的一种机制.
2.Cookie 和 Session之间要是通过** Sessionld 关联起来的, SessionId 是 Cookie和 Session之间的桥梁
3.Cookie和Session经常会在一起配合使用**.但是不是必须配合.
。完全可以用Cookie来保存一些数据在客户端.这些数据不一定是用户身份信息,也不一定是Sessionld
。Session中的sessionId 也不需要非得通过Cookie/Set-Cookie 传递,比如通过URL传递.
共同点:都是会话机制
Cookie是客户端机制
Session是服务器机制
如何获取cookie:
通过@CookieValue
@RequestMapping("/request")
@RestController
public class RequestController {
@RequestMapping("/getCookie")
public String getCookie(@CookieValue("test") String test){
return "test:"+test;
}
}

这样子一次不能获取全部cookie,只能想要哪个选哪个
如果想一次性全部获取就只能通过 HttpServletRequest来
@RequestMapping("/getAllCookies")
public String getAllCookies(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie :cookies){
System.out.println(cookie.getName());
}
return "获取到cookie";
}
return "cookie为空";
}

如何获取Session:
同样也有两种写法
先写第一种:因为session不能伪造 所以 我们先创一个session来设置下
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute("userName","zhangsan");
return "设置session成功";
}
然后再获取
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request) {
HttpSession session = request.getSession();
String userName = (String)session.getAttribute("userName");
return "登录用户"+userName;
}


第二种
@RequestMapping("getSession2")
public String getSession2(HttpSession session){
String userName = (String)session.getAttribute("userName");
return "登录用户"+userName;
}
HttpSession这也是个内置对象

第三种
@RequestMapping("getSession3")
public String getSession2(@SessionAttribute("userName") String userName){
return "登录用户"+userName;
}
第三种最简便 但是不同于前两个 他不会自动创建Session Session不存在时会报错
如果确定 Session 中一定有该属性:用方式三 @SessionAttribute,最优雅
如果属性可能不存在,需要兜底处理:用方式一或二,或者方式三加 required = false + 判空
上述用内置对象最传统、最通用

浙公网安备 33010602011771号