SpringMVC框架学习(二)
文章目录
三、SpringMVC进阶
1、运行流程图解
<1>、流程图
<2>、Spring工作流程描述
1) 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获;
2) DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI):
判断请求URI对应的映射
① 不存在:
再判断是否配置了mvc:default-servlet-handler:
如果没配置,则控制台报映射查找不到,客户端展示404错误
如果有配置,则执行目标资源(一般为静态资源,如:JS,CSS,HTML)
② 存在:
执行下面流程
3) 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
4) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
5) 如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法【正向】
6) 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
① HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
② 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
③ 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
④ 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
7) Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
8) 此时将开始执行拦截器的postHandle(…)方法【逆向】
9) 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet,根据Model和View,来渲染视图
10) 在返回给客户端时需要执行拦截器的AfterCompletion方法【逆向】
11) 将渲染结果返回给客户端
2、Spring整合SpringMVC
<1>、配置监听器
<!--初始化SpringIOC容器的监听器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--SpringMVC的前段控制器-->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
创建Spring的配置文件:applicationContext.xml
<!--Spring的配置文件-->
<bean id="person" class="ss.beans.Person">
<property name="name" value="Spring+SpringMVC"></property>
</bean>
<!--Spring的组件扫描-->
<context:component-scan base-package="ss">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
</context:component-scan>
springmvc的配置文件:
<!--SpingMVC组件扫描-->
<context:component-scan base-package="ss" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter>
</context:component-scan>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--处理静态资源-->
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
DAO层:
@Repository
public class UserDao {
public UserDao() {
System.out.println("UserDao......");
}
public void hello(){
System.out.println("UserDao Hello");
}
}
Service层:
@Service
public class UserService {
@Autowired
private UserDao userDao;
public UserService() {
System.out.println("UserService......");
}
public void hello(){
userDao.hello();
}
}
Handler层:
@Controller
public class UserHandler {
@Autowired
private UserService userService;
public UserHandler() {
System.out.println("UserHandler......");
}
@RequestMapping("/hello")
public String hello(HttpSession session){
userService.hello();
ServletContext servletContext = session.getServletContext();
//SpringIOC容器
//ApplicationContext context = (ApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
//工具类
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Person person = context.getBean("person", Person.class);
person.sayHello();
return "success";
}
}
index.jsp:
<body>
<a href="hello">Hello SpringMVC</a>
</body>
当然我们也可以书写我们自己的监听器和Servlet:
监听器:
@WebListener()
public class MyServletContextListener implements ServletContextListener{
/**
* 当监听到ServletContext被创建,执行该方法
* @param sce
*/
public void contextInitialized(ServletContextEvent sce) {
//创建SpringIOC容器对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//将SpringIOC容器对象绑定到ServletContext
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("applicationContext", context);
}
public void contextDestroyed(ServletContextEvent sce) {
}
}
Servlet:
public class HelloServlet extends HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, IOException {
doGet(request, response);
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, IOException {
//访问SpringIOC容器中的person对象
//从ServletContext对象中获取SpringIOC容器对象
ServletContext servletContext = getServletContext();
ApplicationContext applicationContext = (ApplicationContext) servletContext.getAttribute("applicationContext");
Person person = applicationContext.getBean("person", Person.class);
person.sayHello();
}
}
<2>、SpringIOC容器和SpringMVC IOC容器的关系
1) 在 Spring MVC 配置文件中引用业务层的 Bean
2) 多个 Spring IOC 容器之间可以设置为父子关系,以实现良好的解耦。
3) Spring MVC WEB 层容器可作为 “业务层” Spring 容器的子容器:
即 WEB 层容器可以引用业务层容器的 Bean,而业务层容器却访问不到 WEB 层容器的 Bean