SpringMVC源码浅析

这篇博客的源码解析处有错误,请大家斟酌的看,等以后再改。

SpringMVC主要运行过程图:(深黄色背景的为重要方法)
在这里插入图片描述

Begin

1、根据request调用getHandler()方法获取执行链对象

这里的执行链指的是什么?
执行一次完整的请求我们不仅仅执行处理器方法,还要执行拦截器等方法
所以这个执行链对象中包含了处理器方法、拦截器等对象属性,想调用时就可以调用

2、根据执行链对象中的处理器对象属性调用getHandlerAdapter()获取处理器适配器

3、插曲1——拦截器preHandle方法执行

4、处理器适配器调用handle()方法返回ModelAndView视图

5、插曲2——拦截器postHandle方法执行

6、调用processDispatchResult()解析、渲染视图

7、插曲3——拦截器afterCompletion方法执行

Over

以上就是SpringMVC的基本流程


SpringMVC的详细流程

执行SpringMVC的主要流程服务器必须在启动时将SpringMVC的九大组件初始化好,
接下来的函数才能根据这些资源寻找合适的适配器、解析器等等

SpringMVC九大组件

1、SpringMVC在工作的时候,关键位置都是由这些组件完成的

2、共同点:九大组件都是接口类型(规范性、扩展性)

 @Nullable
 private MultipartResolver multipartResolver; //文件上传解析器
 @Nullable
 private LocaleResolver localeResolver; //区域信息解析器,和国际化有关
 @Nullable
 private ThemeResolver themeResolver; //主题解析器——主题效果更换(没啥用)
 @Nullable
 private List<HandlerMapping> handlerMappings; //处理器映射信息
 @Nullable
 private List<HandlerAdapter> handlerAdapters; //处理器适配器信息
 @Nullable
 private List<HandlerExceptionResolver> handlerExceptionResolvers; //异常解析器
 @Nullable
 private RequestToViewNameTranslator viewNameTranslator; //视图名称转换器(没啥用)
 @Nullable
 private FlashMapManager flashMapManager; //SpringMVC中运行重定向携带数据的功能
                                          //(存到session域中,取完立即移除session)
 @Nullable
 private List<ViewResolver> viewResolvers; //视图解析器

它们是如何被初始化的呢?
在这里插入图片描述
没错,onRefresh就是初始化九大组件的方法,它是Spring构建IOC容器的时候被调用的

让我们仔细看看initStrategies方法它初始化了哪些组件
在这里插入图片描述
我们点开一个initHandlerMappings方法
在这里插入图片描述
1、detectAllHandlerMappings是Boolean类型,默认为true。是否检测所有的处理器映射类型

2、BeanFactoryUtils.beansOfTypeIncludingAncestors方法作用是从SpringIOC容器中查找所有

HandlerMapping.class的类获得Map matchingBeans对象

3、只抽取Map matchingBeans对象中的value值最后初始化了this.handlerMappings对象

4、当然你也可以不检测所有,在配置初始化DispatchServlet前端控制器的web.xml文件中添加初始化属性设置detectAllHandlerMappings为false即可。这样你就可以采取只获得你配置的HandlerMapping

5、如果以上两种方式都没有初始化this.handlerMappings对象
那么就会采用默认策略,默认策略是根据Properties defaultStrategies对象,其实就是
DispatcherServlet.properties,里面已经指定了所有组件的默认值(注意:值是包含许多个不同的HandlerMapping对象,用逗号分隔)。
执行时会获取DispatcherServlet.properties的属性并在SpringIOC容器中创建对应的Bean对象

DispatcherServlet.properties文件
在这里插入图片描述
总结初始化九大组件:

有就从SpringIOC容器中去找,没有呢就使用默认策略在SpringIOC容器中创建默认的组件对象

初始化步骤已经结束,接下来我们根据以上流程步骤看看它们函数中执行了哪些基本操作

一、getHandler()——获取执行链
在这里插入图片描述
在这里插入图片描述

我们可以清楚看到它在遍历handlerMappingshandlerMappings是调用initStrategies()

初始化九大组件时从SpringIOC容器中获取的数组信息。

进入循环出现有三种HandlerMapping
在这里插入图片描述

