SpringMVC工作流程

一、springMVC是什么?

​ springMVC是一个MVC的开源框架,springMVC就相当于是Struts2加上sring的整合,那么springMVC和spring是什么样的关系呢?在百度百科上有一个很好的解释:springMVC是spring的一个后续产品,其实就是spring在原有基础上,又提供了web应用的MVC模块,可以简单的把springMVC理解为是spring的一个模块(类似AOP,IOC这样的模块),网络上经常会说springMVC和spring无缝集成,其实springMVC就是spring的一个子模块,所以根本不需要同spring进行整合。

​ 工作原理图:

可以看到这里分为大致11个步骤,这11个步骤的任务是这样的:

​ 1、用户发送请求至前端控制器DispatcherServlet。

​ 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

​ 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

​ 4、DispatcherServlet调用HandlerAdapter处理器适配器。

​ 5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

​ 6、Controller执行完成返回ModelAndView。

​ 7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

​ 8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

​ 9、 ViewReslover解析后返回具体View,这个view不是完整的,仅仅是一个页面(视图)名字,且没有后缀名。

​ 10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

​ 11、 DispatcherServlet响应用户。

图中可以看到,DispatcherServlet(前端控制器)占据了很大的一部分,事实也是这样,springMVC中,DispatcherServlet是他的核心。

接下来再看一下springMVC组件及其核心步骤的说明:

​ 黄色字体和绿色字体是对组件作用的说明,其中黄色字体说明的组件是框架提供,绿色字体说明的部分是要由工程师实现,红色字体是核心架构的具体流程步骤

二、配置文件的方式结合源码,了解工作流程

看完了原理,再来通过注释的方式,写一个Hello World,熟悉一下过程。

准备maven的web工程

maven需要的相关依赖,springMVC需要的spring-webmvc,日志相关的slf4j-log4j12,JSP相关的jstl、servlet-api、jsp-api。

配置web.xml

因为DispatcherServlet本身就是一个Servlet,所以要在web.xml配置:

<servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
复制代码

创建springmvc配置文件

前端控制器要协调各个组件干活,所以就要依赖于配置文件,SpringMVC要读取的配置文件是要是自己手动创建,怎么创建?配置文件应该怎么命名?先来到DispatcherServlet的源代码中:

可以看到DispatcherServlet继承了FrameworkServlet,FrameworkServlet是Spring web框架的基本servlet。为集成提供了基于javabean的整体解决方案中的Spring应用程序上下文。FrameworkServlet注释中有这样一段描述:

大致意思就是,默认的SpringMVC配置文件名字是“servlet-name”-servlet.xml, 而这个“servlet-name”就是在web.xml中配置的的名字,这里就是springmvc,当然你也可以起其他名字。然后读取的默认位置是在/WEB-INF/“servlet-name”-servlet.xml,所以这里要在WEB-INF下面创建的是名叫springmvc-servlet.xml的配置文件,因为他和Spring都是一个体系内的,所以可以直接创建spring的配置文件模板:

​ 现在有了配置文件,那么改在配置文件中配置什么东西?可以回到SpringMVC工作流程图看到,在springMVC配置文件中起码要配置,映射器HandlerMapping、适配器HandelAdapter、处理器Handel(Controller)、视图解析器ViewResolver。View的渲染不是SpringMVC来完成,所以这里不需要配置。

配置映射器

​ 先来配置HandlerMapping,找到HandlerMapping,他是一个接口,所以要配置的是HandlerMapping的实现类,找到HandlerMapping源码,查看他的继承树:

不看已经过时的(这里Spring基于4.3的一个版本),我们要通过请求中的url和HandlerMapping找到处理器,所以使用BeanNameUrlHandlerMapping,类名中的BeanName也就是要找的处理器,在注释中也有说明,如果url是/foo ,对应的处理器名字也是/foo,假设我们等等要访问的url是localhost:8080/hello.do,那么后面我们再写 处理器中的代码的名字也是hello.do.

然后再springmvc-servler.xml中配置映射器:

