【Springboot】请求处理、响应处理(请求映射、基本注解、响应JSON、内容协商)

🔰 学习视频 🔰

尚硅谷雷神SpringBoot2零基础入门springboot全套完整版(spring boot2)

集数:25—42 (原理部分跳过)


🔰 学习笔记 🔰

【Java】学习笔记汇总


一、请求处理

1.1 请求映射

🔶 @xxxMapping

/getUser   获取用户     
/deleteUser 删除用户    
/editUser  修改用户       
/saveUser 保存用户

🔶 Rest风格支持:使用HTTP请求方式动词来表示对资源的操作

/user   
GET-获取用户    
DELETE-删除用户 
PUT-修改用户 
POST-保存用户  

🔶 Rest风格用法

1 表单method=post,隐藏域 _method=put

2 SpringBoot中手动开启,配置文件

# 开启页面表单的Rest功能
spring:
 mvc:
  hiddenmethod:
   filter:
    enabled: true

🔶 Rest风格原理

请求过来被HiddenHttpMethodFilter拦截,如果请求正常并且为POST,获取到_method的值(兼容PUT.DELETE.PATCH请求,大小写均可)。原生模式的request(post),包装模式requestWrapper重写了getMethod方法,返回的是传入的值。过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。

如果是Android直接发送,或者使用Postman客户端直接发送这些PUT.DELETE.PATCH请求,不会经过filter,所以页面表单的Rest功能可以选择性开启。

@GetMapping("/user") 等同于@RequestMapping(value = "/user",method = RequestMethod.GET)

@RequestMapping(value = "/user",method = RequestMethod.GET)
public String getUser(){
    return "GET-张三";
}

@RequestMapping(value = "/user",method = RequestMethod.POST)
public String saveUser(){
    return "POST-张三";
}


@RequestMapping(value = "/user",method = RequestMethod.PUT)
public String putUser(){
    return "PUT-张三";
}

@RequestMapping(value = "/user",method = RequestMethod.DELETE)
public String deleteUser(){
    return "DELETE-张三";
}

@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}

//自定义filter
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
    HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
    methodFilter.setMethodParam("_m");
    return methodFilter;
}
<form action="/user method="post">
	<input name="_method" type="hidden" value="delete"/>
	<input value="提交" type="submit"/>
</form>

🔶 扩展:如何把_method这个名字换成_m

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;

@Configuration(proxyBeanMethods = false)
public class WebConfig {

    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m");
        return methodFilter;
    }
}

1.2 请求映射原理

集数:28

1.3 基本注解

@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

🔶 路径变量 @PathVariable

@RestController
public class ParameterController {

    @GetMapping("/car/{id}/owner/{username}")
    public Map<String, Object> getCar(@PathVariable("id") Integer id,
                                      @PathVariable("username") String name,
                                      @PathVariable Map<String, String> pv) {
        Map<String, Object> map = new HashMap<>();

        map.put("id", id);
        map.put("name", name);
        map.put("pv", pv);
        return map;
    }
}

访问:localhost:8080/testPathVariable/1/owner/xxx

结果:

{"pv":{"id":"1","username":"xxx"},"name":"xxx","id":1}

🔶 请求头 @RequestHeader

@GetMapping("/testRequestHeader/{id}")
public Map<String, Object> testRequestHeader(@PathVariable("id") Integer id,
                                             @RequestHeader("User-Agent") String userAgent,
                                             @RequestHeader Map<String, String> pv) {
    Map<String, Object> map = new HashMap<>();
    map.put("id", id);
    map.put("userAgent", userAgent);
    map.put("pv", pv);
    return map;
}

访问:localhost:8080/testRequestHeader/1

结果:

