Spring Boot中的内容协商

简介: Spring Boot中的内容协商

Spring Boot中的内容协商

今天我们来探讨一下Spring Boot中的内容协商(Content Negotiation)。内容协商是一个重要的Web服务功能,它允许服务器根据客户端请求中的头信息返回不同格式的数据,例如JSON、XML等。通过内容协商,开发者可以为同一个资源提供多种表示形式。

一、内容协商的基本概念

内容协商是HTTP协议中的一部分,允许客户端和服务器就响应的最佳表示形式达成一致。在HTTP请求中,客户端可以通过Accept头指定希望接收的响应格式,服务器则会根据这一信息决定返回哪种格式的数据。

二、Spring Boot中的内容协商配置

在Spring Boot中,内容协商通过ContentNegotiationConfigurer进行配置。我们可以在配置类中设置默认的媒体类型和支持的媒体类型。

首先,创建一个配置类:

package cn.juwatech.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
   

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
   
        configurer
            .favorParameter(true)
            .parameterName("mediaType")
            .ignoreAcceptHeader(false)
            .defaultContentType(org.springframework.http.MediaType.APPLICATION_JSON)
            .mediaType("json", org.springframework.http.MediaType.APPLICATION_JSON)
            .mediaType("xml", org.springframework.http.MediaType.APPLICATION_XML);
    }
}

三、控制器中的内容协商

接下来,我们在控制器中编写示例代码,展示如何根据请求的媒体类型返回不同格式的数据。

package cn.juwatech.controller;

import cn.juwatech.model.User;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

@RestController
public class UserController {
   

