SpringBoot中MVC的自动配置详解
作者:果子爸聊技术
SpringBoot中MVC的自动配置详解
一个简单的例子
public class MvcModel { private String modelName; private Integer modelType; /**省略geter、setter方法**/ } @RestController @EnableAutoConfiguration public class SpringMvcGuide { @RequestMapping("/getModel") public MvcModel getMvcModel(){ MvcModel mvcModel = new MvcModel(); mvcModel.setModelName("小明"); mvcModel.setModelType(1); return mvcModel; } public static void main(String[] args){ SpringApplication.run(SpringMvcGuide.class,args); } }
启动服务,访问//localhost:8080/getModel可以看到页面显示
{"modelName":"小明","modelType":1}
页面上展示会将MvcModel对象转换成json字符串,这是我们最常用的格式,后台统一返回json格式,前台接收到json格式后进行解析
在实际开发过程中,还有一些老的系统在使用xml格式来传输数据,SpringBoot也提供了xml格式数据的返回,只需要小小的改动,就可以实现
增加依赖
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.11.2' compile 'org.glassfish.jaxb:jaxb-runtime:2.3.3'
将实体类打上@XmlRootElement注解
@XmlRootElement public class MvcModel { private String modelName; private Integer modelType; /**省略geter、setter方法**/ }
重新启动项目,访问//localhost:8080/getModel可以看到页面显示
<MvcModel>
<modelName>小明</modelName>
<modelType>1</modelType>
</MvcModel>
从上面的例子可以看出来,想返回xml格式的数据只需要引入相应的jar包就行了,无需修改任何配置
Spring MVC自动配置
SpringBoot为SpringMVC提供了自动配置,除了SpringMVC默认的配置外还提供了以下配置:
- 引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
- 对静态资源的支持,包括对WebJars的支持
- 自动注册Converter,GenericConverter,Formatter beans。
- 对HttpMessageConverters的支持。
- 自动注册MessageCodeResolver。
- 对静态index.html的支持。
- 对自定义Favicon的支持。
- 自动使用ConfigurableWebBindingInitializer bean。
如果你想保留SpringBoot MVC的特性,只需要增加相应的MVC配置(如拦截器、格式化处理器、视图控制器),如果你想全面的控制Spring MVC,也可以实现自己的配置,并使用@EnableWebMvc注解
HttpMessageConverters
Spring MVC使用HttpMessageConverter来转换HTTP请求和响应中的数据,比如对象自动转换成JSON或XML对象,这些转换的处理类都是SpringBoot默认都配置好了,你不需要做任何配置就可以实现数据的转换,当然也提供了自定义HttpMessageConverters的方法,上下文中出现的所有HttpMessageConverter bean都会被添加到converter列表,你可以通过这种方式来覆盖默认的转换器列表。下面通过一个例子来演示一下如何自定义HttpMessageConverter
默认转换json的转换器是使用的jackson,我们先来看看默认的例子
@RestController @SpringBootApplication public class SpringMvcGuide { @RequestMapping("/getStudent") public Student getStudent(){ Student stu = new Student(); stu.setName("小明"); return stu; } public static void main(String[] args){ SpringApplication.run(SpringMvcGuide.class,args); } }
public class Student { private String name; private int age; private String address; /** 省略getter、setter方法 **/ }
启动程序,访问//localhost:8080/getStudent ,页面显示
{"name":"小明","age":0,"address":null}
可以看到Student对象被转换成json字符串,age默认值为0,address默认为null
下面我们替换成fastjson,并且String类型的默认值为空字符串
首先引入依赖
compile 'com.alibaba:fastjson:1.2.58'
添加HttpMessageConverter配置类
@Configuration public class HttpMessageConverterConfig { @Bean public HttpMessageConverter fastJsonHttpMessageConverter(){ FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); SerializerFeature[] serializerFeatures = new SerializerFeature[]{ SerializerFeature.QuoteFieldNames,//输出Key是否包含双引号 SerializerFeature.WriteMapNullValue,//是否输出为null的字段,若为null则显示该字段 SerializerFeature.WriteNullNumberAsZero,//数字若为null,输出0 SerializerFeature.WriteNullListAsEmpty, //list为null,输出[] SerializerFeature.WriteNullStringAsEmpty,//String为null,输出"" SerializerFeature.WriteNullBooleanAsFalse,//boolean为null,输出false SerializerFeature.WriteDateUseDateFormat,//Date的日期转换器 SerializerFeature.DisableCircularReferenceDetect //循环引用 }; fastJsonConfig.setSerializerFeatures(serializerFeatures); fastJsonConfig.setCharset(Charset.forName("UTF-8")); fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); List<MediaType> mediaTypeList = new ArrayList<MediaType>(); mediaTypeList.add(MediaType.APPLICATION_JSON); fastJsonHttpMessageConverter.setSupportedMediaTypes(mediaTypeList); return fastJsonHttpMessageConverter; } }
重新启动程序,访问//localhost:8080/getStudent,页面显示
{"address":"","age":0,"name":"小明"}
可以看到address默认值已经变成空字符串,说明我们引入的fastjson生效了
自定义Json序列化和反序列化
如果你使用Jackson来序列化和反序列化json数据,你可能需要写自己的JsonSerializer和JsonDeserializer类,自定义序列化器通常通过Module注册到Jackson,但SpringBoot提供了@JsonComponent注解能轻松的将序列化器注册为Spring Bean
您可以直接在JsonSerializer、JsonDeserializer或KeyDeserializer实现上使用@JsonComponent注释。还可以在包含序列化器/反序列化器的内部类上使用它,如下面的示例所示
@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版本提供了有用的替代方案。详情可以自行查阅JsonObjectSerializer和JsonObjectDeserializer,这里不再展开
静态内容
默认情况下,Spring Boot从类路径中的/static(/public,/resources,/META-INF/resources)目录或ServletContext的根目录中提供静态内容。它是使用Spring MVC中的ResourceHttpRequestHandler来实现的, 这样你就可以通过添加自己的WebMvcConfigurer和覆盖addResourceHandlers方法来进行自定义
在独立的web应用程序中,容器中的默认servlet也被启用,并充当后备,如果Spring决定不处理ServletContext,则从ServletContext的根提供内容。大多数情况下,这种情况不会发生(除非您修改了默认的MVC配置),因为Spring总是可以通过DispatcherServlet处理请求
默认情况下,资源映射到/**上,但是您可以使用spring.mvc.static-path-pattern属性来进行调整。例如,将所有资源重新定位到/resources/**,可以通过如下配置实现
spring: mvc: static-path-pattern: "/resources/**"
还可以使用spring.web.resources来定制静态资源位置,除了前面提到的静态资源位置之外,Webjars内容也是一个特殊情况,任何/webjars/**路径的资源都是从jar文件中提供的,前提是它们是以webjars格式打包的
模板引擎
除了REST web服务之外,还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持多种模板技术 (包括Thymeleaf、FreeMarker和jsp), 此外,许多其他模板引擎也包含它们自己的Spring MVC集成。
Spring Boot支持以下模板引擎的自动配置:
- FreeMarker
- Groovy
- Thymeleaf
- Mustache
当您使用上述模板引擎之一时,将会自动从src/main/resources/templates目录下获取模板
异常/错误的处理
默认情况下,Spring Boot提供了一个/error映射,它以一种合理的方式处理所有错误,并在servlet容器中注册为一个“全局”错误页面。对于机器客户端来说,它生成一个JSON响应,其中包含错误、HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“whitelabel”错误视图,它以HTML格式呈现相同的数据
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Mar 03 22:46:49 CST 2021
There was an unexpected error (type=Not Found, status=404).
对于返回json格式的请求来说,可以定义一个带@ControllerAdvice注释的类,来处理特定的Controller异常信息,如下面的示例所示
@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); } }
对于返回页面的请求,我们一般会定制自己的异常页面,例如404、500这些异常的状态码都会定位到对应的页面。
比如要对404定制一个html页面,可以把页面放到对应的目录下
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
再比如要对500定制一个FreeMarker页面
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 500.ftlh
+- <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
跨域支持
跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,它允许您以灵活的方式指定哪种跨域请求得到授权,而不是使用一些不太安全、功能不太强大的方法,如IFRAME或JSONP。
从4.2版开始,Spring MVC支持CORS。在Spring Boot应用程序中使用带有@CrossOrigin注释的Controller方法不需要任何特定的配置。通过使用自定义的addcorsmapping (CorsRegistry)方法注册WebMvcConfigurer bean,可以定义全局CORS配置,如下面的示例所示:
@Configuration(proxyBeanMethods = false) public class MyConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }; } }
到此这篇关于SpringBoot中MVC的自动配置详解的文章就介绍到这了,更多相关MVC的自动配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!