{"pv":{"host":"localhost:8080","connection":"keep-alive","sec-ch-ua":"\"Google Chrome\";v=\"95\", \"Chromium\";v=\"95\", \";Not A Brand\";v=\"99\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"Windows\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","sec-fetch-site":"none","sec-fetch-mode":"navigate","sec-fetch-user":"?1","sec-fetch-dest":"document","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7","cookie":"Idea-11f3a2b2=09893cd1-2e09-40b2-9024-ec951cc04a73; JSESSIONID=FF70BC34EC9A540598FB6B3F29D9C73B; token=19fcec7bda5bef324bdb9af9c6ebf25d"},"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36","id":1}

🔶 请求参数 @RequestParam

@GetMapping("/testRequestParam")
public Map<String, Object> testRequestParam(@RequestParam("id") Integer id,
                                            @RequestParam("list")List<String> list,
                                            @RequestParam Map<String, String> pv) {
    Map<String, Object> map = new HashMap<>();
    map.put("id", id);
    map.put("list", list);
    map.put("pv", pv);

    return map;
}

访问:localhost:8080/testRequestParam?id=1&list=l1&list=l2

结果:

{"pv":{"id":"1","list":"l1"},"id":1,"list":["l1","l2"]}

🔶 Cookie值 @CookieValue

@GetMapping("/testCookieValue")
public Map<String, Object> testCookieValue(@CookieValue("JSESSIONID") String JSESSIONID,
                                           @CookieValue("JSESSIONID") Cookie cookie) {
    Map<String, Object> map = new HashMap<>();
    System.out.println(cookie);
    map.put("JSESSIONID", JSESSIONID);
    return map;
}

访问:localhost:8080/testCookieValue

结果:

{"JSESSIONID":"FF70BC34EC9A540598FB6B3F29D9C73B"}

控制台输出:

javax.servlet.http.Cookie@a7fcf7c

🔶 请求体 @RequestBody

@PostMapping("/save")
public Map<String, Object> postMethod(@RequestBody String content) {
    Map<String, Object> map = new HashMap<>();
    map.put("content", content);
    return map;
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
  <form action="/save" method="post">
     username:<input type="text" name="username"/><br>
     email:<input type="email" name="email"/><br>
     <input type="submit">
  </form>
</body>
</html>

测试
在这里插入图片描述
结果
在这里插入图片描述

🔶 请求域属性 @RequestAttribute

通过/goto发送请求,并进行setAttribute,然后将请求转发给/success;在success中获得转发前的请求。

@Controller
public class RequestController {

    @GetMapping("/goto")
    public String goToPage(HttpServletRequest request) {
        request.setAttribute("msg", "成功了...");
        request.setAttribute("code", 200);
        return "forward:/success"; // 转发到 /success请求
    }


    @ResponseBody
    @GetMapping("/success")
    public Map success(@RequestAttribute("msg") String msg,
                       @RequestAttribute("code") Integer code,
                       HttpServletRequest request) {

        Map<String,Object> map = new HashMap<>();
        Object msg1 = request.getAttribute("msg");

        map.put("reqMethod_msg", msg1);
        map.put("annotation_msg", msg);
        return map;
    }
}

访问:localhost:8080/goto

结果:

{"reqMethod_msg":"成功了...","annotation_msg":"成功了..."}

🔶 矩阵变量 @MatrixVariable

配置:

@Configuration(proxyBeanMethods = false)
public class WebConfig{

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                // 不处理";"后面的内容,矩阵变量功能就可以实现了。
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
    }
}

案例1

控制器:

@GetMapping("/cars/{path}")
public Map testMatrixVariable(@MatrixVariable("low") Integer low,
                              @MatrixVariable("brand") List<String> brand,
                              @PathVariable("path") String path) {
    Map<String, Object> map = new HashMap<>();
    map.put("low", low);
    map.put("brand", brand);
    map.put("path", path);
    return map;
}

访问:http://localhost:8080/cars/sell;low=34;brand=byd,audi,yd

结果:

{"path":"sell","low":34,"brand":["byd","audi","yd"]}

案例2

两个路径有相同的属性,如何指定获取。

//访问: /boss/1;age=20/2;age=10

@GetMapping("/boss/{bossId}/{empId}")
public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
                @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
    Map<String,Object> map = new HashMap<>();

    map.put("bossAge",bossAge);
    map.put("empAge",empAge);
    return map;
}

二、响应处理

在这里插入图片描述

2.1 响应JSON

所需依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Web场景自动引入了Json场景

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-json</artifactId>
	<version>2.3.4.RELEASE</version>
	<scope>compile</scope>
</dependency>

控制类:

@Controller
public class ResponseController {

    @ResponseBody
    @GetMapping("/test/person")
    public Person getPerson() {
        Person person = new Person();
        person.setAge(28);
        person.setBirth(new Date());
        person.setUserName("xxx");
        return person;
    }
}

访问:localhost:8080/test/person

结果:

{"userName":"xxx","age":28,"birth":"2021-11-06T10:31:08.327+00:00"}

2.2 内容协商

根据客户端接收能力不同,返回不同媒体类型的数据。

导入依赖:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

控制类:

@Controller
public class ResponseController {

    @ResponseBody
    @GetMapping("/test/person")
    public Person getPerson() {
        Person person = new Person();
        person.setAge(28);
        person.setBirth(new Date());
        person.setUserName("xxx");
        return person;
    }
}

访问:localhost:8080/test/person

根据客户端请求头中Accept字段,来返回对应的结果。Http协议中规定的,告诉服务器本客户端可以接收的数据类型。如果客户端要接收xml,则返回xml;如果客户端要接收json,则返回json。

在这里插入图片描述

### 如何在Spring Boot和Vue项目中实现WebSocket通信 #### 添加依赖项 为了使 Spring Boot 支持 WebSocket 功能,在 `pom.xml` 文件中需加入以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 这一步骤确保了应用程序能够处理 WebSocket 连接请求[^3]。 #### 配置WebSocket支持 创建配置类以启用消息代理并定义端点映射规则。通过继承 `AbstractSessionWebSocketMessageBrokerConfigurer` 或者使用注解方式简化配置过程,允许前端连接到指定路径下的 WebSocket 服务。 ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); } } ``` 此代码片段设置了 STOMP 协议作为传输层之上的一层抽象,并开放 `/ws` 路径供客户端建立 SockJS 型 WebSocket 连接[^1]。 #### 创建控制器接收消息 编写一个简单的控制器用于监听来自特定目的地的消息事件,并向订阅该主题的所有会话广播响应信息。 ```java @Controller public class ChatController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws Exception { Thread.sleep(1000); // simulated delay return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"); } } ``` 上述例子中的 `@MessageMapping` 注解指定了要匹配的目的地模式;而 `@SendTo` 则决定了返回的数据应该发送给哪些已注册的主题订阅者。 #### Vue前端集成 安装必要的 npm 包如 `sockjs-client` 和 `stompjs` 来管理后端之间的交互逻辑。 ```bash npm install --save sockjs-client stompjs ``` 接着可以在组件内部初始化 Stomp 客户端实例并服务器保持持续通讯状态。 ```javascript import SockJS from 'sockjs-client'; import { Client } from '@stomp/stompjs'; const client = new Client({ brokerURL: 'http://localhost:8080/ws', connectHeaders: {}, debug: (str) => console.log(str), reconnectDelay: 5000, heartbeatIncoming: 4000, heartbeatOutgoing: 4000, }); client.onConnect = () => { console.log('Connected to WS'); }; client.activate(); export default { name: 'ChatApp', data() { return { messages: [], text: '' }; }, methods: { sendMessage(event) { const payload = JSON.stringify({name: this.text}); client.publish({destination: '/app/hello', body: payload}); event.target.reset(); }, subscribeMessages() { client.subscribe('/topic/greetings', response => { let msg = JSON.parse(response.body); this.messages.push(msg.content); }); } }, mounted(){ this.subscribeMessages(); } }; ``` 这段 JavaScript 代码实现了基本的聊天室功能,它能向后台推送新消息以及接收其他用户的发言更新[^2]。 #### 握手流程说明 WebSocket 的握手机制遵循HTTP协议标准,由客户端发起带有特殊头部字段(例如Upgrade、Connection等)的GET 请求至目标 URL 。一旦服务器同意升级,则回复相应的确认报文完成整个协商过程[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望天边星宿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值