8/30 Spring学习博客

MVC是一种思想 SpringMVC是一种实现

29474ea776848ee0a507202c710f165e

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";
    }

9dc84fd1f2a2dcdc1a80125cfc843cf0

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

d6e5bd7af0707a5bc2736acaa0b75328

指定请求方式

public class UserController{
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public static String hello(){
        return "hello";
    }

注解里双引号的值会赋值给“value”这个属性,多个对多个属性赋值需要写上,属性名,只有一个属性且属性名是value时,可以忽略

这时候我们设置了get 再post就出错了
686e187de8df292b2d36d4f4b98e6d5d

(1)请求单个参数

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

5d151a55caeaa4eb47eadcf730f5e269

Spring从参数里面拿到并进行转换

    @RequestMapping("/r2")
    public String r2(int age){
        return "接收到参数age : " +age;
    }

假如这时候出现错误
785b8f5953534e6f29a2c0957879fad3

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;
    }

9b1a7fa4cd416dc7e12b26026d7a64e7

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

ea82ca318a48d2f74e6b33b1b5cb930c
这时候就是 4开头 认为是客户端传了一个错误的参数

(2)传递多个参数

    @RequestMapping("/r3")
    public String r3(String name,Integer age){
        return "接收到参数name :"+name+"接收到参数age : " +age;
    }

c1b5e29f4e5d463704431357b5ef3bc6

参数请求,不分先后

13abe04fbb259b969f693c7b1b8d9eff

同样的多个参数也是如此,那参数过多也不好写,我们就封装成一个对象

    @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简化了开发 我们直接继续传递参数就可以了

9389c0aa965152025c472024c35575ce

这里需要注意:如果我们用对象的话 里面的参数就可以是基本类型的

对参数进行重命名:
前端传的name 后端想要个username,通过@RequestParam重命名

    @RequestMapping("/r5")
    public String r5(@RequestParam(value = "name",required = false) String username, Integer age){
        return "接收到参数username :"+ username+"接收到参数age : " +age;
    }

96f4bdc2239bfffcbd672441a9f0d1d9

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

83092d85128e35f9a48ca602110fdbfb

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

13f792a075b76013f427b1c0dacf4bc9

传递数组:

    @RequestMapping("/r6")
    public String r6(String[] arr){
        return Arrays.toString(arr)+"length="+arr.length;
    }

如何传递数组 后端直接调用方法,对于前端
d71c0571dca0ad6a5cb9b096a6eca7c6

我们传的时候是一个字符串,那打印出来的数组是不是也是字符串?

我们通过长度来判定,如果是一个字符串长度是1

195f6679de00055dc879040bd4820de8

很明显这里是数组

是spring根据代码区分出来的

第二种传递数组的方式:多个名称一样的参数时,会把它变成一个数组
f89c9fb946ccff17ac33d8335b391d77

如何传递集合:

    @RequestMapping("/r7")
    public String r7(List<String> list){   
            return list.toString();
    }

传递方式和数组一样
93269614337fc18aa282bb9b44452b6a

No primary or single unique constructor found for interface java.util.List

Spring没有帮我们把这个字符串转化成list

因为Spring默认情况下请求中参数同名的多个值是被封装到数组如果要封装到集合,要使用@RequestParam绑定参数关系
4d12a4f172861e85dfe4c2584c770324

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

5c7ad7ecc981ce850fdfef8aa576851f

那如果我们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中两种结构 对象用{},数组用[]
ac290b77009974bad3b4b62d73dcd8e4

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);

    }
}

ea3c7cd80bd4add88965b8cf64a06865

传递JSON需要借助@RequestBody

@RequestMapping("/r8")
    public String r8(@RequestBody UserInfo userInfo){
        return userInfo.toString();
    }

这时候我们POST一个请求 发现
707e56b15e49902dee29265e765d038d

{
"timestamp": "2026-08-30T06:33:03.347+00:00",
"status": 400,
"error": "Bad Request",
"path": "/user/r8"
}
Required request body is missing:

@RequestBody它表示要从正文里面拿到信息
所以我要改成这样
789c7801b67cb827ab77544b75d596a0

832a5ddadba76be335a1d8ae7c034dbf

这样就拿到信息了

jackson拿到json字符串构造对象 是调用无参构造,挨个解析赋值

如何获取URL中参数:
b322b2a65599354a469a6ffe80c0dea9

@RequestMapping("/r9/{articleId}")
    public String r9(@PathVariable Integer articleId){
        return "articleId"+articleId;

    }

@PathVariable 这个注解获取路径里的变量,变量用{ }这个包住
6b1a9dfdf37672ba2c15bf7c2d1710f1

变量名字和参数的要一致
多个参数时候 要按照定义的顺序来

@RequestMapping("/r10/{name}/{id}")
    public String r10(@PathVariable String name,@PathVariable Integer id){
        return "name:"+name+"id:"+id;

    }

否则就会

87ea104a8209b57ed0e39c0752320935

当然他也可以对参数重命名

直接用@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();

    }

774a8a943ce0251bebedfe0ef1330c0f

那我们获得这个文件后,可以存放

就改为

    @RequestMapping("/r11")
    public String r11(@RequestPart MultipartFile file) throws IOException {
        String fileName=file.getOriginalFilename();
        file.transferTo(new File("D:/tmp/"+fileName));
        return  "获取上传文件:"+file.getOriginalFilename();

    }

3ab5ce1352abdbd3de4dc2d9af769e3b

同样这里也可以参数重命名

到这里 Springmvc的请求的基本操作就学完了

回顾Cookie

HTTP协议自身是属于"无状态”协议.
"无状态”的含义指的是:

默认情况下HTTP协议的客户端和服务器之间的这次通信,和下次通信之间没有直接的联系.
但是实际开发中,我们很多时候是需要知道请求之间的关联关系的.
例如登陆网站成功后,第二次访问的时候服务器就能知道该请求是否是已经登陆过了.

b798a95aa9ac7e886e0ccae0312b2efc

这里的令牌就储存在Cookie字段中

回顾下Session 会话

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

23cab46af5676da10ad3b0974d2251ef

Cookie&Session

f39650f3ef842fe07023f03793faacf3

学生证可以造假,但是学校教务系统的信息不能造假。

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;
    }

}

068131622935c3143b04f18c644c2496

这样子一次不能获取全部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为空";
    }

459577dfb2f7b29ce51a4d7bcca9e081

如何获取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;
    }

707762026d0e5fcf6e446f74e811b1b1

19b6c35d71b10efd53059b3a68f1ee75

第二种

@RequestMapping("getSession2")
    public String getSession2(HttpSession session){
        String userName = (String)session.getAttribute("userName");
        return "登录用户"+userName;
    }

HttpSession这也是个内置对象
2421bb8865db9375e8c613619c3986e2

第三种

@RequestMapping("getSession3")
    public String getSession2(@SessionAttribute("userName") String userName){
        return "登录用户"+userName;
    }

第三种最简便 但是不同于前两个 他不会自动创建Session Session不存在时会报错

如果确定 Session 中一定有该属性:用方式三 @SessionAttribute,最优雅

如果属性可能不存在,需要兜底处理:用方式一或二,或者方式三加 required = false + 判空

上述用内置对象最传统、最通用

posted @ 2026-08-30 21:48  曾章吉的浩吧  阅读(3)  评论(0)    收藏  举报