Spring Boot框架学习 - Spring Boot Web Application

Spring Boot框架学习 - Spring Boot Web Application,第1张

Spring Boot框架学习 - Spring Boot Web Application 四、Web

Spring Boot 非常适合 Web 应用程序开发。 您可以使用嵌入式 Tomcat、Jetty、Undertow 或 Netty 创建自包含的 HTTP 服务器。 大多数 Web 应用程序使用 spring-boot-starter-web 模块来快速启动和运行。 您还可以选择使用 spring-boot-starter-webflux 模块构建反应式 Web 应用程序。

如果你还没有开发过 Spring Boot web 应用,可以关注“Hello World!” 入门部分中的示例。

1、Servlet Web 应用程序

如果您想构建基于 servlet 的 Web 应用程序,您可以利用 Spring Boot 对 Spring MVC 或 Jersey 的自动配置。

1.1 “Spring Web MVC 框架”

Spring Web MVC 框架(通常称为“Spring MVC”)是一个丰富的“模型视图控制器”Web 框架。 Spring MVC 允许您创建特殊的 @Controller 或 @RestController bean 来处理传入的 HTTP 请求。 控制器中的方法通过使用 @RequestMapping 注解映射到 HTTP。

以下代码显示了一个典型的 @RestController,它提供 JSON 数据:

import java.util.List;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class MyRestController {

    private final UserRepository userRepository;

    private final CustomerRepository customerRepository;

    public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {
        this.userRepository = userRepository;
        this.customerRepository = customerRepository;
    }

    @GetMapping("/{user}")
    public User getUser(@PathVariable Long userId) {
        return this.userRepository.findById(userId).get();
    }

    @GetMapping("/{user}/customers")
    public List getUserCustomers(@PathVariable Long userId) {
        return this.userRepository.findById(userId).map(this.customerRepository::findByUser).get();
    }

    @DeleteMapping("/{user}")
    public void deleteUser(@PathVariable Long userId) {
        this.userRepository.deleteById(userId);
    }

}

Spring MVC 是核心 Spring framework 的一部分,详细信息可在参考文档中找到。 在 spring.io/guides 上还有一些涵盖 Spring MVC 的指南。

1.1.1 Spring MVC 自动配置

Spring Boot 为 Spring MVC 提供了自动配置,适用于大多数应用程序。

自动配置在 Spring 的默认设置之上添加了以下功能:

  • 包含 ContentNegotiatingViewResolver 和 BeanNameViewResolver bean。
  • 支持提供静态资源,包括对 WebJars 的支持(本文档稍后介绍)。
  • 自动注册 Converter、GenericConverter 和 Formatter bean。
  • 对 HttpMessageConverters 的支持(本文档稍后介绍)。
  • MessageCodesResolver 的自动注册(本文档稍后介绍)。
  • 静态 index.html 支持。
  • 自动使用 ConfigurableWebBindingInitializer bean(本文档稍后介绍)。

如果您想保留那些 Spring Boot MVC 自定义并进行更多 MVC 自定义(拦截器、格式化程序、视图控制器和其他功能),您可以添加自己的 WebMvcConfigurer 类型的 @Configuration 类,但不添加 @EnableWebMvc。

如果您想提供 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 或 ExceptionHandlerExceptionResolver 的自定义实例,并且仍然保留 Spring Boot MVC 自定义,您可以声明一个类型为 WebMvcRegistrations 的 bean 并使用它来提供这些组件的自定义实例。

如果您想完全控制 Spring MVC,您可以添加您自己的带有 @EnableWebMvc 注解的 @Configuration,或者添加您自己的 @Configuration 注解的 DelegatingWebMvcConfiguration,如 @EnableWebMvc 的 Javadoc 中所述。

Spring MVC 使用与用于转换 application.properties 或 application.yaml 文件中的值不同的 ConversionService。 这意味着 Period、Duration 和 DataSize 转换器不可用,@DurationUnit 和 @DataSizeUnit 注解将被忽略。

如果要自定义 Spring MVC 使用的 ConversionService,可以提供带有 addFormatters 方法的 WebMvcConfigurer bean。 通过此方法,您可以注册您喜欢的任何转换器,也可以委托给 ApplicationConversionService 上可用的静态方法。

1.1.2 HttpMessageConverters

Spring MVC 使用 HttpMessageConverter 接口来转换 HTTP 请求和响应。 包括开箱即用的合理默认值。 例如,对象可以自动转换为 JSON(使用 Jackson 库)或 XML(使用 Jackson XML 扩展,如果可用,或者使用 JAXB,如果 Jackson XML 扩展不可用)。 默认情况下,字符串以 UTF-8 编码。

如果需要添加或自定义转换器,可以使用 Spring Boot 的 HttpMessageConverters 类,如下面的清单所示:

import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;

@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {

    @Bean
    public HttpMessageConverters customConverters() {
        HttpMessageConverter additional = new AdditionalHttpMessageConverter();
        HttpMessageConverter another = new AnotherHttpMessageConverter();
        return new HttpMessageConverters(additional, another);
    }

}

上下文中存在的任何 HttpMessageConverter bean 都会添加到转换器列表中。 您还可以以相同的方式覆盖默认转换器。