    @GetMapping(value = "/users", produces = {
   MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    public List<User> getUsers() {
   
        return Arrays.asList(
            new User(1, "John Doe", "john.doe@example.com"),
            new User(2, "Jane Smith", "jane.smith@example.com")
        );
    }
}

四、模型类

为了使上述代码正常工作,我们需要创建一个简单的模型类User

package cn.juwatech.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class User {
   

    private int id;
    private String name;
    private String email;

    public User() {
   
    }

    public User(int id, String name, String email) {
   
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public int getId() {
   
        return id;
    }

    public void setId(int id) {
   
        this.id = id;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public String getEmail() {
   
        return email;
    }

    public void setEmail(String email) {
   
        this.email = email;
    }
}

五、测试内容协商

现在,我们可以通过不同的方式来测试内容协商功能。

  1. 使用浏览器:

    • 访问http://localhost:8080/users?mediaType=json,浏览器会显示JSON格式的数据。
    • 访问http://localhost:8080/users?mediaType=xml,浏览器会显示XML格式的数据。
  2. 使用curl命令行工具:

    • 请求JSON格式的数据:
      curl -H "Accept: application/json" http://localhost:8080/users
      
    • 请求XML格式的数据:
      curl -H "Accept: application/xml" http://localhost:8080/users
      

六、使用自定义消息转换器

有时,我们需要自定义消息转换器以支持特殊的媒体类型。以下是一个示例,展示如何在Spring Boot中注册自定义消息转换器。

首先,创建自定义消息转换器类:

package cn.juwatech.converter;

import cn.juwatech.model.User;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class CustomMessageConverter extends AbstractHttpMessageConverter<User> {
   

    public CustomMessageConverter() {
   
        super(new MediaType("application", "x-custom-type", StandardCharsets.UTF_8));
    }

    @Override
    protected boolean supports(Class<?> clazz) {
   
        return User.class.equals(clazz);
    }

    @Override
    protected User readInternal(Class<? extends User> clazz, HttpInputMessage inputMessage) throws IOException {
   
        // 实现读取逻辑
        return null;
    }

    @Override
    protected void writeInternal(User user, HttpOutputMessage outputMessage) throws IOException {
   
        // 实现写入逻辑
        String output = "Custom User Output: " + user.getName();
        outputMessage.getBody().write(output.getBytes(StandardCharsets.UTF_8));
    }
}

接下来,在配置类中注册这个自定义消息转换器:

package cn.juwatech.config;

import cn.juwatech.converter.CustomMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {
   

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
   
        converters.add(new CustomMessageConverter());
    }
}

七、测试自定义消息转换器

为了测试自定义消息转换器,我们可以更新控制器中的方法,使其支持自定义的媒体类型:

@GetMapping(value = "/custom-user", produces = "application/x-custom-type")
public User getCustomUser() {
   
    return new User(1, "John Doe", "john.doe@example.com");
}

现在,我们可以通过以下命令测试自定义消息转换器:

curl -H "Accept: application/x-custom-type" http://localhost:8080/custom-user

总结

通过本文,我们了解了在Spring Boot中实现内容协商的基本方法,包括配置内容协商、使用不同的媒体类型返回数据以及自定义消息转换器。内容协商是构建灵活、高效的RESTful服务的重要组成部分,能够帮助我们更好地满足不同客户端的需求。

相关文章
|
缓存 安全 JavaScript
前端安全:Vue应用中防范XSS和CSRF攻击
【4月更文挑战第23天】本文探讨了在Vue应用中防范XSS和CSRF攻击的重要性。XSS攻击通过注入恶意脚本威胁用户数据,而CSRF则利用用户身份发起非授权请求。防范措施包括:对输入内容转义、使用CSP、选择安全的库;采用Anti-CSRF令牌、同源策略和POST请求对抗CSRF;并实施代码审查、更新依赖及教育团队成员。通过这些实践,可提升Vue应用的安全性,抵御潜在攻击。
1330 0
|
Docker 容器
docker出现问题:启动nexus时报错mkdir: cannot create directory ‘../sonatype-work/nexus3‘: Permission denied解决方案
docker出现问题:启动nexus时报错mkdir: cannot create directory ‘../sonatype-work/nexus3‘: Permission denied解决方案
1782 0
docker出现问题:启动nexus时报错mkdir: cannot create directory ‘../sonatype-work/nexus3‘: Permission denied解决方案
|
10月前
|
数据采集 小程序 API
通义千问Qwen2.5-Coder 全系列来咯!强大、多样、实用
千问团队开源了强大的 Qwen2.5-Coder 系列模型,涵盖 0.5B 到 32B 六种尺寸,旨在推动开放代码模型的发展。该系列模型在代码生成、修复和推理等方面表现出色,支持多种编程语言,并在多个基准测试中达到 SOTA 水平。此外,Qwen2.5-Coder 还提供了丰富的应用场景,如代码助手、Artifacts 和 Interpreter,满足不同开发者的需求。
3667 106
|
11月前
|
Linux 网络安全 数据安全/隐私保护
Jetson 学习笔记(十三):SSH远程登录控制(终端控制和图形界面)-成功通过
这篇文章介绍了如何通过SSH命令行和VNC图形界面远程登录和控制NVIDIA Jetson Nano设备。
1508 0
Jetson 学习笔记(十三):SSH远程登录控制(终端控制和图形界面)-成功通过
|
Java Docker 容器
云效构建镜像并上传的过程中,Context Path是用于指定Dockerfile所在的目录
云效构建镜像并上传的过程中,Context Path是用于指定Dockerfile所在的目录
198 1
|
JSON JavaScript 前端开发
VUE3(七)vue项目抽离.vue文件中的js、css代码
平常再做开发的时候,一般情况下不会将html,js,css代码写到一个文件中。 基本上都会写在各自对应的文件中,然后再引入即可。
972 0
VUE3(七)vue项目抽离.vue文件中的js、css代码
|
安全 前端开发 Java
WebMvcConfigurationSupport 和 WebMvcConfigurer 区别你知道吗
WebMvcConfigurationSupport 和 WebMvcConfigurer 的使用过程中你是否踩坑了它们的区别是什么快来看看吧
970 0
|
存储 缓存 前端开发
《Webpack5 核心原理与应用实践》学习笔记-> webpack5持久化缓存
《Webpack5 核心原理与应用实践》学习笔记-> webpack5持久化缓存
449 1
|
存储 缓存 Unix
NPM 常用命令(二)
NPM 常用命令(二)
|
Java Spring
Spring项目中value注解,@Value不能a够读取到配置文件的值,无法成功注入值的问题解决(超简单)
Spring项目中value注解,@Value不能a够读取到配置文件的值,无法成功注入值的问题解决(超简单)
811 0