Handler处理器(Controller)类型
1、使用@Controller注释的类 —— RequestMappingHandlerMapping
2、实现Controller接口的类,通过key访问value值对应的处理器(很少用)
(还要加@Component添加到Spring容器中)—— SimpleUrlHandlerMapping
3、实现Controller接口的类,访问bean的名称直接访问处理器(更少用)
(bean名称必须以“/”开头)—— BeanNameUrlHandlerMapping

因为我们的处理器都是使用@Controller注解标识的类,所以所有处理器类中的方法信息都储存在
RequestMappingHandlerMapping之中

此时这里循环的作用是遍历所有HandlerMapping种类校验是否能根据请求获取到相应的执行链,
只要成功返回执行链对象即退出循环在这里插入图片描述
很明显,现在处理器方法对象方法的所有信息都在RequestMappingHandlerMapping中,而我们要在这些信息中找到我们相应的处理器方法对象并将拦截器等属性合并成执行链的。

所以我们现在点进getHandler方法看看它是如何获取这个执行链的

在这里插入图片描述
很明显,我们要能获取执行链对象,必须先获取处理器方法对象,其后再做其它处理最终形成执行链,
所以我们点进去看看如何获取处理器方法对象
在这里插入图片描述
这里跳到了子类方法,明显这里没有重要的执行语句,所以我们不管,直接看父类的getHandlerInternal方法
在这里插入图片描述
1、getUrlPathHelper().getLookupPathForRequest方法获取了请求的uri路径

2、根据uri和请求调用lookupHandlerMethod查找处理器方法对象的方法
(注意获取的是处理器方法对象,并不是处理器对象!所以这就是我为什么之前一直强调为什么是处理器方法对象,而不是处理器)

我们继续点进去看看。
在这里插入图片描述
mappingRegistry.getMappingsByUrl(lookupPath)很明显是根据uri获取一些对象,点进去看看。
在这里插入图片描述
很明显,这里根据uri获取到了处理器方法对象的相应信息!

好了,这里就成功获取到处理器方法对象了。
在这里插入图片描述大家不要被这个返回名称handler所迷惑了,其实它真正的类型是 HandlerMethod!
也就是处理器方法类型,所以handler也就是处理器方法对象,而不是处理器对象!

好了,我们继续整合执行链对象
在这里插入图片描述
这里根据处理器方法对象和请求调用了getHandlerExecutionChain方法获取执行链
我们继续点进去看看。

在这里插入图片描述
1、明显第一步创建一个执行链对象并将处理器方法对象囊入其中

2、根据uri遍历拦截器数组查看是否符合,符合则将该拦截器添加到执行链中

好了,最终执行链对象成功获取了!


二、getHandlerAdapter()获取处理器适配器
在这里插入图片描述
我们点进去看看
在这里插入图片描述
进入方法后,也是像获取执行链那样遍历数组。这里的handlerAdapters数组有三个成员,

handlerAdapters数组也是经过 initStrategies() 方法初始化的

HandlerAdapter有三种:
1、HttpRequestHandlerAdapter 要求该处理器继承HttpRequest
2、SimpleControllerHandlerAdapter 要求该处理器继承Controller抽象类
3、RequestMappingHandlerAdapter 要求处理器里有方法即可

最终是RequestMappingHandlerAdapter匹配成功并且返回该处理器适配器对象

获取处理器适配器成功~


三、拦截器preHandle方法
在这里插入图片描述
很明显,只要拦截器执行的preHandle方法不放行(return false),则后面包括目标方法的所有代码都不

会继续执行(我们继续进里面看看)

在这里插入图片描述
这里有三个关键点:

1、interceptorIndex是用来记录已经执行放行的拦截器,标志拦截器数组中哪个拦截器已放行

2、preHandle方法执行预处理

3、triggerAfterCompletion方法根据interceptorIndex来执行已经放行的拦截器的afterCompletion方法

我们再进入triggerAfterCompletion方法中看看

在这里插入图片描述
这里很明显的看到根据interceptorIndex的记录数来执行拦截器的执行已经放行的拦截器的afterCompletion方法(倒序执行)

Over

四、处理器适配器调用handle()执行处理器对象(困难,目前能力不足)
在这里插入图片描述
然后Steo Into 两层进入handleInternal()方法
在这里插入图片描述
很明显,invokeHandlerMethod方法执行后返回ModelAndView mv对象,我们点进去看看