<!--HandelMapping-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
复制代码

配置适配器

​ 映射器处理完后,返回执行链,DispatcherServlet去调用处理器,处理器实现本身就就是多元化的,要根据处理器的具体实现,通过适配器(处理器包装后)调用处理器,我们先找到HandlerAdapter,看看这个接口的继承树:

有一个适配器SimpleControllerHandlerAdapter,能够帮我们调用处理器(也可以叫Controller)中的方法,

那么他是怎么调用处理器方法?

他是通过判断你的处理器是否属于Controller的类型,是则返回true。那么Controller又是什么呢?查看源代码发现Controller是一个接口,也就意味着,我们写处理器部分的代码要实现这一个接口。

这个接口中就一个方法,也就是处理器方法,这个方法等同与Servlet中的doGet/doPost方法。

我们调用处理器方法的前提是实现Controller接口,在交给适配器,适配器判断完之后,处理器(handler)在调用Controller接口中的处理器方法,所以最终调用处理器方法返回ModelAndView的是适配器的handler方法:

接下来我们要做的事就是在springmvc-servlet.xml配置这个SimpleControllerHandlerAdapter:

<!--SimpleControllerHandlerAdapter-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
复制代码

创建处理器

配置好适配器,按照流程图接下来搞配置处理器,前面说提到处理器部分是我们自己来实现的。

我们在项目中创建一个一个包com.ljm.springmvc.controller,然后在包中创建处理器HelloController。这里不叫包名类名不叫Handler而叫controller,至于为什么,可能是因为他要实现一个接口,这接口叫Controller。然后重写Controller中的方法:

package com.ljm.springmvc.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return null;
    }
}
复制代码

配置处理器

因为我们自己创建了处理器和Spring没啥关系,要想有有点什么关系,就要把它配置到springmvc-servlet.xml中,处理器有很多个,那么就要给他配上id或者name,这里给他配置name,前面在配置映射器时提到,这个名字是我们要访问的url所以,不能随便配:

<!--处理器,注意/不能丢-->
<bean name="/hello.do" class="com.ljm.springmvc.controller.HelloController" />
复制代码

实现处理器

创建配置好处理器后,就要开始实现处理器中的业务,该调用哪个service层就调用哪个service,然后把结果响应到客户端,这里响应回去的是一个ModelAndView,这里不实现service和dao层,写一个死数据,不管三七二十一,先创建一个ModelAndView对象用于返回,

这里可以看到modelAndView有一些add方法:addObject(),根据参数可以联想到request的get/set Attribute方法,先设置一对key/value;但这时候只设置了数据,没有告诉他往哪个页面返回,所以这里还有一个操作,叫设置视图名称,使用的是modelAndView的setViewName方法,但这里参数仅仅是设置要返回到的视图名称(逻辑视图),且不带后缀名,这里我们要返回到index.jsp,所以参数是index;所以处理器的代码实现已经完成了:

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg","spring MVC : Hello World!");
        modelAndView.setViewName("index");
        return modelAndView;
    }
}
复制代码

配置视图解析器

视图解析器:ViewResolver是框架提供的,所以直接配置到springmvc-servlet.xml就行。

ViewResolver也是个接口,查看继承树,

其中有一个InternalResourceViewResolver,根据注释我们可以看到我们要用的就是他InternalResourceViewResolver继承了UrlBasedViewResolver,根据UrlBasedViewResolver注释的提示,我们可以看到视图解析器正确的配置姿势:

我们这里的配置就应该是:

<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
    <!--配置路径:返回页面在webapp下,所以配置/-->
    <property name="prefix" value="/" />
    <!--配置后缀名-->
    <property name="suffix" value=".jsp" />
    <!--viewname已经在处理器配置过了-->
</bean>
复制代码

页面接收返回参数

<html>
<body>
<h2>${msg}</h2>
</body>
</html>
复制代码

添加日志

添加log4j.properties 到resources

log4j.rootLogger=DEBUG,A1
log4j.logger.org.apache=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
复制代码

测试

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值