Spring Boot(2.1.6.RELEASE)开发Web应用程序


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

Spring Web MVC framework

Spring Web MVC framework(通常简称为“Spring MVC”)是一个典型的MVC(model view controller)框架。Spring MVC允许您创建@Controller或@RestControllerbean来处理传入的HTTP请求。Controller中的方法通过使用@RequestMapping注解映射到具体的HTTP。

以下代码显示了@RestController为JSON数据提供服务的典型代码:

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

	@RequestMapping(value="/{user}", method=RequestMethod.GET)
	public User getUser(@PathVariable Long user) {
		// ...
	}

	@RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
	List<Customer> getUserCustomers(@PathVariable Long user) {
		// ...
	}

	@RequestMapping(value="/{user}", method=RequestMethod.DELETE)
	public User deleteUser(@PathVariable Long user) {
		// ...
	}

}

Spring MVC自动化配置

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

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

  • 包含ContentNegotiatingViewResolver和BeanNameViewResolver beans。
  • 支持提供静态资源,包括对WebJars的支持( 本文稍后介绍)。
  • 自动注册Converter,GenericConverter和Formatter beans。
  • 支持HttpMessageConverters( 本文档后面部分)。
  • 自动注册MessageCodesResolver( 本文档后面部分)。
  • 支持静态index.html。
  • 支持自定义Favicon(本文档稍后介绍)。
  • 自动使用ConfigurableWebBindingInitializerbean( 本文档稍后介绍)。

如果希望保留Spring Boot MVC特性,并添加额外的MVC配置(拦截器、格式化器、视图控制器和其他特性),可以添加自己@Configuration修饰的WebMvcConfigurer类,但是不需要@EnableWebMvc。如果希望提供RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,可以声明一个WebMvcRegistrationsAdapter实例来提供此类组件。

如果您想完全控制Spring MVC,您可以添加自己的@Configuration,并使用注解@EnableWebMvc。

HttpMessageConverters

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

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

import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration
public class MyConfiguration {

	@Bean
	public HttpMessageConverters customConverters() {
		HttpMessageConverter<?> additional = ...
		HttpMessageConverter<?> another = ...
		return new HttpMessageConverters(additional, another);
	}

}

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

自定义JSON序列化程序和反序列化程序

如果使用Jackson序列化和反序列化JSON数据,您可能希望编写自己的类JsonSerializer和JsonDeserializer类。自定义序列化程序通常通过模块向Jackson注册,但Spring Boot提供了另一种@JsonComponent注释,可以更容易地直接注册Spring Beans。

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

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

	public static class Serializer extends JsonSerializer<SomeObject> {
		// ...
	}

	public static class Deserializer extends JsonDeserializer<SomeObject> {
		// ...
	}

}

ApplicationContext中的所有@JsonComponent 注解的bean都自动注册到Jackson。因为@JsonComponent使用@Component进行元注解,所以通常使用组件扫描规则。
Spring Boot还提供了JsonObjectSerializer和JsonObjectDeserializer基类,它们在序列化对象时提供了标准Jackson版本之外的替代方法。ApplicationContext中的所有@JsonComponent bean都自动注册到Jackson。因为@JsonComponent使用@Component进行元注释,所以通常使用组件扫描规则。
Spring Boot还提供了JsonObjectSerializer和JsonObjectDeserializer基类,它们在序列化对象时提供了标准Jackson版本之外的有用替代方法。有关详细信息,请参阅Javadoc中的JsonObjectSerializer和JsonObjectDeserializer。

MessageCodesResolver

Spring MVC有一个用于生成错误代码的策略,以便在错误中绑定错误消息:MessageCodesResolver。如果您设置spring.mvc.message-code -resolver.format属性为PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE, Spring Boot为会创建一个MessageCodesResolver。

静态内容

默认情况下,Spring Boot从类路径中的/static( /public或/resources或/META-INF/resources)或者根目录中提供静态内容ServletContext。它使用来自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.resources.static-locations属性(用目录位置列表替换默认值)。根上下文路径“/”会自动添加为一个位置。

欢迎界面

Spring Boot支持静态和模板化欢迎页面。它首先index.html在配置的静态内容位置中查找 文件。如果找不到,则查找index模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。

路径匹配

Spring MVC可以通过查看请求路径并将其与应用程序中定义的映射(例如, Controller方法上的@GetMapping注解)相匹配,将传入的HTTP请求映射到处理程序。

Spring Boot默认禁用后缀模式匹配,这意味着请求"GET /projects/spring-boot.json"不会与@GetMapping("/projects/spring-boot")映射匹配 。这被认为是Spring MVC应用程序的最佳实践。我们需要确保将正确的内容类型发送给客户端。

还有其他方法可以处理不一致请求发送到正确的客户端。我们可以使用查询参数来确保诸如“GET /projects/spring-boot?”format=json"将被映射到@GetMapping("/projects/spring-boot"):

spring.mvc.contentnegotiation.favor-parameter=true

# We can change the parameter name, which is "format" by default:
# spring.mvc.contentnegotiation.parameter-name=myparam

# We can also register additional file extensions/media types with:
spring.mvc.contentnegotiation.media-types.markdown=text/markdown

如果您理解这些警告,并且仍然希望应用程序使用后缀模式匹配,则需要以下配置:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true

另外,相对打开所有后缀模式,而仅支持已注册的后缀模式更安全:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true

# You can also register additional file extensions/media types with:
# spring.mvc.contentnegotiation.media-types.adoc=text/asciidoc

模板引擎