1.1.3 自定义 JSON 序列化器和反序列化器

如果您使用 Jackson 来序列化和反序列化 JSON 数据,您可能需要编写自己的 JsonSerializer 和 JsonDeserializer 类。 自定义序列化程序通常通过模块向 Jackson 注册,但 Spring Boot 提供了一个替代的 @JsonComponent 注解,可以更轻松地直接注册 Spring Beans。

您可以直接在 JsonSerializer、JsonDeserializer 或 KeyDeserializer 实现上使用 @JsonComponent 注解。 您还可以在包含序列化器/反序列化器作为内部类的类上使用它,如以下示例所示:

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import org.springframework.boot.jackson.JsonComponent;

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonSerializer {

        @Override
        public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
            jgen.writeStringField("name", value.getName());
            jgen.writeNumberField("age", value.getAge());
        }

    }

    public static class Deserializer extends JsonDeserializer {

        @Override
        public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            ObjectCodec codec = jsonParser.getCodec();
            JsonNode tree = codec.readTree(jsonParser);
            String name = tree.get("name").textValue();
            int age = tree.get("age").intValue();
            return new MyObject(name, age);
        }

    }

}

ApplicationContext 中的所有 @JsonComponent bean 都会自动向 Jackson 注册。 因为 @JsonComponent 是用 @Component 元注解的,所以通常的组件扫描规则适用。

Spring Boot 还提供了 JsonObjectSerializer 和 JsonObjectDeserializer 基类,它们在序列化对象时提供了标准 Jackson 版本的有用替代方案。 有关详细信息,请参阅 Javadoc 中的 JsonObjectSerializer 和 JsonObjectDeserializer。

上面的示例可以重写为使用 JsonObjectSerializer/JsonObjectDeserializer,如下所示:

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;

import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.jackson.JsonObjectDeserializer;
import org.springframework.boot.jackson.JsonObjectSerializer;

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonObjectSerializer {

        @Override
        protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
                throws IOException {
            jgen.writeStringField("name", value.getName());
            jgen.writeNumberField("age", value.getAge());
        }

    }

    public static class Deserializer extends JsonObjectDeserializer {

        @Override
        protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
                JsonNode tree) throws IOException {
            String name = nullSafevalue(tree.get("name"), String.class);
            int age = nullSafevalue(tree.get("age"), Integer.class);
            return new MyObject(name, age);
        }

    }

}
1.1.4 MessageCodesResolver

Spring MVC 有一个生成错误代码的策略,用于从绑定错误呈现错误消息:MessageCodesResolver。 如果您设置 spring.mvc.message-codes-resolver-format 属性 PREFIX_ERROR_CODE 或 POSTFIX_ERROR_CODE,Spring Boot 会为您创建一个(请参阅 DefaultMessageCodesResolver.Format 中的枚举)。

1.1.5 静态内容

默认情况下,Spring Boot 提供来自类路径或 ServletContext 根目录中名为 /static(或/public 或 /resources 或 /meta-INF/resources)的目录中的静态内容。 它使用 Spring MVC 中的 ResourceHttpRequestHandler,因此您可以通过添加自己的 WebMvcConfigurer 并覆盖 addResourceHandlers 方法来修改该行为。

在独立的 Web 应用程序中,来自容器的默认 servlet 也被启用并充当回退,如果 Spring 决定不处理它,则从 ServletContext 的根提供内容。 大多数时候,这不会发生(除非你修改了默认的 MVC 配置),因为 Spring 总是可以通过 DispatcherServlet 处理请求。

默认情况下,资源映射在 /** 上,但您可以使用 spring.mvc.static-path-pattern 属性对其进行调整。 例如,将所有资源重定位到 /resources/** 可以实现如下:

spring.mvc.static-path-pattern=/resources/**

您还可以使用 spring.web.resources.static-locations 属性(用目录位置列表替换默认值)自定义静态资源位置。 根 servlet 上下文路径“/”也被自动添加为一个位置。

除了前面提到的“标准”静态资源位置之外,还为 Webjars 内容制作了一个特例。 任何在 /webjars/** 中有路径的资源都从 jar 文件提供,如果它们以 Webjars 格式打包。

如果您的应用程序打包为 jar,请不要使用 src/main/webapp 目录。 虽然这个目录是一个通用的标准,但它只适用于war包,如果你生成一个jar,它会被大多数构建工具默默地忽略。

Spring Boot 还支持 Spring MVC 提供的高级资源处理功能,允许使用诸如缓存破坏静态资源或使用 Webjar 的版本不可知 URL 等用例。

要为 Webjar 使用与版本无关的 URL,请添加 webjars-locator-core 依赖项。 然后声明你的 Webjar。 以 jQuery 为例,添加“/webjars/jquery/jquery.min.js”会导致“/webjars/jquery/x.y.z/jquery.min.js”,其中 x.y.z 是 Webjar 版本。

如果使用 JBoss,则需要声明 webjars-locator-jboss-vfs 依赖项而不是 webjars-locator-core。 否则,所有 Webjar 都会解析为 404。

要使用缓存清除,以下配置为所有静态资源配置缓存清除解决方案,有效地在 URL 中添加内容哈希,例如

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5696391.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存