MyException - 我的异常网
当前位置:我的异常网» VC/MFC » SpringMVC详解(2)-详细架构

SpringMVC详解(2)-详细架构

www.MyException.Cn  网友分享于:2013-08-22  浏览:0次
SpringMVC详解(二)------详细架构

  通过上篇博客,我们能编写一个 SpringMVC 的入门实例,但是为什么要这样写?这样写有啥好处?通过这篇博客我们会有详细的了解。

   本篇博客源码下载链接:http://pan.baidu.com/s/1boOfxlP 密码:bxq4

1、SpringMVC 详细介绍

  通过入门实例,我们大概知道 SpringMVC 的作用,那么它到底是什么呢?

  Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。

  与之相反的是基于组件的、事件驱动的Web框架,如Tapestry、JSF等,在此就不介绍了。

  Spring Web MVC也是服务到工作者模式的实现,但进行可优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

 

2、SpringMVC 处理请求流程

第一步:用户发送请求到前端控制器(DispatcherServlet)。

第二步:前端控制器请求 HandlerMapping 查找 Handler,可以根据 xml 配置、注解进行查找。

第三步: 处理器映射器 HandlerMapping 向前端控制器返回 Handler

第四步:前端控制器调用处理器适配器去执行 Handler

第五步:处理器适配器执行 Handler

第六步:Handler 执行完成后给适配器返回 ModelAndView

第七步:处理器适配器向前端控制器返回 ModelAndView

    ModelAndView 是SpringMVC 框架的一个底层对象,包括 Model 和 View

第八步:前端控制器请求试图解析器去进行视图解析

    根据逻辑视图名来解析真正的视图。

第九步:试图解析器向前端控制器返回 view

第十步:前端控制器进行视图渲染

    就是将模型数据(在 ModelAndView 对象中)填充到 request 域

第十一步:前端控制器向用户响应结果

 

下面我们对上面出现的一些组件进行解释:

  1、前端控制器DispatcherServlet(不需要程序员开发)。 
    作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。
  2、处理器映射器HandlerMapping(不需要程序员开发)。
    作用:根据请求的url查找Handler。
  3、处理器适配器HandlerAdapter(不需要程序员开发)。
    作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。
  4、处理器Handler(需要程序员开发)。
    注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
  5、视图解析器ViewResolver(不需要程序员开发)。
    作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
  6、视图View(需要程序员开发jsp)。
    注意:View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)
  ps:不需要程序员开发的,需要程序员自己做一下配置即可。

  可以总结出:需要我们开发的工作只有处理器 Handler 的编写以及视图比如JSP页面的编写。可能你还对诸如前端控制器、处理器映射器等等名词不太理解,那么接下来我们对其进行详细的介绍。

 

