关于Spring MVC的详细学习可以参考系列博客《Spring MVC使用篇系列博客传送门》
在Spring Boot中使用Spring MVC仅需在pom文件中引入spring-boot-starter-web即可。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
在Spring Boot的启动机制下启用Spring MVC,它会在开始初始化一些Spring MVC的重要组件,如DispatcherServlet、HandlerAdapter的实现类RequestMappingHandlerAdapter等组件对象。
关于这些组件的初始化,我们可以在spring-web-xxx.jar包的属性文件DispatcherServlet.properties,它定义的对象都是在Spring MVC开始时就初始化,并且存放在Spring IoC容器中的。其源码如下:
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.
# 国际化解析器
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
# 主题解析器
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
# HandlerMapping实例
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
org.springframework.web.servlet.function.support.RouterFunctionMapping
# 处理器适配器
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
org.springframework.web.servlet.function.support.HandlerFunctionAdapter
# 处理器异常解析器
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
# 策略师徒名称转换器,当你没有返回视图逻辑名称的时候,通过它可以生产默认的视图名称
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
# 视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
# FlashMap管理器。不常用,不再讨论
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
通过上面的代码我们可知,这些组件会在Spring MVC得到初始化,所以我们并不需要太多的配置就能够开发Spring MVC程序,尤其是在Spring Boot中,更是如此。
我们可以通过Spring Boot的配置来定制这些组件的初始化。
在Servlet 3.0规范中,web.xml再也不是一个必须的配置文件。为了适应这个规范,Spring MVC从3.1版本开始也进行了支持,也就是我们已经不再需要通过任何的XML去配置Spring MVC的运行环境,正如Spring Boot的宗旨,消除XML的繁杂配置。
为了支持对Spring MVC的配置,Spring提供了接口WebMvcConfigurer,这是一个基于Java 8的接口,所以其大部分方法都是default类型的,但是它们都是空实现,这样开发者只需要实现这个接口,重写需要自定义的方法即可,这样就很方便进行开发了。
在Spring Boot中,自定义是通过配置类WebMvcAutoConfiguration定义的,它有一个静态的内部类WebMvcAutoConfigurationAdapter,通过它Spring Boot就自动配置了Spring MVC的初始化。
在WebMvcAutoConfigurationAdapter类中,它会读入Spring配置Spring MVC的属性来初始化对应组件,这样能够在一定程度上实现自定义。不过应该首先明确可以配置哪些内容。Spring Boot关于Spring MVC可以配置的内容如下:
这些配置项将会被Spring Boot的机制读入,然后使用WebMvcAutoConfigurationAdapter去定制初始化。一般而言,我们只需要配置少数的选项就能够使得Spring MVC工作了。
同时,对于上面的这些配置,我们也可以选择实现接口WebMvcConfigurer加入自己定义的方法就可以了,毕竟这个接口是Java 8的接口,其本身已经提供了default方法,对其定义的方法做了空实现。
关于IDEA中创建的Maven项目没有webapp目录的问题,可以参考博客《IDEA 新建MAVEN项目不是用maven骨架 没有webapp目录解决办法
》,按照步骤即可解决。这里值得注意的是,在Spring Boot的项目中,webapp目录要放入src/main目录下。
实际上,Spring Boot内部对JSP的支持并不理想,也不推荐使用,但JSP技术作为一个很常规的技术这里还是有必要说一下的,因为这里面仍然存在着很深的坑,爬坑不易。
第一,想要在Spring Boot中与Spring MVC的环境下整合JSP,即在Spring MVC中使用JSP作为视图。这里需要在pom文件下引入如下依赖:
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<scope>providedscope>
dependency>
关于上面依赖中scope标签的作用,以及属性为provided还是compile,请大家自行百度了解,这里不再赘述。
第二,在路径src/main/webapp/WEB-INF/jsp下,创建测试页面index.jsp,具体路径与代码如下:
<%@ page pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta charset="UTF-8">
<title>Indextitle>
head>
<body>
<h1>Hello JSP Index Test!h1>
body>
第三,在application.properties配置文件中,对Spring MVC自动配置的InternalResourceViewResolver视图解析器进行配置,配置其前后缀属性如下:
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
上面的配置中,关于JSP页面前缀路径的配置需要注意:最后面的斜杠是不能省略的,在拼接的时候是根据prefix+名称+suffix。而最开始的斜杠则涉及到了相对路径与绝对路径的问题,关于此问题可查看系列博客《Spring MVC使用篇系列博客传送门》 中的第五篇《Spring MVC使用篇(五)—— 请求路径问题》中关于相对路径和绝对路径的讲解。
第四,在controller包中创建名为TestController的控制器类,具体如下:
package com.ccff.springboot.demo.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by wangzhefeng01 on 2019/8/14.
*/
@Controller
@RequestMapping("/test")
public class TestController {
@GetMapping("/testJSP")
public String testJSP(){
return "index";
}
}
第五,此时我们便可以执行Spring Boot的启动类,运行main方法,在浏览器内输入对应的请求后验证整合JSP是否成功了。
由于博客记录期间使用的是Intellij Idea 15,在直接执行启动类的main方法时发现莫名其妙地无法启动项目,结果如下:
这里就需要特别说明一下这个问题,这个坑有点恶心
首先让我们来换一种Spring Boot的启动方式,打开Idea中的Maven Projects视图窗口 -> 选择需要启动的module -> 选择Plugins -> 选择spring-boot -> 双击执行spring-boot:run命令。此时发现项目居然能够成功启动,且验证结果成功。
那么问题来了,同样的代码,采用不同的启动方式为什么结果会如此不同呢? 经过查找资料,发现答案如下:
在 Intellij Idea 15 中使用maven时,所有 scope 为 provided 的依赖都是不会被加入到 classpath 中的,目前该bug尚未被修复(bug report)。如果你的web应用是部署到容器中的,那么这个bug不会影响使用,因为web应用中provided的依赖在容器运行时会被提供。如果你做Spring Boot开发,有带provided的依赖时,直接在IDE中运行项目会导致ClassNotFound异常。
目前针对该问题的解决方案就是通过Maven Projects中的Plugins中的spring-boot:run命令启动。
下面是两篇参考博客,贴出来大家可以看一下:
由于Spring MVC并不是本系列博客介绍的重点,因此这里对涉及的Spring MVC常用注解仅进行简单罗列,至于某个注解的具体使用方法,请参考系列博客《Spring MVC使用篇系列博客传送门》中对Spring MVC的详细讲解。
在Spring Boot中提供了几种默认的配置方式,在启动项目后我们可以直接通过浏览器请求这些路径来访问对应的静态资源。
classpath:/META-INF/resources
classpath:/resources
classpath:/static
classpath:/public
备注说明: "/"=>当前项目的根路径
上面这几个都是静态资源的映射路径,优先级顺序为:META-INF/resources > resources > static > public
例如,我们在src/main/resources/static/static-images/下放入了一张图片tmac.jpg,路径如下所示:
当我们运行项目后,在浏览器内输入请求URL后便能够查看到该图片:
这里需要说明一点的是:,如果我们根据之前提到的内容在src/main目录下创建了webapp目录,如这里创建了如下路径,并放入一张图片:
实际上,这里已经和Spring Boot的配置无关了,因为这里就是一个web项目的路径,通过浏览器的相应URL也是能访问到的,但是不要相互混淆。
有时候,我们会需要使用自定义的路径来存放静态资源,例如在src/main/resources/assert/路径下也存在着一张图片penta-kill.jpg,显然,仅仅通过Spring Boot的默认设置是访问不到这张图片的。
重写addResourceHandlers方法有两个方式,分别为:
package com.ccff.springboot.demo.springmvc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created by wangzhefeng01 on 2019/8/13.
*/
@SpringBootApplication
public class SpringMVCApplication implements WebMvcConfigurer {
/**
* addResourceHandler: 指的是对外暴露的访问路径
* addResourceLocations: 指的是文件放置的目录
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assert/**").addResourceLocations("classpath:/assert/");
}
public static void main(String[] args) {
SpringApplication.run(SpringMVCApplication.class,args);
}
}
package com.ccff.springboot.demo.springmvc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
* Created by wangzhefeng01 on 2019/8/13.
*/
@SpringBootApplication
public class SpringMVCApplication extends WebMvcConfigurationSupport {
/**
* addResourceHandler: 指的是对外暴露的访问路径
* addResourceLocations: 指的是文件放置的目录
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assert/**").addResourceLocations("classpath:/assert/");
}
public static void main(String[] args) {
SpringApplication.run(SpringMVCApplication.class,args);
}
}
在浏览器内再次输入URL,测试结果如下:
通过实现该接口的其他方法,也可以对Spring MVC进行其他相应配置。例如,重写addViewControllers方法可以设置默认欢迎页等。
在application.properties中配置静态资源路径,即在spring.resources.static-locations后面追加一个静态资源的配置路径。具体如下:
# 静态文件请求匹配方式
spring.mvc.static-path-pattern=/**
# 修改默认的静态寻址资源目录 多个使用逗号分隔
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/assert/
在浏览器内再次输入URL,测试结果如下:
这里需要注意一下: 这个URL与上一小节的URL是不一致的。