SpringMVC 入门
spring MVC 是一个基于servlet api
并且被整合进spring框架的一个web框架。
快速入门
在这一段配置中,可以不用关注这些配置是怎么来的,但是必须要按照这些配置进行配置
maven配置
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
编写Spring-mvc的配置文件
这里的spring-mvc配置文件有一个命名规范
springmvc-servlet.xml : [servletname]-servlet.xml
这个文件是在classpath
下的,即一般在:resourse
路径下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
添加 处理映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
添加 处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
添加 视图解析器
<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
编写控制器类(Controller)
public class TestController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//新建视图和模型
ModelAndView modelAndView = new ModelAndView();
//模拟处理业务
String msg = "Hello Spring MVC";
//添加结果
modelAndView.addObject("msg",msg);
//添加视图名称
modelAndView.setViewName("hello");
return modelAndView;
}
}
注意这个类实现的接口,是org.springframework.web.servlet.mvc.Controller
下的,要不然会报错
配置映射
<bean id="/hello" class="team.controller.TestController"/>
实现视图层
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hello</title>
</head>
<body>
${msg}
</body>
</html>
检查包依赖
- 在
project structure
中检查项目中有没有把依赖的包都添加进去了 - 如果没有添加,进行添加,然后重启tomcat
从请求到响应
第一站 DispatcherServlet
从http请求,然后发送给服务器,服务器交给我们注册的DispatcherServlet
来进行处理,这个地方常常被叫做前端控制器,进行一个简单的处理。
正如我们在web.xml
所配置的那样
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-1-->
<load-on-startup>1</load-on-startup>
</servlet>
这里有个注意点,在配置ServletMapping的时候会出现一个问题
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
url-pattern配置的是/
而不是/*
-
/ 匹配所有的请求(不包括.jsp)
-
/* 匹配所有的请求(包括.jsp)
如果是/*
在后面会出现无法拼接视图名称的问题
在这个类中,真正执行Dispatch分发的是doDispatch(HttpServletRequest request, HttpServletResponse response)
方法
* Process the actual dispatching to the handler. * <p>The handler will be obtained by applying the servlet's HandlerMappings in order. * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters * to find the first that supports the handler class. * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers * themselves to decide which methods are acceptable.
这个方法做如下几件事
- 根据HandlerMapping获取handler
- 根据注册的HandlerAdapter获取HandlerAdapter
- 找到第一个支持handler的类
- 用Handler处理请求
- 做出回应
第二站 UrlHandlerMapping
maps from URLs to beans with names that start with a slash ("/")
通过包含
/
的name
将url
向映射Bean
映射
@Nullable
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// Direct match?
Object handler = this.handlerMap.get(urlPath);
// 下面是通过通配符匹配
...
}
这一步的目的是对url中的内容进行解析,解析出控制器的名字,并且在已经注册的控制器中进行寻找,交给下一站进行使用
DispatcherServlet 源码
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
第三站 ControllerHandlerAdapter
The accesses all installed handlers through * this interface, meaning that it does not contain code specific to any handler type
DispatcherServlet 通过这个处理器去调用Handler
这一步是把刚刚HandlerMapping
找到的控制器名称进行适配,Adapter为适配器,会找到相对应的控制器给DispatcherServlet
进行操作,这个Adapter就是执行控制器本身方法的一层封装
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
...
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
第四站 Controller
控制器里编写的是我们的业务逻辑,可以在控制器里通过Dao层访问数据库等等。控制器返回一个ModelAndView
类,给DispatcherServlet
第五站 视图解析器 ViewResolver
通过返回的ModelAndView
对象,DispatcherServlet
交给注册过的ViewResolver
进行视图的解析
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
通过配置前缀和后缀,对返回的视图名进行拼接,从而返回相对应的视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
使用注解开发
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在spring-mvc配置文件中配置
配置自动扫描包
<context:component-scan base-package="team.controller"/>
配置让springMVC不再处理静态资源
<mvc:default-servlet-handler/>
此处解释,引用他人博客
由于早期的Spring MVC不能很好地处理静态资源,所以在web.xml中配置
DispatcherServlet
的请求映射,往往使用 *.do 、 *.xhtml等方式。这就决定了请求URL必须是一个带后缀的URL,而无法采用真正的REST风格的URL。如果将DispatcherServlet请求映射配置为"/",则Spring MVC将捕获Web容器所有的请求,包括静态资源的请求,Spring MVC会将它们当成一个普通请求处理,因此找不到对应处理器将导致错误。
在springMVC-servlet.xml中配置
<mvc:default-servlet-handler />
后,会在Spring MVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler
,它会像一个检查员,对进入DispatcherServlet
的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet
继续处理。
就是把静态资源转交给DefaultServletHttpRequestHandler
进行处理
配置映射器和适配器
<mvc:annotation-driven/>
配置视图解析器
<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
编写controller层的代码
@Controller
public class TestController{
@RequestMapping("/hello")
public String hello(Model model)
{
model.addAttribute("msg","helloSpringMVC");
return "hello";
}
}
- 使用
@Controller
注解标明这是一个Bean组件,我们的<context:component-scan base-package="team.controller"/>
可以扫描到这个组件,此处还可以写@RestController
会直接返回一个字符串,不会被视图解析器解析 - 使用
@RequestMapping
标注资源的访问路径 - 参数
Model model
是一个模型,存放数据 - 返回值String类型,是视图名称,会被视图解析器解析
创建视图层
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hello</title>
</head>
<body>
${msg}
</body>
</html>
创建的目录在WEB_INF/jsp
目录下,目的是为了让浏览器不能直接访问资源