3、配置前端控制器

  在 web.xml 文件中进行如下配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	 xmlns="http://java.sun.com/xml/ns/javaee"
	 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	 http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>SpringMVC_01</display-name>
  <!-- 配置前端控制器DispatcherServlet -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--springmvc.xml 是自己创建的SpringMVC全局配置文件,用contextConfigLocation作为参数名来加载
    	如果不配置 contextConfigLocation,那么默认加载的是/WEB-INF/servlet名称-servlet.xml,在这里也就是 springmvc-servlet.xml
      -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--第一种配置:*.do,还可以写*.action等等,表示以.do结尾的或者以.action结尾的URL都由前端控制器DispatcherServlet来解析
    	第二种配置:/,所有访问的 URL 都由DispatcherServlet来解析,但是这里最好配置静态文件不由DispatcherServlet来解析
    	错误配置:/*,注意这里是不能这样配置的,应为如果这样写,最后转发到 jsp 页面的时候,仍然会由DispatcherServlet进行解析,
    				而这时候会找不到对应的Handler,从而报错!!!
      -->
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

  

4、配置处理器适配器

  在 springmvc.xml 文件中配置。用来约束我们所需要编码的 Handler类。

  第一种配置:编写 Handler 时必须要实现 Controller

<!-- 配置处理器适配器,所有适配器都得实现 HandlerAdapter接口 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> 

  我们可以查看源码: 

 

   第二种配置:编写 Handler 时必须要实现 HttpRequestHandler

<!-- 配置处理器适配器第二种方法,所有适配器都得实现 HandlerAdapter接口 ,这样配置所有Handler都得实现 HttpRequestHandler接口-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" /> 

  

 

5、编写 Handler

  在 springmvc.xml 文件中配置。通俗来讲,就是请求的 URL 到我们这里所编写的 Handler 类的某个方法进行一些业务逻辑处理。

  我们在上面讲解了两个处理器适配器来约束 Handler,那么我们就通过上面两种配置分别编写两个 Handler

  第一种:实现Controller 接口

package com.ys.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class HelloController implements Controller{

	@Override
	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		ModelAndView modelView = new ModelAndView();
		//类似于 request.setAttribute()
		modelView.addObject("name","张三");
		modelView.setViewName("/WEB-INF/view/index.jsp");
		return modelView;
	}

}

  第二种:实现 HttpRequestHandler 接口

package com.ys.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.HttpRequestHandler;

public class HelloController2 implements HttpRequestHandler{

	@Override
	public void handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setAttribute("name", "张三");
		request.getRequestDispatcher("/WEB-INF/view/index.jsp").forward(request, response);
	}

}

  总结:通常我们使用第一种方式来编写 Handler ,但是第二种没有返回值,我们可以通过 response 修改相应内容,比如返回 json 数据。

response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json字符串");

  所以具体使用哪一种根据实际情况来判断。

 

 

5、配置处理器映射器

  在 springmvc.xml 文件中配置。通俗来讲就是请求的 URL 怎么能被 SpringMVC 识别,从而去执行我们上一步所编写好的 Handler

   第一种方法:

<!-- 配置Handler -->    
<bean name="/hello.do" class="com.ys.controller.HelloController2" />

<!-- 配置处理器映射器
	将bean的name作为url进行查找,需要在配置Handler时指定bean name(就是url)-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

  这样配置的话,那么请求的 URL,必须为 http://localhost:8080/项目名/hello.do

  

  第二种方法:

<!-- 配置Handler -->    
<bean id="hello1" class="com.ys.controller.HelloController" />
<bean id="hello2" class="com.ys.controller.HelloController" />
<!-- 第二种方法:简单URL配置处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<property name="mappings">
		<props>
			<prop key="/hello1.do">hello1</prop>
			<prop key="/hello2.do">hello2</prop>
		</props>
	</property>
</bean>

  这种配置请求的 URL可以为 http://localhost:8080/项目名/hello1.do,或者http://localhost:8080/项目名/hello2.do

 

 总结:上面两种处理器映射器配置可以并存,前端控制器会正确的去判断 url 用哪个 Handler 去处理。

 

 

6、配置视图解析器

  第一种配置:

<!-- 配置视图解析器 
  	进行jsp解析,默认使用jstl标签,classpath下得有jstl的包-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />

 如果这样配,那么在 Handler 中返回的必须是路径+jsp页面名称+".jsp" 

   第二种配置:

<!--配置视图解析器  -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 返回视图页面的前缀 -->
		<property name="prefix" value="/WEB-INF/view"></property>
		<!-- 返回页面的后缀 -->
		<property name="suffix" value=".jsp"></property>
	</bean>

  如果这样配,那么在 Handler 中只需要返回在 view 文件夹下的jsp 页面名就可以了。

 

7、DispatcherServlet.properties

  上面我们讲解了各种配置,可能有人会问这么多配置,万一少配置了一样,那不就不能运行了,那我们能不能不配置呢?答案是肯定的,SpringMVC 给我们提供了一个 DispatcherServlet.properties 文件。系统会首先加载这里面的配置,如果我们没有配置,那么就默认使用这个文件的配置;如果我们配置了,那么就优先使用我们手动配置的。

  

  在 SpringMVC 运行之前,会首先加载 DispatcherServlet.properties 文件里面的内容,那么我们来看看这里面都是什么。

# 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

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
	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

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

  我们可以从上面得出,如果我们不手动进行各种配置,那么也有会默认的

  ①、处理器适配器默认:org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter

  ②、处理器映射器默认:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping

  ③、视图解析器默认:org.springframework.web.servlet.view.InternalResourceViewResolver

 

文章评论

每天工作4小时的程序员
每天工作4小时的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
老程序员的下场
老程序员的下场
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员应该关注的一些事儿
程序员应该关注的一些事儿
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
如何成为一名黑客
如何成为一名黑客
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员都该阅读的书
程序员都该阅读的书
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
代码女神横空出世
代码女神横空出世
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
为什么程序员都是夜猫子
为什么程序员都是夜猫子
我的丈夫是个程序员
我的丈夫是个程序员
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员必看的十大电影
程序员必看的十大电影
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
鲜为人知的编程真相
鲜为人知的编程真相
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员和编码员之间的区别
程序员和编码员之间的区别
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
那些争议最大的编程观点
那些争议最大的编程观点
编程语言是女人
编程语言是女人
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
 程序员的样子
程序员的样子
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
一个程序员的时间管理
一个程序员的时间管理
Java程序员必看电影
Java程序员必看电影
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
漫画:程序员的工作
漫画:程序员的工作
我是如何打败拖延症的
我是如何打败拖延症的
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有