管理及扩展SpringMVC组件 1. 管理SpringMVC的组件 1,前端控制器的自动管理
找到WebMvcAutoConfiguration
,找到DispatcherServletAutoConfiguration.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { public static final String DEFAULT_PREFIX = "" ; public static final String DEFAULT_SUFFIX = "" ; private static final String SERVLET_LOCATION = "/" ; ... }
DispatcherServletAutoConfiguration
,public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties)
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration { public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet" ; public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration" ; @Configuration(proxyBeanMethods = false) @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) protected static class DispatcherServletConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet (WebMvcProperties webMvcProperties) { DispatcherServlet dispatcherServlet = new DispatcherServlet (); dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound()); dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails()); return dispatcherServlet; } ... } @Configuration(proxyBeanMethods = false) @Conditional(DispatcherServletRegistrationCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) @Import(DispatcherServletConfiguration.class) protected static class DispatcherServletRegistrationConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServletRegistrationBean dispatcherServletRegistration (DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) { DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean (dispatcherServlet, webMvcProperties.getServlet().getPath()); registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup()); multipartConfig.ifAvailable(registration::setMultipartConfig); return registration; } } ... }
1 2 3 4 @Component和@Bean注解 1.@Component不能初始化属性值,@Bean可以初始化属性值 2.@Component比@Bean的优先级高 3.当class类位于jar中,无法添加@Component注解,这时可以通过@Bean注解向IOC容器中创建一个该类的对象
2,控制器[controller]的自动管理
直接扫描@ComponentScan(basePackages = {})
3,视图解析器的自动管理
创建视图解析器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public class WebMvcAutoConfiguration { public static final String DEFAULT_PREFIX = "" ; public static final String DEFAULT_SUFFIX = "" ; ... public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer { ... @Bean @ConditionalOnMissingBean public InternalResourceViewResolver defaultViewResolver () { InternalResourceViewResolver resolver = new InternalResourceViewResolver (); resolver.setPrefix(this .mvcProperties.getView().getPrefix()); resolver.setSuffix(this .mvcProperties.getView().getSuffix()); return resolver; } @Bean @ConditionalOnBean(View.class) @ConditionalOnMissingBean public BeanNameViewResolver beanNameViewResolver () { BeanNameViewResolver resolver = new BeanNameViewResolver (); resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10 ); return resolver; } @Bean @ConditionalOnBean(ViewResolver.class) @ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class) public ContentNegotiatingViewResolver viewResolver (BeanFactory beanFactory) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver (); resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class)); resolver.setOrder(Ordered.HIGHEST_PRECEDENCE); return resolver; } ... } ... }
contentNegotiationViewResolver是一个管理所有视图解析器的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ContentNegotiatingViewResolver { ... @Override protected void initServletContext (ServletContext servletContext) { Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), ViewResolver.class).values(); ... } ... }
4.自定义前缀和后缀
SpringBoot默认不支持jsp
application.yml
1 2 3 4 5 6 spring: mvc: view: prefix: /WEB-INF/view/ suffix: .jsp
创建jsp页面
1 2 3 4 5 6 7 8 9 10 11 12 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8" > <title>Insert title here</title> </head> <body> This is a jsp file. </body> </html>
在pom文件中加入相关依赖
1 2 3 4 5 6 <dependency > <groupId > org.apache.tomcat.embed</groupId > <artifactId > tomcat-embed-jasper</artifactId > <scope > provided</scope > </dependency >
创建controller
1 2 3 4 5 6 7 8 9 10 @Controller @RequestMapping("index") public class IndexController { @RequestMapping("hello") public String hello () { return "hello" ; } }
5.文件上传和下载的自动配置
查看MultipartAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class }) @ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true) @ConditionalOnWebApplication(type = Type.SERVLET) @EnableConfigurationProperties(MultipartProperties.class) public class MultipartAutoConfiguration { ... }
查看MultipartProperties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @ConfigurationProperties(prefix = "spring.servlet.multipart", ignoreUnknownFields = false) public class MultipartProperties { private boolean enabled = true ; private String location; private DataSize maxFileSize = DataSize.ofMegabytes(1 ); private DataSize maxRequestSize = DataSize.ofMegabytes(10 ); ... }
application.yml
1 2 3 4 5 6 servlet: multipart: enabled: true location: max-file-size: 10MB
文件大小的单位必须为MB(大写)
6.消息转化和格式化转化
6.1 消息转化【接收页面参数并类型转化】
1 2 3 4 5 6 7 8 9 public class WebMvcAutoConfiguration { public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer { @Override public void addFormatters (FormatterRegistry registry) { ApplicationConversionService.addBeans(registry, this .beanFactory); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class ApplicationConversionService extends FormattingConversionService { public static void addBeans (FormatterRegistry registry, ListableBeanFactory beanFactory) { Set<Object> beans = new LinkedHashSet <>(); beans.addAll(beanFactory.getBeansOfType(GenericConverter.class).values()); beans.addAll(beanFactory.getBeansOfType(Converter.class).values()); beans.addAll(beanFactory.getBeansOfType(Printer.class).values()); beans.addAll(beanFactory.getBeansOfType(Parser.class).values()); for (Object bean : beans) { if (bean instanceof GenericConverter) { registry.addConverter((GenericConverter) bean); } else if (bean instanceof Converter) { registry.addConverter((Converter<?, ?>) bean); } else if (bean instanceof Formatter) { registry.addFormatter((Formatter<?>) bean); } else if (bean instanceof Printer) { registry.addPrinter((Printer<?>) bean); } else if (bean instanceof Parser) { registry.addParser((Parser<?>) bean); } } } }
标出的部分为接收前台参数,将前台参数进行类型转换。
6.2 消息格式化转化【接收页面参数并格式化转化】
1 2 3 4 5 spring: mvc: format: date: yyyy-MM-dd
1 2 3 4 5 6 7 8 9 10 11 12 @Data @AllArgsConstructor @NoArgsConstructor public class Student { private Integer id; private String name; @DateTimeFormat(pattern = "yyyy/MM/dd-HH:mm:ss") private Date birthday; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 @Controller @RequestMapping("index") public class IndexController { @RequestMapping("showDateTime") public String showDateTime (Date date) { System.out.println(date); return "hello" ; } @RequestMapping("showDateTime2") public String showDateTime2 (@DateTimeFormat(pattern = "yyyy:MM:dd:HH:mm:ss") Date date) { System.out.println(date); return "hello" ; } @RequestMapping(value = "showStudentInfo", method = RequestMethod.GET) public String showStudentInfo (Student student) { System.out.println(student); return "hello" ; } }
7.欢迎页面的默认配置
以前欢迎页面的配置:web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <welcome-file-list > <welcome-file > index.jsp</welcome-file > <welcome-file > login.jsp</welcome-file > <welcome-file > index.html</welcome-file > <welcome-file > index.htm</welcome-file > <welcome-file > default.html</welcome-file > <welcome-file > default.htm</welcome-file > <welcome-file > default.jsp</welcome-file > </welcome-file-list >
欢迎页面默认为src/main/resources/static/
目录下的index.html
1 2 3 4 5 6 7 8 9 10 <!DOCTYPE html > <html > <head > <meta charset ="UTF-8" > <title > Insert title here</title > </head > <body > This is the welcome index.html. </body > </html >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public class WebMvcAutoConfiguration { public static class EnableWebMvcConfiguration { @Bean public WelcomePageHandlerMapping welcomePageHandlerMapping (ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) { WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping ( new TemplateAvailabilityProviders (applicationContext), applicationContext, getWelcomePage(), this .mvcProperties.getStaticPathPattern()); welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider)); welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations()); return welcomePageHandlerMapping; } private Resource getWelcomePage () { for (String location : this .resourceProperties.getStaticLocations()) { Resource indexHtml = getIndexHtml(location); if (indexHtml != null ) { return indexHtml; } } ServletContext servletContext = getServletContext(); if (servletContext != null ) { return getIndexHtml(new ServletContextResource (servletContext, SERVLET_LOCATION)); } return null ; } private Resource getIndexHtml (String location) { return getIndexHtml(this .resourceLoader.getResource(location)); } private Resource getIndexHtml (Resource location) { try { Resource resource = location.createRelative("index.html" ); if (resource.exists() && (resource.getURL() != null )) { return resource; } } catch (Exception ex) { } return null ; } } }