静态/动态资源访问
优先找动态资源,再找静态资源
静态资源访问前缀
spring:
mvc:
#这个是静态资源访问的前缀,所有需要访问的前缀都需要拼这个才能访问
static-path-pattern: /res/**
resources:
#这个是静态资源的规定文件夹,配置后只有该文件夹下才能被访问
static-location: classpath:/res/
欢迎页支持
- 方式一: 建一个index.html
- 方式二: 建一个@RequestMapping(“index”) return “/xxx”;
ICON支持
在静态资源文件夹下,放入favicon.ico就可以有图标
静态资源配置原理
- SpringMVC自动配置类WebMvcAutoConfiguration,生效
1、一个配置类(@Configration修饰的类)只有一个有参构造器时,那么所有参数都会从容器中确定
WebMvcAutoConfiguration.class
// 相当于给WebMvc自动装载的适配器从IOC中获取资源
// WebProperties 获取和spring.resources绑定的所以的值的对象
// WebMvcProperties 绑定了spring.mvc的所有的值的对象
// ListableBeanFactory Spring的bean工厂
// HttpMessageConverters 参数处理器
// ResourceHandlerRegistrationCustomizer 资源处理器的自定义器
// DispatcherServletPath DispatcherServlet 路径
// ServletRegistrationBean 给应用注册的 Servlet Filter
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties,
WebMvcProperties mvcProperties, ListableBeanFactory beanFactory,
@Lazy HttpMessageConverters messageConverters,
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
this.resourceProperties = resourceProperties;
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConverters = messageConverters;
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider
.getIfAvailable();
}
2、静态资源能够生效的真正原因
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
/** 这里第一个IF 判断IOC(配置文件中可配置,默认为true)中
spring.web.add-mapping :true/false
true:允许使用静态资源
false:禁用静态资源,所有的静态页,图片全部404
**/
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
ServletContext servletContext = getServletContext();
/**
两个addResourceHanlder 就是增加两个静态资源处理器
第一个addRe……说的是给IOC注册webjars/**等两个路径的静态资源
第二个addRe……说的是给spring.mvc.staticPathPattern配置的静态资源
新版默认值为/**,可以.properties或.yml配置 【图1】
**/
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (servletContext != null) {
registration.addResourceLocations(new ServletContextResource(servletContext, SERVLET_LOCATION));
}
});
}
图1
3、欢迎页的原理
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(
ApplicationContext applicationContext) {
return new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext),
applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
}
//进入new WelcomePageHandlerMapping
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
ApplicationContext applicationContext, Optional<Resource> welcomePage,
String staticPathPattern) {
//第一个if判断,是否存在欢迎页,如果存在就转发到index.html中
if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
logger.info("Adding welcome page: " + welcomePage.get());
setRootViewName("forward:index.html");
}
//第一个if失败的话,就去寻找是否有处理器能够处理index请求,如果有,就请求index方法
else if (welcomeTemplateExists(templateAvailabilityProviders,
applicationContext)) {
logger.info("Adding welcome page template: index");
setRootViewName("index");
}
}
【源码分析】Rest请求处理原理
WebMvcAutoConfiguration中
OrderedHiddenHttpMethodFilter
继承HiddenHttpMethodFilter
如果是表单访问PUT或者DELETE方法时
需要
1、表单需要是POST方式
2、需要配置一个隐藏域
<input type="hidden" name = "_method" value = "PUT"> 声明配置一下,因为源码中
原因如下:
如果不想要_method,自定义的话:
需要自己写一个配置类@Configuration,并且再其中@Bean一个方法,在方法中重新set一下HiddenHttpMethodFilter中的methodParam
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
HiddenHttpMethodFilter filter = new ……;
filter.setMethodParam("自定义的name名");
return filter;
}
【源码分析】请求映射原理
在WebMvcAutoConfiguration发现,底层是SpringMVC的DispatchServlet。
DispatchServlet的底层其实也是一个HttpServlert
其中FramworkSerlet重写了doGet doPost等方法
并且他们的核心方法都用了processRequest->doService
而doSerivce是由DispatchServlet实现的
其核心又是用了一个doDispatch方法
而doDispatch方法中:
- 1、先获取了HandlerMapping 返回了多个HandlerMapping组成执行链HanlerExecutionChain
- 2、其中最核心的是RequestHandlerMapping:它能够找到对应的@Request注解和对应Controller对应方法的关联关系
- 3、根据HandlerAdapter关联关系去匹配当前请求的url的对应方法
- 4、返回对应的Controller里的对应方法去处理