标签:configure view one 示例 body adapter OWIN getname acl
在SpringBoot官网对于SpringMVCde 自动配置介绍
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
The auto-configuration adds the following features on top of Spring’s defaults:
ContentNegotiatingViewResolver
and BeanNameViewResolver
beans.Converter
, GenericConverter
, and Formatter
beans.HttpMessageConverters
(covered later in this document).MessageCodesResolver
(covered later in this document).index.html
support.Favicon
support (covered later in this document).ConfigurableWebBindingInitializer
bean (covered later in this document).If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration
class of type WebMvcConfigurer
but without @EnableWebMvc
. If you wish to provide custom instances of RequestMappingHandlerMapping
, RequestMappingHandlerAdapter
, or ExceptionHandlerExceptionResolver
, you can declare a WebMvcRegistrationsAdapter
instance to provide such components.
If you want to take complete control of Spring MVC, you can add your own @Configuration
annotated with @EnableWebMvc
.
Spring Boot为Spring MVC提供自动配置,且适用于大多数应用程序。
自动配置在Spring默认配置基础上,添加了以下功能:
如果要保留Spring Boot MVC功能并且想要添加其他MVC配置(interceptors,formatters,view controllers和其他功能),可以添加自己的@Configuration类,类型为WebMvcConfigurer,但不包含@EnableWebMvc。如果您希望可以自定义RequestMappingHandlerMapping,RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver实例,则可以声明WebMvcRegistrationsAdapter实例以提供此类组件。
如果您想完全控制Spring MVC,可以使用@EnableWebMvc添加自己的@Configuration注释。
以下正文,对上面标红的内容进行分析
public class WebMvcAutoConfiguration { //-在Springboot启动初始化时,自动装载WebMvcAutoConfiguration类, //其中包括WebMvcAutoConfiguration内部类WebMvcAutoConfigurationAdapter下的ContentNegotiatingViewResolver viewResolver()方法 public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware { @Bean @ConditionalOnBean({ViewResolver.class}) @ConditionalOnMissingBean( name = {"viewResolver"}, value = {ContentNegotiatingViewResolver.class} ) public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver(); resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class)); resolver.setOrder(-2147483648); return resolver; } } }
public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport implements ViewResolver, Ordered, InitializingBean { //2-ContentNegotiatingViewResolver 执行其内部initServletContext()初始化方法,从BeanFactoryUtils中获取全部ViewResolver protected void initServletContext(ServletContext servletContext) { Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values(); ViewResolver viewResolver; if (this.viewResolvers == null) { Iterator var3 = matchingBeans.iterator(); while(var3.hasNext()) { viewResolver = (ViewResolver)var3.next(); if (this != viewResolver) { this.viewResolvers.add(viewResolver); } } } …………………………省略 } //2-当一个请求进来时,调用ContentNegotiatingViewResolver 下的View resolveViewName()方法,,并返回bestView,主要包括beanName参数,即对应渲染的(比如:html)文件名称 @Nullable public View resolveViewName(String viewName, Locale locale) throws Exception { //ContentNegotiatingViewResolver 根据文件名和请求头类型来决定返回什么样的View。而mediaTypes这个属性存储了 你请求后缀名 或者 参数 所对应 的mediaType RequestAttributes attrs = RequestContextHolder.getRequestAttributes(); List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest()); if (requestedMediaTypes != null) { //获取候选视图对象 List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes); //选择一个最适合的视图对象 View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs); if (bestView != null) { //返回视图对象 return bestView; } } ……………省略 } //2-1-获取候选视图对象 private List<View> getCandidateViews(String viewName, Locale locale, List<MediaType> requestedMediaTypes) throws Exception { List<View> candidateViews = new ArrayList(); if (this.viewResolvers != null) { //获取全部视图解析器 Iterator var5 = this.viewResolvers.iterator(); //筛选出候选View while(var5.hasNext()) { …………………………省略 while(var11.hasNext()) { String extension = (String)var11.next(); String viewNameWithExtension = viewName + ‘.‘ + extension; view = viewResolver.resolveViewName(viewNameWithExtension, locale); if (view != null) { candidateViews.add(view);//获取view } } } } return candidateViews; } }
1-3-1-自定义解析其源码
@SpringBootApplication public class SpringbootdemoApplication { public static void main(String[] args) { SpringApplication.run(SpringbootdemoApplication.class, args); } //在Springboot启动时,加载自定义的MyViewResolver类 @Bean public ViewResolver myViewResolver(){ return new MyViewResolver(); } //(这里为了方便,在启动类下写了一个内部类) //MyViewResolver实现接口类ViewResolver private static class MyViewResolver implements ViewResolver{ @Override public View resolveViewName(String s, Locale locale) throws Exception { return null; } } }
1-3-2-源码解析
1-3-3-使用结果:在Spring分发请求时,发现自定义的MyViewResolver被被加载
//1-controller层 @Controller public class DemoController { Logger log = LoggerFactory.getLogger(DemoController.class); @RequestMapping(value="get/student") public String getStudent(Student student,Model model){ log.debug("student: " + student); model.addAttribute("student",student); return "student"; } } //2-自定义converter @Configuration public class StringToStudentConverrter implements Converter<String,Student> { @Override public Student convert(String s) { //student=tyj-18 String[] split = s.split("-"); Student student = new Student(split[0],Integer.parseInt(split[1])); return student; } }
//3-html示例
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div th:text="${student.name}"></div> <div th:text="${student.age}"></div> <strong>success!</strong> </body> </html>
4-2-自定义HttpMessageConverters
//1-自定义HttpMessageConverters public class MyMessageConveter extends AbstractHttpMessageConverter<Student>{ public MyMessageConveter() { //Content-Type= application/xxx-tyj super(new MediaType("application", "xxx-tyj", Charset.forName("UTF-8"))); } @Override protected boolean supports(Class<?> aClass) { // 表明只处理UserEntity类型的参数。 return Student.class.isAssignableFrom(aClass); } //重写readlntenal 方法,处理请求的数据。代码表明我们处理由“-”隔开的数据,并转成 Student类型的对象。 @Override protected Student readInternal(Class<? extends Student> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException { String content = StreamUtils.copyToString(httpInputMessage.getBody(), Charset.forName("UTF-8")); String[] split = content.split("-"); return new Student(split[0],Integer.parseInt(split[1])); } //重写writeInternal ,处理如何输出数据到response。 @Override protected void writeInternal(Student student, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException { String out = "hello: " +student.getName() + " ,你今年" + student.getAge() + "了么?"; httpOutputMessage.getBody().write(out.getBytes()); } }
//2-加载自定义的MyMessageConveter @Configuration public class MySpringBootConfig { @Bean public MyMessageConveter MyMessageConveter (){ return new MyMessageConveter(); } }
//3-controller @Controller public class DemoController { @RequestMapping(value="hello/student",method = POST) @ResponseBody public Student helloStudent(@RequestBody Student student){ return student; } }
接口测试 URL:POST localhost:8080/hello/student header: Content-Type = application/xxx-tyj body: tyj-21 返回值:hello: tyj ,你今年21了么?
@Configuration public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter { // 添加converter的第一种方式,代码很简单,也是推荐的方式 // 这样做springboot会把我们自定义的converter放在顺序上的最高优先级(List的头部) // 即有多个converter都满足Accpet/ContentType/MediaType的规则时,优先使用我们这个 @Bean public MyMessageConveter MyMessageConveter (){ return new MyMessageConveter(); } // 添加converter的第二种方式 // 通常在只有一个自定义WebMvcConfigurerAdapter时,会把这个方法里面添加的converter(s)依次放在最高优先级(List的头部) // 虽然第一种方式的代码先执行,但是bean的添加比这种方式晚,所以方式二的优先级 大于 方式一 @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // add方法可以指定顺序,有多个自定义的WebMvcConfigurerAdapter时,可以改变相互之间的顺序 // 但是都在springmvc内置的converter前面 converters.add(new MyMessageConveter()); } // 添加converter的第三种方式 // 同一个WebMvcConfigurerAdapter中的configureMessageConverters方法先于extendMessageConverters方法执行 // 可以理解为是三种方式中最后执行的一种,不过这里可以通过add指定顺序来调整优先级,也可以使用remove/clear来删除converter,功能强大 // 使用converters.add(xxx)会放在最低优先级(List的尾部) // 使用converters.add(0,xxx)会放在最高优先级(List的头部) @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new MyMessageConveter()); } }
参考资料
2-http://www.cnblogs.com/huhx/p/baseusespringbootconverter1.html
3-https://www.cnblogs.com/page12/p/8166935.html
4-http://www.cnblogs.com/hhhshct/p/9676604.html
标签:configure view one 示例 body adapter OWIN getname acl
原文地址:https://www.cnblogs.com/wobuchifanqie/p/10123118.html