从0-1SpringBoot开发webMVC应用(版本2.X)-第六天

一、开发web应用

Spring Boot非常适合web应用程序开发。可以使用嵌入式Tomcat、Jetty、Undertow或Netty创建自包含的HTTP服务器。大多数web应用程序都使用spring-boot-starter-web模块来快速启动和运行。您还可以选择使用spring-boot-starter-webflux模块构建反应性web应用程序。
如果您还没有开发Spring Boot web应用程序,可以看我的之前文章
5.1)Spring Web MVC框架(通常简称为“Spring MVC”)是一个丰富的“模型视图控制器”Web框架。Spring MVC允许您创建特殊的@Controller或@RestController bean来处理传入的HTTP请求。控制器中的方法通过使用@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) {
		// ...
	}

}

1.1)Spring MVC自动配置
自动配置在Spring的默认值之上添加了以下特性

  • 包含ContentNegotiatingViewResolver和BeanNameViewResolver
  • 支持提供静态资源,包括对webjar的支持(可以看下后面的1.5资源)
  • Converter, GenericConverter, 和Formatter的bean自动注册
  • HttpMessageConverters支持(可以看下后面的1.2资源)
  • MessageCodesResolver自动注册(可以看下后面的1.4资源)
  • 静态index.html支持
  • 支持自定义图标(可以看后面的1.7资源)
  • ConfigurableWebBindingInitializer的bean自动使用(可以看下后面1.9资源)

如果希望保留Spring Boot MVC特性,并且希望添加额外的MVC配置(拦截器、格式化器、视图控制器和其他特性),那么可以添加自己的WebMvcConfigurer类型的@Configuration类,但是不需要@EnableWebMvc。
如果想要定制化RequestMappingHandlerMapping, RequestMappingHandlerAdapter, 或者ExceptionHandlerExceptionResolver的实例,你可以声明WebMvcRegistrationsAdapter实例来提供这样的组件。
如果想完全控制Spring MVC,那么可以添加自己的@Configuration,并使用@EnableWebMvc进行注释
1.2)HttpMessageConverters
Spring MVC使用HttpMessageConverter接口来转换HTTP请求和响应。合理的默认值是开箱即用的。例如,对象可以自动转换为JSON(通过使用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都将添加到转换器列表中。您还可以用同样的方法覆盖默认转换器

1.3)自定义JSON序列化器和反序列化器
如果使用Jackson序列化和反序列化的话需要自己的JsonSerializer 和JsonDeserializer类。自定义序列化器通常通过模块向Jackson注册,但是SpringBoot提供了@JsonComponent组件注解直接注册spring的bean实例。

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版本之外的有用替代方法。有关详细信息,请参阅Javadoc中的JsonObjectSerializer和JsonObjectDeserializer。

1.4)MessageCodesResolver
Spring MVC有一个策略,用于生成错误代码,以便从绑定错误中呈现错误消息
如果设置了spring.mvc.message-codes-resolver.format属性PREFIX_ERROR_CODE或者POSTFIX_ERROR_CODE,SpringBoot会根据枚举来创建格式输出