在这里插入图片描述
请注意initModel方法,它的方法名看起来虽然不显眼,但很重要,
内部就是执行@ModelAndView标识的方法的步骤!(补充:@ModelAndView方法比处理器方法先执行 我们点进去看看。

在这里插入图片描述
很明显,invokeModelAttributeMethods方法看方法名就是要执行@ModelAndView标识的方法了。
我们继续点进去看看。

在这里插入图片描述
invokeForRequest方法继续点进去看看。
在这里插入图片描述
很明显,getMethodArgumentValues方法是获取ModelAndView方法的参数和参数值,我们点进去看看。
在这里插入图片描述
getMethodParameters方法是获取方法的参数(是未解析的参数数组)

resolvers.resolveArgument方法就是解析参数对象并获取值,我们继续点进去看看
在这里插入图片描述
getArgumentResolver方法根据参数获取相应的参数解析对象(如引用类型、基本类型等)
(我的第一个参数是自定义引用类型,第二三个是String、Integer)
继续点击进入resolveArgument方法
在这里插入图片描述
getNameForParameter方法是获取参数的名称,

parameter.getParameterAnnotation方法获取参数的注解,

this.bindRequestParameters方法是获取该对象所有属性(request.getParameter)并封装成一个对象最后返回。

对象参数的解析就此结束!

接下来是普通参数的解析

在这里插入图片描述
this.resolveStringValue方法获取参数名,

很明显,resolveName方法解析参数(request.getParameter)并返回属性值。

最后经过多次循环,我们的参数值就获取在args[ ]数组中啦!!

参数我们准备好了,那接下来是不是准备执行 ModelAttribute目标方法了呢!

在这里插入图片描述
doInvoke方法携带参数数组执行,我们点进去看看。

在这里插入图片描述
makeAccessible方法如果没记错的话应该是设置反射可访问私有字段权限,

this.getBridgedMethod().invoke方法我相信大家都很熟悉了,这就是反射调用方法的语法了,

getBridgedMethod()代表处理器方法对象,

this.getBean()代表处理器类对象。

args就是参数啦~

所以执行完这一步后理所当然的会执行 ModelAttribute目标方法中的语句啦!

等等,执行完ModelAttribute方法就应该轮到处理器方法了,但其实我们可以知道,

利用反射方式调用方法其实都是一样的,所以执行处理器方法和执行ModelAttribute方法的步骤是一样的

准备参数——>反射调用

我们来粗略的观摩一下

在这里插入图片描述
执行完ModelAttribute方法接下来执行处理器方法,我们点进去看看。

在这里插入图片描述
继续点进去。
在这里插入图片描述
咦!结局是不是惊人的相似呢?没错,按之前所说的,执行处理器方法和执行ModelAttribute方法方式是相同的,都是准备参数——>反射调用方法的步骤

因为和ModelAttribute方法执行步骤一样,所以我们就不再点进去啦!有兴趣的小伙伴可以继续点进去观察观察

此时此刻,ModelAttribute方法和处理器方法都执行完毕了,但按照规程,应该还有个ModelAndView的
mv对象,所以接下来执行。(但小伙伴们不要误以为之前的两个方法和视图的返回是无关的,其实这里存在一个参数ModelAndViewContainer mavContainer,这个参数保存了之前两个方法的最终Model数据,还有处理器方法的返回值——视图名)

在这里插入图片描述
很明显,this.getModelAndView方法就是获取ModelAndView mv 对象的,我们点进去看看。

在这里插入图片描述
很明显。new ModelAndView方法就是创建一个ModelAndView mv 对象并把Model数据、视图名等等对其进行初始化的简单过程。

就这样,ModelAndView mv 对象创建成功了。最后成功返回ModelAndView mv 对象。

五、拦截器postHandle方法
在这里插入图片描述
在这里插入图片描述
拦截器postHandle方法倒序执行

六、processDispatchResult()视图解析

在这里插入图片描述
明显该方法携带了ModelAndView mv对象等等(其他对象在此函数中不是关键)

ModelAndView mv对象:有视图名称(字符串)、model(Map)中的数据
在这里插入图片描述
在这里插入图片描述
明显render方法携带了ModelAndView对象,继续点进去看看

在这里插入图片描述
红色圈圈的View view对象是真正渲染页面的视图对象,其实视图解析器目的就是实例化view对象,所以获取如何获取view对象是整个视图渲染步骤的核心!!

我们可以观察一下传入的参数

1、视图名称:viewName

2、model数据:mv.getModelInternal()

3、国际化:“zh_CN”(不重要)

4、request:请求

很明显resolveViewName方法主要依靠 视图名model对象在获取视图View不起作用,它是作用于视图渲染过程的) 去获取view对象了,我们继续点进去看看

