spring-boot-starter-web
Spring Boot提供了spring-boot-starter-web为Web开发予以支持,spring-boot-starter-web为我们提供了嵌入的Tomcat以及Spring MVC的依赖。
Spring MVC自动配置
Spring Boot为Spring MVC提供适用于多数应用的自动配置功能。在Spring默认基础上,自动配置添加了以下特性:
- 引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
- 对静态资源的支持,包括对WebJars的支持。
- 自动注册Converter,GenericConverter,Formatter beans。
- 对HttpMessageConverters的支持。
- 自动注册MessageCodeResolver。
- 对静态index.html的支持。
- 对自定义Favicon的支持。
如果想要自己完全控制WebMVC配置,就需要在@Configuration注解的配置类上增加@EnableWebMvc注解。增加该注解以后WebMvcAutoConfiguration中配置就不会生效,你需要自己来配置需要的每一项。这种情况下的配置还是要多看一下WebMvcAutoConfiguration类(上面7个默认配置就在此处设定)。
@EnableWebMvc
@Configuration
public class TestMvc {
···
}
如果想保留Spring Boot MVC的特性(应用默认配置),并只是添加自定义的MVC配置(拦截器,formatters,视图控制器等),你可以自定义一个配置类并继承WebMvcConfigurerAdapter类。在类中通过配置@Bean方法来注册自己想要的bean甚至是自定义的bean。或重写父类某一方法实现自己的处理逻辑
@Configuration
public class CustomizeWebMvcConfiguration extends WebMvcConfigurerAdapter {
···
@Bean
public BeanNameViewResolver beanNameViewResolver () {
return new BeanNameViewResolver(); // 示例代码
}
/* 一个道理
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjar/**").addResourceLocations("classpath:/webjar/");
super.addResourceHandlers(registry);
}
···
}
当你使用@EnableWebMvc来配置spring mvc时,会把WebMvcConfigurationSupport当成配置文件来用,将其中所有标识有@Bean注解的方法配置成bean,这就成了Spring mvc的默认配置
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
····
}
各个组件都是可以定制化的,在WebMvcConfigurationSupport是通过模板方法模式来实现的,在各个发布成Bean的方法中(@Bean),都调用了自定义组件的抽象方法,所以可以在其在子类中对这些组件进行覆盖,如:
对HandlerAdapter组件,有addInterceptors(InterceptorRegistry registry)可以添加自己的拦截器;
-
对conversionService组件,有addFormatters(FormatterRegistry registry)可以添加自己的类型转换器;
···
从而实现定制化。
上面提到子类,Spring mvc提供的默认实现是DelegatingWebMvcConfiguration,覆盖父类的方法之前,它会寻找容器中所有的WebMvcConfigurer实现类,将所有WebMvcConfigurer实现类中的配置组合起来,组成一个超级配置,再对WebMvcConfigurationSupport中对应的发布成Bean的方法进行覆盖。这样,WebMvcConfigurationSupport中的bean配置发布时,就会把这所有自定义配置都带上了。
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
···
}
总的来说就是,WebMvcConfigurationSupport负责bean的发布。分派自己的子类DelegatingWebMvcConfiguration去寻找用户所有实现了WebMvcConfigurer接口的实现类。并将用户所有发布成Bean的方法组合起来。交还给WebMvcConfigurationSupport统一发布并配置。
静态文件
默认情况下,Spring Boot从classpath下一个叫/static(/public,/resources或/META-INF/resources)的文件夹或从ServletContext根目录提供静态内容。(这几个都是静态资源的映射路径,优先级顺序为:META-INF/resources > resources > static > public)
对应的配置文件配置如下:
# 默认映射,默认值为 /**
spring.mvc.static-path-pattern=
# 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
spring.resources.static-locations=这里设置要指向的路径,多个使用英文逗号隔开
可以通过修改spring.mvc.static-path-pattern来修改默认的映射,例如改成/thymeleaf/**,那运行的时候访问 http://lcoalhost:8080/thymeleaf/index.html 才对应到index.html页面。
这使用了Spring MVC的ResourceHttpRequestHandler,所以你可以通过添加自己的WebMvcConfigurerAdapter并覆写addResourceHandlers方法来改变这个行为(加载静态文件)。
在一个单独的web应用中,容器默认的servlet是开启的,如果Spring决定不处理某些请求,默认的servlet作为一个回退(降级)将从ServletContext根目录加载内容。大多数时候,这不会发生(除非你修改默认的MVC配置),因为Spring总能够通过DispatcherServlet处理请求。
此外,上述标准的静态资源位置有个例外情况是Webjars内容。任何在/webjars/**路径下的资源都将从jar文件中提供,只要它们以Webjars的格式打包。
注:如果你的应用将被打包成jar,那就不要使用src/main/webapp文件夹。尽管该文件夹是一个共同的标准,但它仅在打包成war的情况下起作用,并且如果产生一个jar,多数构建工具都会静悄悄的忽略它
默认实现类:
class WebMvcConfigurerComposite implements WebMvcConfigurer {
···
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addResourceHandlers(registry);
}
···
}
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
···
@Bean
public HandlerMapping resourceHandlerMapping() {
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
this.servletContext, mvcContentNegotiationManager());
// 关键代码
addResourceHandlers(registry);
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
if (handlerMapping != null) {
handlerMapping.setPathMatcher(mvcPathMatcher());
handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
handlerMapping.setInterceptors(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
handlerMapping.setCorsConfigurations(getCorsConfigurations());
}
else {
handlerMapping = new EmptyHandlerMapping();
}
return handlerMapping;
}
···
}
扩展类:
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
···
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
···
}
模板引擎
Spring Boot支持多种模版引擎包括:
- FreeMarker
- Groovy
- Thymeleaf(官方推荐)
JSP技术Spring Boot官方是不推荐的:
- Tomcat 只支持war的打包方式,不支持可执行的jar。
- Jetty 嵌套的容器不支持jsp
- Undertow
- 创建自定义error.jsp页面不会覆盖错误处理的默认视图,而应该使用自定义错误页面
当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates
。
Thymeleaf模板引擎
Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。与其它模板引擎相比,Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用。它的功能特性如下:
- Spring MVC中@Controller中的方法可以直接返回模板名称,接下来Thymeleaf模板引擎会自动进行渲染
- 模板中的表达式支持Spring表达式语言(Spring EL)
- 表单支持,并兼容Spring MVC的数据绑定与验证机制
- 国际化支持
引入依赖
<!--thymeleaf模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
需要注意的是:
spring-boot-starter-thymeleaf会自动包含spring-boot-starter-web,所以我们就不需要单独引入web依赖了。
Model
@Data
@AllArgsConstructor
public class User {
private String username;
private String password;
}
Controller
@Controller
@RequestMapping(value = "/thymeleaf")
public class ThymeleafController {
@RequestMapping(path = "/", method = RequestMethod.GET)
public ModelAndView index() {
List<User> userList = new ArrayList<User>();
User user = new User("jyg", "jyg");
userList.add(user);
user = new User("lyn", "lyn");
userList.add(user);
ModelAndView modelAndView = new ModelAndView("index.html");
modelAndView.addObject("userList", userList);
return modelAndView;
}
}
Html
- 首先通过xmlns:th=”http://www.thymeleaf.org“ 命名 thymeleaf 空间,将静态页面转换为动态的视图,需要进行动态处理的元素将使用“th:”前缀。
xmlns:th="http://www.thymeleaf.org"
-
代码:
<body> <h1>Thymeleaf</h1> <hr/> <table class="table table-striped table-bordered table-hover"> <tr class="info"> <td>用户名</td> <td>密码</td> </tr> <!--/*@thymesVar id="userList" type=""*/--> <tr th:each="user : ${userList}" class="success"> <td th:text="${user.username}">冀永光</td> <td th:text="${user.password}">jiyongguang.</td> </tr> </table> </body>
Thymeleaf 做到了什么
直接访问 index.html :
访问 http://localhost:8080/thymeleaf/:
Thymeleaf 做到了不破坏 Html 自身内容的数据逻辑分离。
Thymeleaf的默认参数配置
# THYMELEAF (ThymeleafAutoConfiguration)
#开启模板缓存(默认值:true)
spring.thymeleaf.cache=true
#Check that the template exists before rendering it.
spring.thymeleaf.check-template=true
#检查模板位置是否正确(默认值:true)
spring.thymeleaf.check-template-location=true
#Content-Type的值(默认值:text/html)
spring.thymeleaf.content-type=text/html
#开启MVC Thymeleaf视图解析(默认值:true)
spring.thymeleaf.enabled=true
#模板编码
spring.thymeleaf.encoding=UTF-8
#要被排除在解析之外的视图名称列表,用逗号分隔
spring.thymeleaf.excluded-view-names=
#要运用于模板之上的模板模式。另见StandardTemplate-ModeHandlers(默认值:HTML5)
spring.thymeleaf.mode=HTML5
#在构建URL时添加到视图名称前的前缀(默认值:classpath:/templates/)
spring.thymeleaf.prefix=classpath:/templates/
#在构建URL时添加到视图名称后的后缀(默认值:.html)
spring.thymeleaf.suffix=.html
#Thymeleaf模板解析器在解析器链中的顺序。默认情况下,它排第一位。顺序从1开始,只有在定义了额外的TemplateResolver Bean时才需要设置这个属性。
spring.thymeleaf.template-resolver-order=
#可解析的视图名称列表,用逗号分隔
spring.thymeleaf.view-names=