1.5)静态内容
默认情况下,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.resources自定义静态资源位置。属性(用目录位置列表替换默认值)。根Servlet上下文路径“/”也会自动添加为一个位置
上面提到的是标准的,还有一些是来自/webjars/**的资源路径可以参考这里
不要使用src/main/webapp目录因为只适用于war包,如果构建为jar包的时候会被忽略掉。
Spring Boot还支持Spring MVC提供的高级资源处理功能,允许使用一些用例,比如破坏缓存的静态资源,或者为webjar使用版本无关的url
要为webjar使用版本无关的url,请添加webjar -locator-core依赖项。然后声明您的Webjar。以jQuery为例,添加“/webjars/ jQuery / jQuery .min.js" 为 “/webjars/jquery/x.y.z/jquery.min.js”。x.y.z是Webjar版本。
如果使用JBoss,则需要声明webjar -locator- JBoss -vfs依赖项,而不是webjar -locator-core。否则,所有webjar解析为404

为了使用缓存破坏,下面的配置为所有静态资源配置了一个缓存破坏解决方案,
有效地添加了一个内容散列,
比如<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6。css " / >,在url
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**

由于ResourceUrlEncodingFilter是为Thymeleaf和FreeMarker自动配置的,所以在运行时可以在模板中重写到资源的链接。在使用jsp时,应该手动声明此过滤器。目前不自动支持其他模板引擎,但是可以使用自定义模板宏/helper和ResourceUrlProvider
当使用JavaScript模块加载器动态加载资源时,不能重命名文件。这就是为什么其他策略也受到支持,并且可以组合使用。“fixed”策略在URL中添加静态版本字符串而不更改文件名,如下面的示例所示

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/lib/
spring.resources.chain.strategy.fixed.version=v12

随上述配置,如果路径为"/v12/js/lib/mymodule.js",则JavaScript 会定位到"/js/lib/"下面。然后其他资源仍然会使用

<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>

1.6)欢迎页
Spring Boot同时支持静态和模板化的欢迎页面。它首先在配置的静态内容位置中查找index.html文件。如果没有找到,则查找索引模板。如果找到其中之一,它将自动用作应用程序的欢迎页面

1.7)定制化自己的图标
Spring Boot在已配置的静态内容位置和类路径的根目录中查找favicon.ico(按这个顺序)。如果存在这样的文件,它将自动用作应用程序的favicon

1.8)路径匹配和内容匹配协商
Spring MVC可以通过查看请求路径并将其匹配到应用程序中定义的映射(例如,@GetMapping对控制器方法的注释),将传入的HTTP请求映射到处理程序
默认情况下,Spring Boot选择禁用后缀模式匹配
“GET /projects/spring-boot.json"无法和@GetMapping(”/projects/spring-boot")进行匹配,主要是在不能发送“Accept”请求头的Http客户端非常有用,现在我们更加关注的是内容匹配协商。
如果想让上述那种后缀模式可以需要如下配置:

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

1.9)ConfigurableWebBindingInitializer
springMVC默认使用WebBindingInitializer初始化WebDataBinder针对特殊请求,如果你创建了ConfigurableWebBindingInitializer @Bean,SpringBoot自动配置给springMVC来使用它。

1.10)模板引擎
SpringBoot支持的在这里插入图片描述
如果可以的话,还是避免JSP,原因如这里看JSP的限制可以参考下面4.5资源
当使用这些带有默认配置的模板引擎之一时,的模板将自动从src/main/resources/templates中获取
在这里插入图片描述
IntelliJ IDEA根据您运行应用程序的方式对类路径进行不同的排序。在IDE中从主方法运行应用程序的顺序与使用Maven或Gradle或从打包的jar运行应用程序的顺序不同。这可能导致Spring Boot无法在类路径上找到模板。如果有此问题,可以重新排序IDE中的类路径,以首先放置模块的类和资源。或者,您可以配置模板前缀来搜索类路径上的每个模板目录,如下所示:classpath*:/templates/

1.11)错误处理
默认情况下,SpringBoot提供/error路径处理所有错误。并且注册为全局错误页面在servlet容器中。对于某些机器客户端,他将产生一份错误的细节,Http的状态,异常信息的JSON响应。对于浏览器客户端,会在HTML格式输出空白页,可以通过定制化解析错误信息提示一个视图。要完全替换默认行为,可以实现ErrorController并注册该类型的bean定义,或者添加ErrorAttributes类型的bean来使用现有机制,但替换内容。
BasicErrorController可以用作自定义ErrorController的基类。如果您想为新的内容类型添加一个处理程序(默认情况下是专门处理文本/html,并为其他所有内容提供一个回退),那么这尤其有用。为此,扩展BasicErrorController,添加一个带有@RequestMapping的公共方法,该方法具有produces属性,并创建一个新类型的bean。

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

}

在前面的示例中,如果您的rexception由与AcmeController在同一个包中定义的控制器抛出,则使用CustomErrorType POJO的JSON表示,而不是ErrorAttributes表示
1.11.1)定制错误的页面
先添加个/error文件夹,添加个使用templates模板创建的静态HTML页面,文件的名称应该是确切的状态码或系列掩码。举个例子404静态HTML

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

5xx的都走freemaker模板

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

对于更多的复杂映射,你可以添加ErrorViewResolver接口的实现

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

}

还可以使用常规的Spring MVC特性,比如@ExceptionHandler方法和@ControllerAdvice。然后ErrorController获取任何未处理的异常

1.11.2)在Spring MVC之外映射错误页面
对于应用不使用springMVC的,可以使ErrorPageRegistrar 接口直接注册ErrorPages。这样直接依赖内置servlet容器并即使没有springMVC的DispatcherServlet也能正常工作。

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

}

如果使用过滤器处理的路径注册了一个ErrorPage(这在一些非spring web框架中很常见,比如Jersey和Wicket),那么过滤器必须显式地注册为一个错误分派器,如下面的示例所示

@Bean
public FilterRegistrationBean myFilter() {
	FilterRegistrationBean registration = new FilterRegistrationBean();
	registration.setFilter(new MyFilter());
	...
	registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
	return registration;
}

注意,默认的FilterRegistrationBean不包含错误分派器类型。
注意:当部署到servlet容器时,Spring Boot使用其错误页面过滤器将带有错误状态的请求转发到适当的错误页面。如果尚未提交响应,则只能将请求转发到正确的错误页面。默认情况下,WebSphere Application Server 8.0以及稍后在成功完成servlet的服务方法后提交响应。可以通过设置com.ibm.ws.webcontainer.invokeFlushAfterService=false禁用此行为。

1.12)spring的超媒体
如果开发一个使用超媒体的RESTful API, Spring Boot将为Spring HATEOAS提供自动配置,这在大多数应用程序中都能很好地工作。自动配置取代了使用@EnableHypermediaSupport的需要,并注册了许多bean,以简化基于超媒体的应用程序的构建,包括一个LinkDiscoverers(用于客户端支持)和一个ObjectMapper(配置为正确地将响应编组到所需的表示形式)。ObjectMapper是通过设置各种spring.jackson定制的。*属性,如果存在属性,则由Jackson2ObjectMapperBuilder bean创建。
可以使用@EnableHypermediaSupport控制Spring HATEOAS的配置。注意,这样做会禁用前面描述的ObjectMapper定制

1.13)跨域支持
跨源资源共享(Cross-origin resource sharing, CORS)是大多数浏览器实现的W3C规范,它允许您以灵活的方式指定授权了哪种跨域请求,而不是使用一些不太安全、功能不太强大的方法,如IFRAME或JSONP
从4.2版开始,Spring MVC支持CORS。在Spring引导应用程序中使用带有@CrossOrigin注释的控制器方法CORS configuration不需要任何特定的配置。全局CORS配置可以通过使用定制的addcorsm(CorsRegistry)方法注册WebMvcConfigurer bean来定义,如下例所示:

@Configuration
public class MyConfiguration {

	@Bean
	public WebMvcConfigurer corsConfigurer() {
		return new WebMvcConfigurer() {
			@Override
			public void addCorsMappings(CorsRegistry registry) {
				registry.addMapping("/api/**");
			}
		};
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小诚信驿站

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

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

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

打赏作者

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

抵扣说明:

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

余额充值