在这里插入图片描述
这里又是循环一个数组了,只不过数组元素类型是视图解析器,没错,就是我们在Spring.XML中配置的
解析器!这个解析器的类型就是 InternalResourceViewResolver

就是这个很简单的视图解析器在这里插入图片描述
这里循环的意思是从数组中每次找到一个视图解析器,用这个视图解析器去获取视图view,如果获取成

功则返回,结束。如果不能获取则换下一个视图解析器,如此循环往复。如果最后视图view仍为空,则

无法实现页面渲染,当然就报异常啦!

所以我们先来尝试第一个视图解析器
(我也只配了一个视图解析器,这个视图解析器一般都正确的啦!所以最后会获取到视图view)

请记住,我们现在采用的视图解析器类型是 InternalResourceViewResolver

继续点进viewResolver.resolveViewName方法看看
在这里插入图片描述
以下这个方法调用InternalResourceViewResolver类的爷爷类AbstractCachingViewResolver的方法
在这里插入图片描述
明显这里上上下下的方法都只有一个目的——实例化视图view!(前面的方法也是获取视图view,但是是根据缓存获取的,所以如果有缓存的话就不用创建了。但我们此处为了更加清楚如何创建,不适用缓存方式获取视图view。不想用缓存方式的可以重新启动一次项目即可)

实例化视图view对应的方法是createView()

我们继续点进去看看

在这里插入图片描述
以下的这个方法是调用InternalResourceViewResolver类的父类UrlBasedViewResolver的方法
在这里插入图片描述
咦,这里看到重定向和转发是否有点熟悉了呢!

很明显,此时它会根据viewName来判断创建哪一种视图对象

重定向创建RedirectView对象

转发创建InternalResourceView对象

但很明显,我们的viewName是仅仅是“success”,只能到else代码块中继续调用createView方法。。

我们继续点进去看看(点两次)

在这里插入图片描述
很明显,如果要使用默认方法创建视图对象要经过两个步骤

buildView方法applyLifecycleMethods方法

我们点进buildView方法看看
在这里插入图片描述
这里buidView这个方法是先调用的子类方法InternalResourceView对象的方法

很明显,默认创建视图view的类型也是和转发一样的视图类型InternalResourceView

我们再跳到父类的同名方法中,继续点进去看看。
在这里插入图片描述
明显创建了一个AbstractUrlBasedView类的视图view(抽象的),

这里也由UrlBasedViewResolve(实质上是 InternalResourceView )将我们配置的视图解析器前缀和后缀都给视图名拼接上了

下面也就是配置参数了,跳过

现在轮到执行applyLifecycleMethods方法我们点进去看看
很明显就是获取Spring容器然后里面再利用反射技术初始化视图view(由于太菜看不懂里面的了)

好了, InternalResourceView 视图解析器终于把视图对象创建并获取了。接下来就是根据视图对象执行页面渲染了!

在这里插入图片描述
我们将方法跳出来,来到了真正的页面渲染步骤!我们继续点进去看看
在这里插入图片描述
1、createMergedOutputModel方法创建合并输出模型,对model数据进行整合(体现不是很明显,略)

2、prepareResponse方法,对响应response对象设置响应头参数

3、getRequestToExpose方法,要求公开请求设置(默认不公开)

4、前面三个方法都是为了准备页面渲染renderMergedOutputModel方法而准备的步骤

所以我们直接看renderMergedOutputModel方法,继续点进去看看

在这里插入图片描述
这里有三个函数

1、exposeModelAsRequestAttributes()

2、prepareForRendering()

3、getRequestDispatcher()

我们先看第一个exposeModelAsRequestAttributes(),点进去看看

在这里插入图片描述
终于看到熟悉的语句了,感动。。

明显这里是将model(Map, modelMap)中的所有数据置于request域中,让页面获取到这些数据