除REST Web服务外,您还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持各种模板技术,包括Thymeleaf,FreeMarker和JSP。此外,许多其他模板引擎也包含他们自己的Spring MVC集成。

Spring Boot对以下模板引擎支持自动配置:

  • FreeMarker
  • Groovy
  • Thymeleaf
  • Mustache

应该避免jsp。在与嵌入式servlet容器一起使用时,有几个已知的限制:

  • 使用Jetty和Tomcat,如果使用war包,是可以工作的。运行java -jar启动可执行的war包,并且也可以部署到任何标准容器中。打包成jar文件时不支持JSP。
  • Undertow不支持JSP。
  • 创建自定义error.jsp页面不会覆盖错误处理的默认视图 。 应该使用自定义错误页面。

当您使用其中一个模板引擎和默认配置时,程序将自动从src/main/resources/templates路径下获取模板。

错误处理

默认情况下,Spring Boot提供了一个/error目录以合理方式处理所有错误的映射,并将其注册为servlet容器中的“全局”错误页面。对于计算机客户端,它会生成一个JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“whitelabel”错误视图,它以HTML格式呈现相同的数据(以自定义它,添加View解析后的数据error)。要完全替换默认行为,您可以实现 ErrorController并注册该类型的bean定义,或者添加类型的bean ErrorAttributes以使用现有机制但替换内容。

还可以@ControllerAdvice注解自定义类来设置特定控制器和/或异常类型返回的JSON文档,如以下示例所示:

@ControllerAdvice(basePackageClasses = AcmeController.class)
public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {

	@ExceptionHandler(YourException.class)
	@ResponseBody
	ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
		HttpStatus status = getStatus(request);
		return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
	}

	private HttpStatus getStatus(HttpServletRequest request) {
		Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
		if (statusCode == null) {
			return HttpStatus.INTERNAL_SERVER_ERROR;
		}
		return HttpStatus.valueOf(statusCode);
	}

}

自定义错误界面

如果要根据状态码自定义HTML错误页面,可以将文件添加到文件到/error目录。错误页面可以是静态HTML(即,添加到任何静态资源文件夹下),也可以使用模板构建。文件名应该是确切的状态代码或系列掩码。

例如,要映射404到静态HTML文件,文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

使用FreeMarker模板映射所有5xx错误,文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftl
             +- <other templates>

对于更复杂的映射,可通过添加实现ErrorViewResolver 接口的bean ,如以下示例所示:

public class MyErrorViewResolver implements ErrorViewResolver {

	@Override
	public ModelAndView resolveErrorView(HttpServletRequest request,
			HttpStatus status, Map<String, Object> model) {
		// Use the request or status to optionally return a ModelAndView
		return ...
	}

}

对跨域(CORS)的支持

跨源资源共享 (CORS)是大多数浏览器实现 的W3C规范,允许以灵活的方式指定授权何种跨域请求,而不是使用一些安全性较低且功能较弱的方法,如IFRAME或JSONP。
从4.2开始,Spring MVC 支持CORS。 在Spring Boot应用程序中使用带有注解@CrossOrigin的控制器方法时,CORS配置不需要任何特定配置。 可以通过使用自定义方法注册bean 来定义全局CORS配置,如以下示例所示:

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
	return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

	@Override
	public void registerErrorPages(ErrorPageRegistry registry) {
		registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
	}

}

Spring WebFlux框架(spring boot 2.0)

Spring WebFlux是Spring Framework 5.0中引入的新型响应式Web框架。与Spring MVC不同,它不需要Servlet API,完全异步且无阻塞, 通过Reactor项目实现Reactive Streams规范。

  • 原始Web框架Spring Web MVC是专为Servlet API和Servlet容器构建的
  • 响应式Web框架Spring WebFlux在5.0以后的版中添加。它完全无阻塞,支持 Reactive Streams背压,并在Netty,Undertow和Servlet 3.1+容器等服务器上运行。

Spring WebFlux有两种版本:基于功能和注解。基于注解的注解非常接近Spring MVC模型,如以下示例所示:

  • 基于注解

    @RestController
    @RequestMapping("/users")
    public class MyRestController {
    
    	@GetMapping("/\{user}")
    	public Mono<User> getUser(@PathVariable Long user) {
    		// ...
    	}
    
    	@GetMapping("/\{user}/customers")
    	public Flux<Customer> getUserCustomers(@PathVariable Long user) {
    		// ...
    	}
    
    	@DeleteMapping("/\{user}")
    	public Mono<User> deleteUser(@PathVariable Long user) {
    		// ...
    	}
    
    }
    
  • 功能
    “WebFlux.fn”是功能变体,它将路由配置与请求的实际处理分开,如以下示例所示:

@Configuration
public class RoutingConfiguration {

	@Bean
	public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
		return route(GET("/\{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
				.andRoute(GET("/\{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
				.andRoute(DELETE("/\{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
	}

}

@Component
public class UserHandler {

	public Mono<ServerResponse> getUser(ServerRequest request) {
		// ...
	}

	public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
		// ...
	}

	public Mono<ServerResponse> deleteUser(ServerRequest request) {
		// ...
	}
}

使用方法:将spring-boot-starter-webflux模块添加到pom.xml中。

TIPS:若spring-boot-starter-web和spring-boot-starter-webflux模块同时存在,Spring Boot会自动配置Spring MVC。

嵌入式web容器

Spring Boot对嵌入式Tomcat, Jetty和 Undertow服务器提供支持。大多数开发人员使用适当的“Starter”来获取完全配置的实例。默认情况下,嵌入式服务器侦听端口上的HTTP请求8080。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值