prepareForRendering方法了,轮到我们继续点进去看看。
在这里插入图片描述
而prepareForRendering方法作用是根据视图名是否以 “/” 开头分两种情况判断请求uri是否和视图名相同,相同则抛出异常

再轮到getRequestDispatcher方法,我们继续点进去看看。
在这里插入图片描述
咦,对这个语句是不是有点熟悉呢!没错,就是转发请求,但写法和我们以往的有一点不一样哦,
聪明的小伙伴发现后面没有 .forward(request, response)
所以它getRequestDispatcher方法的作用就是返回一个RequestDispatcher对象,但不进行转发!
(原谅我现在才知道…)

往后我们跳出来继续看。
在这里插入图片描述
没错!这里才是真正的跳转方法!调用RequestDispatcher对象的forward方法!
(当然,执行此语句后不会立即跳转到页面,仍需要经过拦截器、过滤器、DispatchServlet前端处理器等等流程才能真正成功到达页面。)

Over…

七、拦截器调用afterCompletion方法

在这里插入图片描述
拦截器afterCompletion方法是在视图解析方法中执行的
在这里插入图片描述
很明显可以看到,拦截器的afterCompletion方法是在render方法后执行的(当然也是倒序执行

在这里插入图片描述
还有一个地方,视图解析器出错也会调用拦截器的afterCompletion方法

所以这就是拦截器的afterCompletion方法正常执行会调用(内部调用),

报异常也会调用(catch调用)的原因了。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件。本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,现在这一篇补上。下面开始贴代码。 文中用的框架版本:spring 3,hibernate 3,没有的,自己上网下。 先说web.xml配置: [java] view plaincopy 01.<?xml version="1.0" encoding="UTF-8"?> 02.<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> 03. <display-name>s3h3</display-name> 04. <context-param> 05. <param-name>contextConfigLocation</param-name> 06. <param-value>classpath:applicationContext*.xml</param-value> 07. </context-param> 08. <listener> 09. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 10. </listener> 11. 12. <servlet> 13. <servlet-name>spring</servlet-name> 14. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 15. <load-on-startup>1</load-on-startup> 16. </servlet> 17. <servlet-mapping> 18. <servlet-name>spring</servlet-name> <!-- 这里在配成spring,下边也要写一个名为spring-servlet.xml的文件,主要用来配置它的controller --> 19. <url-pattern>*.do</url-pattern> 20. </servlet-mapping> 21. <welcome-file-list> 22. <welcome-file>index.jsp</welcome-file> 23. </welcome-file-list> 24.</web-app> spring-servlet,主要配置controller的信息 [java] view plaincopy 01.<?xml version="1.0" encoding="UTF-8"?> 02. <beans 03. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 04. xmlns:context="http://www.springframework.org/schema/context" 05. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 06. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 07. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 08. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 09. 10. <context:annotation-config /> 11. <!-- 把标记了@Controller注解的类转换为bean --> 12. <context:component-scan base-package="com.mvc.controller" /> 13. <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 --> 14. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> 15. 16. <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 --> 17. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" 18. p:prefix="/WEB-INF/view/" p:suffix=".jsp" /> 19. 20. <bean id="multipartResolver" 21. class="org.springframework.web.multipart.commons.CommonsMultipartResolver" 22. p:defaultEncoding="utf-8" /> 23. </beans> applicationContext.xml代码 [java] view plaincopy 01.<?xml version="1.0" encoding="UTF-8"?> 02.<beans 03. xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 04. xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" 05. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 06. xsi:schemaLocation=" 07. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 08. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 09. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 10. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> 11. 12. <context:annotation-config /> 13. <context:component-scan base-package="com.mvc" /> <!-- 自动扫描所有注解该路径 --> 14. 15. <context:property-placeholder location="classpath:/hibernate.properties" /> 16. 17. <bean id="sessionFactory" 18. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 19. <property name="dataSource" ref="dataSource" /> 20. <property name="hibernateProperties"> 21. <props> 22. <prop key="hibernate.dialect">${dataSource.dialect}</prop> 23. <prop key="hibernate.hbm2ddl.auto">${dataSource.hbm2ddl.auto}</prop> 24. <prop key="hibernate.hbm2ddl.auto">update</prop> 25. </props> 26. </property> 27. <property name="packagesToScan"> 28. <list> 29. <value>com.mvc.entity</value><!-- 扫描实体类,也就是平时所说的model --> 30. </list> 31. </property> 32. </bean> 33. 34. <bean id="transactionManager" 35. class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 36. <property name="sessionFactory" ref="sessionFactory" /> 37. <property name="dataSource" ref="dataSource" /> 38. </bean> 39. 40. <bean id="dataSource" 41. class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 42. <property name="driverClassName" value="${dataSource.driverClassName}" /> 43. <property name="url" value="${dataSource.url}" /> 44. <property name="username" value="${dataSource.username}" /> 45. <property name="password" value="${dataSource.password}" /> 46. </bean> 47. <!-- Dao的实现 --> 48. <bean id="entityDao" class="com.mvc.dao.EntityDaoImpl"> 49. <property name="sessionFactory" ref="sessionFactory" /> 50. </bean> 51. <tx:annotation-driven transaction-manager="transactionManager" /> 52. <tx:annotation-driven mode="aspectj"/> 53. 54. <aop:aspectj-autoproxy/> 55.</beans> hibernate.properties数据库连接配置 [java] view plaincopy 01.dataSource.password=123 02.dataSource.username=root 03.dataSource.databaseName=test 04.dataSource.driverClassName=com.mysql.jdbc.Driver 05.dataSource.dialect=org.hibernate.dialect.MySQL5Dialect 06.dataSource.serverName=localhost:3306 07.dataSource.url=jdbc:mysql://localhost:3306/test 08.dataSource.properties=user=${dataSource.username};databaseName=${dataSource.databaseName};serverName=${dataSource.serverName};password=${dataSource.password} 09.dataSource.hbm2ddl.auto=update 配置已经完成,下面开始例子 先在数据库建表,例子用的是mysql数据库 [java] view plaincopy 01.CREATE TABLE `test`.`student` ( 02. `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 03. `name` varchar(45) NOT NULL, 04. `psw` varchar(45) NOT NULL, 05. PRIMARY KEY (`id`) 06.) 建好表后,生成实体类 [java] view plaincopy 01.package com.mvc.entity; 02. 03.import java.io.Serializable; 04. 05.import javax.persistence.Basic; 06.import javax.persistence.Column; 07.import javax.persistence.Entity; 08.import javax.persistence.GeneratedValue; 09.import javax.persistence.GenerationType; 10.import javax.persistence.Id; 11.import javax.persistence.Table; 12. 13.@Entity 14.@Table(name = "student") 15.public class Student implements Serializable { 16. private static final long serialVersionUID = 1L; 17. @Id 18. @Basic(optional = false) 19. @GeneratedValue(strategy = GenerationType.IDENTITY) 20. @Column(name = "id", nullable = false) 21. private Integer id; 22. @Column(name = "name") 23. private String user; 24. @Column(name = "psw") 25. private String psw; 26. public Integer getId() { 27. return id; 28. } 29. public void setId(Integer id) { 30. this.id = id; 31. } 32. 33. public String getUser() { 34. return user; 35. } 36. public void setUser(String user) { 37. this.user = user; 38. } 39. public String getPsw() { 40. return psw; 41. } 42. public void setPsw(String psw) { 43. this.psw = psw; 44. } 45.} Dao层实现 [java] view plaincopy 01.package com.mvc.dao; 02. 03.import java.util.List; 04. 05.public interface EntityDao { 06. public List<Object> createQuery(final String queryString); 07. public Object save(final Object model); 08. public void update(final Object model); 09. public void delete(final Object model); 10.} [java] view plaincopy 01.package com.mvc.dao; 02. 03.import java.util.List; 04. 05.import org.hibernate.Query; 06.import org.springframework.orm.hibernate3.HibernateCallback; 07.import org.springframework.orm.hibernate3.support.HibernateDaoSupport; 08. 09.public class EntityDaoImpl extends HibernateDaoSupport implements EntityDao{ 10. public List<Object> createQuery(final String queryString) { 11. return (List<Object>) getHibernateTemplate().execute( 12. new HibernateCallback<Object>() { 13. public Object doInHibernate(org.hibernate.Session session) 14. throws org.hibernate.HibernateException { 15. Query query = session.createQuery(queryString); 16. List<Object> rows = query.list(); 17. return rows; 18. } 19. }); 20. } 21. public Object save(final Object model) { 22. return getHibernateTemplate().execute( 23. new HibernateCallback<Object>() { 24. public Object doInHibernate(org.hibernate.Session session) 25. throws org.hibernate.HibernateException { 26. session.save(model); 27. return null; 28. } 29. }); 30. } 31. public void update(final Object model) { 32. getHibernateTemplate().execute(new HibernateCallback<Object>() { 33. public Object doInHibernate(org.hibernate.Session session) 34. throws org.hibernate.HibernateException { 35. session.update(model); 36. return null; 37. } 38. }); 39. } 40. public void delete(final Object model) { 41. getHibernateTemplate().execute(new HibernateCallback<Object>() { 42. public Object doInHibernate(org.hibernate.Session session) 43. throws org.hibernate.HibernateException { 44. session.delete(model); 45. return null; 46. } 47. }); 48. } 49.} Dao在applicationContext.xml注入 <bean id="entityDao" class="com.mvc.dao.EntityDaoImpl"> <property name="sessionFactory" ref="sessionFactory" /> </bean> Dao只有一个类的实现,直接供其它service层调用,如果你想更换为其它的Dao实现,也只需修改这里的配置就行了。 开始写view页面,WEB-INF/view下新建页面student.jsp,WEB-INF/view这路径是在spring-servlet.xml文件配置的,你可以配置成其它,也可以多个路径。student.jsp代码 [xhtml] view plaincopy 01.<%@ page language="java" contentType="text/html; charset=UTF-8" 02. pageEncoding="UTF-8"%> 03.<%@ include file="/include/head.jsp"%> 04.<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 05.<html> 06.<head> 07.<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 08.<title>添加</title> 09.<mce:script language="javascript" src="<%=request.getContextPath()%><!-- 10./script/jquery.min.js"> 11.// --></mce:script> 12.<mce:style><!-- 13.table{ border-collapse:collapse; } 14.td{ border:1px solid #f00; } 15.--></mce:style><style mce_bogus="1">table{ border-collapse:collapse; } 16.td{ border:1px solid #f00; }</style> 17.<mce:script type="text/javascript"><!-- 18.function add(){ 19. [removed].href="<%=request.getContextPath() %>/student.do?method=add"; 20.} 21. 22.function del(id){ 23.$.ajax( { 24. type : "POST", 25. url : "<%=request.getContextPath()%>/student.do?method=del&id;=" + id, 26. dataType: "json", 27. success : function(data) { 28. if(data.del == "true"){ 29. alert("删除成功!"); 30. $("#" + id).remove(); 31. } 32. else{ 33. alert("删除失败!"); 34. } 35. }, 36. error :function(){ 37. alert("网络连接出错!"); 38. } 39.}); 40.} 41.// --></mce:script> 42.</head> 43.<body> 44. 45.<input id="add" type="button" value="添加"/> 46.<table > 47. <tr> 48. <td>序号</td> 49. <td>姓名</td> 50. <td>密码</td> 51. <td>操作</td> 52. </tr> 53. <c:forEach items="${list}" var="student"> 54. <tr id="<c:out value="${student.id}"/>"> 55. <td><c:out value="${student.id}"/></td> 56. <td><c:out value="${student.user}"/></td> 57. <td><c:out value="${student.psw}"/></td> 58. <td> 59. <input type="button" value="编辑"/> 60. <input type="button" value="${student.id}"/>')" value="删除"/> 61. </td> 62. </tr> 63. </c:forEach> 64. 65.</table> 66.</body> 67.</html> student_add.jsp [xhtml] view plaincopy 01.<%@ page language="java" contentType="text/html; charset=UTF-8" 02. pageEncoding="UTF-8"%> 03.<%@ include file="/include/head.jsp"%> 04.<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 05.<html> 06.<head> 07.<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 08.<title>学生添加</title> 09.<mce:script type="text/javascript"><!-- 10.function turnback(){ 11. [removed].href="<%=request.getContextPath() %>/student.do"; 12.} 13.// --></mce:script> 14.</head> 15.<body> 16.<form method="post" action="<%=request.getContextPath() %>/student.do?method=save"> 17.<div><c:out value="${addstate}"></c:out></div> 18.<table> 19. <tr><td>姓名</td><td><input id="user" name="user" type="text" /></td></tr> 20. <tr><td>密码</td><td><input id="psw" name="psw" type="text" /></td></tr> 21. <tr><td colSpan="2" align="center"><input type="submit" value="提交"/><input type="button" value="返回" /> </td></tr> 22.</table> 23. 24.</form> 25.</body> 26.</html> controller类实现,只需把注解写上,spring就会自动帮你找到相应的bean,相应的注解标记意义,不明白的,可以自己查下@Service,@Controller,@Entity等等的内容。 [java] view plaincopy 01.package com.mvc.controller; 02. 03.import java.util.List; 04. 05.import javax.servlet.http.HttpServletRequest; 06.import javax.servlet.http.HttpServletResponse; 07. 08.import org.apache.commons.logging.Log; 09.import org.apache.commons.logging.LogFactory; 10.import org.springframework.beans.factory.annotation.Autowired; 11.import org.springframework.stereotype.Controller; 12.import org.springframework.ui.ModelMap; 13.import org.springframework.web.bind.annotation.RequestMapping; 14.import org.springframework.web.bind.annotation.RequestMethod; 15.import org.springframework.web.bind.annotation.RequestParam; 16.import org.springframework.web.servlet.ModelAndView; 17. 18.import com.mvc.entity.Student; 19.import com.mvc.service.StudentService; 20. 21.@Controller 22.@RequestMapping("/student.do") 23.public class StudentController { 24. protected final transient Log log = LogFactory 25. .getLog(StudentController.class); 26. @Autowired 27. private StudentService studentService; 28. public StudentController(){ 29. 30. } 31. 32. @RequestMapping 33. public String load(ModelMap modelMap){ 34. List<Object> list = studentService.getStudentList(); 35. modelMap.put("list", list); 36. return "student"; 37. } 38. 39. @RequestMapping(params = "method=add") 40. public String add(HttpServletRequest request, ModelMap modelMap) throws Exception{ 41. return "student_add"; 42. } 43. 44. @RequestMapping(params = "method=save") 45. public String save(HttpServletRequest request, ModelMap modelMap){ 46. String user = request.getParameter("user"); 47. String psw = request.getParameter("psw"); 48. Student st = new Student(); 49. st.setUser(user); 50. st.setPsw(psw); 51. try{ 52. studentService.save(st); 53. modelMap.put("addstate", "添加成功"); 54. } 55. catch(Exception e){ 56. log.error(e.getMessage()); 57. modelMap.put("addstate", "添加失败"); 58. } 59. 60. return "student_add"; 61. } 62. 63. @RequestMapping(params = "method=del") 64. public void del(@RequestParam("id") String id, HttpServletResponse response){ 65. try{ 66. Student st = new Student(); 67. st.setId(Integer.valueOf(id)); 68. studentService.delete(st); 69. response.getWriter().print("{/"del/":/"true/"}"); 70. } 71. catch(Exception e){ 72. log.error(e.getMessage()); 73. e.printStackTrace(); 74. } 75. } 76.} service类实现 [java] view plaincopy 01.package com.mvc.service; 02. 03.import java.util.List; 04. 05.import org.springframework.beans.factory.annotation.Autowired; 06.import org.springframework.stereotype.Service; 07.import org.springframework.transaction.annotation.Transactional; 08. 09.import com.mvc.dao.EntityDao; 10.import com.mvc.entity.Student; 11. 12.@Service 13.public class StudentService { 14. @Autowired 15. private EntityDao entityDao; 16. 17. @Transactional 18. public List<Object> getStudentList(){ 19. StringBuffer sff = new StringBuffer(); 20. sff.append("select a from ").append(Student.class.getSimpleName()).append(" a "); 21. List<Object> list = entityDao.createQuery(sff.toString()); 22. return list; 23. } 24. 25. public void save(Student st){ 26. entityDao.save(st); 27. } 28. public void delete(Object obj){ 29. entityDao.delete(obj); 30. } 31.} OK,例子写完。有其它业务内容,只需直接新建view,并实现相应comtroller和service就行了,配置和dao层的内容基本不变,也就是每次只需写jsp(view),controller和service调用dao就行了。 怎样,看了这个,spring mvc是不是比ssh实现更方便灵活。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值