关于springMVC中component-scan的问题以及springmvc.xml整理
关于springMVC中component-scan的问题以及springmvc.xml整理
一、component-scan问题和解决办法
最近在学习使用springMVC+mybatis开发程序的时候,遇到了一些问题,这些问题有的很容易就解决了,可是有一个问题废了我一上午的时间,那就是spring中的组件扫描技术, <context:component-scan base-package="***.***.***"></context:component-scan>这个技术可以让我们少些很多javabean,还是很方便的,可是我在使用了这样的技术之后就一直报java.lang.illegalargumentexception这样的错误,很是苦恼,哪里有参数不合法了,接下来我注释掉了这个component-scan条目,然后使用了普通的javabean来进行暴露,没想到竟然成功了,因此我可以断定问题一定出在这个组件扫描component-scan上,看了很多的资料,都是讲的component-scan的相关内容,可是很少会提及component-scan与java.lang.illegalargumentexception的错误,最终,我总算找到了原因所在,那就是我是用的是spring3.2的大版本,jdk使用的是1.8大版本,这样问题就出来了,版本不匹配,在执行jre的时候就不能相互兼容了,一定要注意在使用组件扫描的时候必须使用jdk和spring的版本相对应的jar,不然的话就会出现不合法的参数错误,真正正确的搭配版本应该是这样的:jdk1.7+spring-context-support-3.2.0.RELEASE.jar或者jdk1.8+spring 4.*来搭配,在这里我使用了前者来解决!解决方法是首先卸载了电脑上的jdk环境,这点可以通过控制面板的“程序和功能”来完成,剩下的就是下载搭配的jdk版本,然后安装,安装之后一般还要重启一下电脑,当然也可以不启动,之后再打开程序,将新的环境jre导入程序中,这样就可以了。因为我的这一点疏忽,让我吃尽了苦头,费了好长时间,在这里我不得不说采用xml的方法进行数据即代码配置,好处是非常大的,但是错误就是难以找到哪个地方出问题了,一旦出现了一个这种相关度非常低的错误,往往是非常费时间的,不利于测试和排错,因此在这里做一整理和总结。
二、注解和非注解的方式总结
2.1、非注解的方式
2.1.1、 方法一
1 <!-- 第一种配置handler的方法,通过beanname来配置,处理器映射器需要配置为beanname
2 特别注意这里处理器适配器不能为HttpRequestHandlerAdapter,只能为SimpleControllerHandlerAdapter-->
3 <bean id="itemsController1" name="/queryItems_test.action" class="cn.itcast.ssm.controller.ItemsController1" />
4
5 <!-- 处理器映射器 将bean的name作为url进行查找 ,需要在配置Handler时指定beanname(就是url) 所有的映射器都实现 HandlerMapping接口。-->
6 <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
7
8 <!-- 处理器适配器 所有处理器适配器都实现 HandlerAdapter接口 -->
9 <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
2.1.2、 方法二
这里注意,我们在上面定义了handler1,并且映射方式是beanname,而这里我们不加改变的,只是利用了其中的一部分信息,id,在这里使用 SimpleUrlHandlerMapping和SimpleControllerHandlerAdapter同样完成了访问对应上面handler的功能的网址的功能,并且同一个handler还可以映射成不同的网址! 值得注意的是,我们使用这两种映射器和SimpleControllerHandlerAdapter适配器只能实现具有public class ItemsController1 implements Controller {。。。}这样生成的handler 。而对于public class ItemsController2 implements HttpRequestHandler {。。。}则无能为力。这种情况需要使用org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter另外,对于handler来说使用什么映射器和是用什么适配器之间并没有什么强定义的关系,但是适配器一定要和handler的定义保持一致,映射器只与映射器的定义方法有关!!!!
1 <!-- 配置Handler2 -->
2 <bean id="itemsController2" class="cn.itcast.ssm.controller.ItemsController2" />
3 <!--简单url映射 -->
4 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
5 <property name="mappings">
6 <props>
7 <!-- 对itemsController1进行url映射,url是/queryItems1.action -->
8 <prop key="/queryItems1.action">itemsController1</prop>
9 <prop key="/queryItems2.action">itemsController1</prop>
10 <prop key="/queryItems3.action">itemsController2</prop>
11 </props>
12 </property>
13 </bean>
14 <!-- 非注解的适配器 ,适用于public class ItemsController2 implements HttpRequestHandler {。。}方法-->
15 <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
1 package cn.itcast.ssm.controller;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.servlet.http.HttpServletRequest;
7 import javax.servlet.http.HttpServletResponse;
8
9 import org.springframework.web.servlet.ModelAndView;
10 import org.springframework.web.servlet.mvc.Controller;
11
12 import cn.itcast.ssm.po.Items;
13
14 public class ItemsController1 implements Controller {
15
16 @Override
17 public ModelAndView handleRequest(HttpServletRequest request,
18 HttpServletResponse response) throws Exception {
19
20 //调用service查找 数据库,查询商品列表,这里使用静态数据模拟
21 List<Items> itemsList = new ArrayList<Items>();
22 //向list中填充静态数据
23
24 Items items_1 = new Items();
25 items_1.setName("联想笔记本");
26 items_1.setPrice(6000f);
27 items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
28
29 Items items_2 = new Items();
30 items_2.setName("苹果手机");
31 items_2.setPrice(5000f);
32 items_2.setDetail("iphone6苹果手机!");
33
34 itemsList.add(items_1);
35 itemsList.add(items_2);
36
37 //返回ModelAndView
38 ModelAndView modelAndView = new ModelAndView();
39 //相当 于request的setAttribut,在jsp页面中通过itemsList取数据
40 modelAndView.addObject("itemsList", itemsList);
41
42 //指定视图
43 modelAndView.setViewName("items/itemsList");
44
45 return modelAndView;
46 }
47 }
1 package cn.itcast.ssm.controller;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.List;
6
7 import javax.servlet.ServletException;
8 import javax.servlet.http.HttpServletRequest;
9 import javax.servlet.http.HttpServletResponse;
10
11 import org.springframework.web.HttpRequestHandler;
12 import org.springframework.web.servlet.ModelAndView;
13
14 import cn.itcast.ssm.po.Items;
15
16 public class ItemsController2 implements HttpRequestHandler {
17
18 @Override
19 public void handleRequest(HttpServletRequest request,
20 HttpServletResponse response) throws ServletException, IOException {
21
22 //调用service查找 数据库,查询商品列表,这里使用静态数据模拟
23 List<Items> itemsList = new ArrayList<Items>();
24 //向list中填充静态数据
25
26 Items items_1 = new Items();
27 items_1.setName("联想笔记本");
28 items_1.setPrice(6000f);
29 items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
30
31 Items items_2 = new Items();
32 items_2.setName("苹果手机");
33 items_2.setPrice(5000f);
34 items_2.setDetail("iphone6苹果手机!");
35
36 itemsList.add(items_1);
37 itemsList.add(items_2);
38 //设置模型数据
39 request.setAttribute("itemsList", itemsList);
40 //设置转发的视图
41 request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);
42
43 //使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据
44 /*
45 response.setCharacterEncoding("utf-8");
46 response.setContentType("application/json;charset=utf-8");
47 response.getWriter().write("json串");*/
48 }
49 }
2.2、注解的方式
1 <!-- 注解的方式 -->
2 <mvc:annotation-driven></mvc:annotation-driven>
3 <!-- 一定要注意在使用组件扫描的时候必须使用jdk和spring的版本相对应的jar,不然的话就会出现不合法的参数错误,
比如说我本来使用的jdk1.8+spring-context-support-3.2.0.RELEASE.jar就是一个错误的搭配,特别的坑,
废了我一个上午的时间去调试最佳的搭配是使用jdk1.7+spring-context-support-3.2.0.RELEASE.jar或者jdk1.8+spring 4.*来搭配,
在这里我采用了前者来解决! -->
4 <context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
1 package cn.itcast.ssm.controller;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.springframework.stereotype.Controller;
7 import org.springframework.web.bind.annotation.RequestMapping;
8 import org.springframework.web.servlet.ModelAndView;
9
10 import cn.itcast.ssm.po.Items;
11
12 //使用Controller标识 它是一个控制器
13 @Controller
14 public class ItemsController3 {
15
16 //商品查询列表
17 //@RequestMapping实现 对queryItems方法和url进行映射,一个方法对应一个url
18 //一般建议将url和方法写成一样
19 @RequestMapping("/queryItems")
20 public ModelAndView queryItems()throws Exception{
21
22 //调用service查找 数据库,查询商品列表,这里使用静态数据模拟
23 List<Items> itemsList = new ArrayList<Items>();
24 //向list中填充静态数据
25
26 Items items_1 = new Items();
27 items_1.setName("联想笔记本");
28 items_1.setPrice(6000f);
29 items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
30
31 Items items_2 = new Items();
32 items_2.setName("苹果手机");
33 items_2.setPrice(5000f);
34 items_2.setDetail("iphone6苹果手机!");
35
36 itemsList.add(items_1);
37 itemsList.add(items_2);
38
39 //返回ModelAndView
40 ModelAndView modelAndView = new ModelAndView();
41 //相当 于request的setAttribut,在jsp页面中通过itemsList取数据
42 modelAndView.addObject("itemsList", itemsList);
43
44 //指定视图
45 //下边的路径,如果在视图解析器中配置jsp路径的前缀和jsp路径的后缀,修改为
46 //modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
47 //上边的路径配置可以不在程序中指定jsp路径的前缀和jsp路径的后缀
48 modelAndView.setViewName("items/itemsList");
49 return modelAndView;
50 }
51 }
需要注意的是使用<mvc:annotation-driven></mvc:annotation-driven>可以代替
1 <!--注解映射器 -->
2 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
3 <!--注解适配器 -->
4 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
并且mvc:annotation-driven默认加载很多的参数绑定方法,比如json转换解析器就默认加载了,如果使用mvc:annotation-driven就不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter,实际开发时使用mvc:annotation-driven。
总结,无论使用哪种方法都要使用处理器映射器、处理器适配器这两个基本的方式来对handler(controller)进行控制,处理器映射器解决的是找到URL对应的处理方法,而处理器适配器解决的是到底要怎么去处理我们的事务,这个handler的输入输出到底是什么样子的,需不需要继承一个父类等问题。因此这两个东西和handler是关联非常大的,在实际开发中我们都使用注解开发,除了形式上的简单之外,容易配置,并且在原理上来说,非注解的开发方法只能在一个类中写一个方法,做一件事情,这样就会建立非常多的文件,而使用注解的开发方法方便灵活,便于控制,并且一个handler中可以包含很多个方法来暴露给不同的URL来访问,这点非常方便。
三、视图解析器
1 <!-- 视图解析器 解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包-->
2 <bean
3 class="org.springframework.web.servlet.view.InternalResourceViewResolver">
4 <!-- 配置jsp路径的前缀 -->
5 <property name="prefix" value="/WEB-INF/jsp/"/>
6 <!-- 配置jsp路径的后缀 -->
7 <property name="suffix" value=".jsp"/>
8 </bean>
这也就解释了,我们在程序里可以有恃无恐的这样写modelAndView.setViewName("items/itemsList");的原因。
四、日期类型的转换(FormattingConversionServiceFactoryBean)
在某些情况下,我们需要对UI上输入的日期格式进行相应的转换,变成我们数据库中对应的格式并存储,然后再显示,这是很常见的,因此我们需要使用mvc:annotation-driven工具进行一定的配置。
1 <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
2 <!-- 自定义参数绑定 -->
3 <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
4 <!-- 转换器 -->
5 <property name="converters">
6 <list>
7 <!-- 日期类型转换 -->
8 <bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>
9 </list>
10 </property>
11 </bean>
1 package cn.itcast.ssm.controller.converter;
2
3 import java.text.ParseException;
4 import java.text.SimpleDateFormat;
5 import java.util.Date;
6
7 import org.springframework.core.convert.converter.Converter;
8 public class CustomDateConverter implements Converter<String,Date>{
9
10 @Override
11 public Date convert(String source) {
12
13 //实现 将日期串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
14
15 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
16
17 try {
18 //转成直接返回
19 return simpleDateFormat.parse(source);
20 } catch (ParseException e) {
21 // TODO Auto-generated catch block
22 e.printStackTrace();
23 }
24 //如果参数绑定失败返回null
25 return null;
26 }
27 }
Converter<String,Date>是一个模板,在这里我们将String类型转换成Date类型来存储到数据库中。
五、解析静态资源
1 <!-- 静态资源解析包括 :js、css、img、..使得网页可以访问这些地址-->
2 <mvc:resources location="/js/" mapping="/js/**"/>
3 <mvc:resources location="/img/" mapping="/img/**"/>
六、校验器
1 <mvc:annotation-driven validator="validator"></mvc:annotation-driven>
2
3 <!-- 校验器 -->
4 <bean id="validator"
5 class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
6 <!-- hibernate校验器-->
7 <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
8 <!-- 指定校验使用的资源文件,在文件中配置校验错误信息,如果不指定则默认使用classpath下的ValidationMessages.properties -->
9 <property name="validationMessageSource" ref="messageSource" />
10 </bean>
11 <!-- 校验错误信息配置文件 -->
12 <bean id="messageSource"
13 class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
14 <!-- 资源文件名-->
15 <property name="basenames">
16 <list>
17 <value>classpath:CustomValidationMessages</value>
18 </list>
19 </property>
20 <!-- 资源文件编码格式 -->
21 <property name="fileEncodings" value="utf-8" />
22 <!-- 对资源文件内容缓存时间,单位秒 -->
23 <property name="cacheSeconds" value="120" />
24 </bean>
七、全局异常处理器
1 <!-- 全局异常处理器,只要实现HandlerExceptionResolver接口就是全局异常处理器-->
2 <bean class="cn.itcast.ssm.exception.CustomExceptionResolver"></bean>
1 package cn.itcast.ssm.exception;
2 public class CustomException extends Exception {
3
4 //异常信息
5 public String message;
6
7 public CustomException(String message){
8 super(message);
9 this.message = message;
10 }
11
12 public String getMessage() {
13 return message;
14 }
15
16 public void setMessage(String message) {
17 this.message = message;
18 }
19 }
1 package cn.itcast.ssm.exception;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5
6 import org.springframework.web.servlet.HandlerExceptionResolver;
7 import org.springframework.web.servlet.ModelAndView;
8
9 public class CustomExceptionResolver implements HandlerExceptionResolver {
10
11 @Override
12 public ModelAndView resolveException(HttpServletRequest request,
13 HttpServletResponse response, Object handler, Exception ex) {
14 //handler就是处理器适配器要执行Handler对象(只有method)
15
16 // 解析出异常类型
17 // 如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示
18 // String message = null;
19 // if(ex instanceof CustomException){
20 // message = ((CustomException)ex).getMessage();
21 // }else{
22 //// 如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
23 // message="未知错误";
24 // }
25
26 //上边代码变为
27 CustomException customException = null;
28 if(ex instanceof CustomException){
29 customException = (CustomException)ex;
30 }else{
31 customException = new CustomException("未知错误");
32 }
33
34 //错误信息
35 String message = customException.getMessage();
36
37
38 ModelAndView modelAndView = new ModelAndView();
39
40 //将错误信息传到页面
41 modelAndView.addObject("message", message);
42
43 //指向错误页面
44 modelAndView.setViewName("error");
45
46
47 return modelAndView;
48 }
49
50 }
八、文件上传
1 <!-- 文件上传 -->
2 <bean id="multipartResolver"
3 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
4 <!-- 设置上传文件的最大尺寸为5MB -->
5 <property name="maxUploadSize">
6 <value>5242880</value>
7 </property>
8 </bean>
九、拦截器
1 <!--拦截器 -->
2 <mvc:interceptors>
3 <!--多个拦截器,顺序执行 -->
4 <!-- 登陆认证拦截器 -->
5 <mvc:interceptor>
6 <mvc:mapping path="/**"/>
7 <bean class="cn.itcast.ssm.interceptor.LoginInterceptor"></bean>
8 </mvc:interceptor>
9 <mvc:interceptor>
10 <!-- /**表示所有url包括子url路径 -->
11 <mvc:mapping path="/**"/>
12 <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean>
13 </mvc:interceptor>
14 <mvc:interceptor>
15 <mvc:mapping path="/**"/>
16 <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2"></bean>
17 </mvc:interceptor>
18 </mvc:interceptors>
1 package cn.itcast.ssm.interceptor;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5
6 import org.springframework.web.servlet.HandlerInterceptor;
7 import org.springframework.web.servlet.ModelAndView;
8
9 public class HandlerInterceptor1 implements HandlerInterceptor {
10
11 //进入 Handler方法之前执行
12 //用于身份认证、身份授权
13 //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
14 @Override
15 public boolean preHandle(HttpServletRequest request,
16 HttpServletResponse response, Object handler) throws Exception {
17
18 System.out.println("HandlerInterceptor1...preHandle");
19
20 //return false表示拦截,不向下执行
21 //return true表示放行
22 return true;
23 }
24
25 //进入Handler方法之后,返回modelAndView之前执行
26 //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
27 @Override
28 public void postHandle(HttpServletRequest request,
29 HttpServletResponse response, Object handler,
30 ModelAndView modelAndView) throws Exception {
31
32 System.out.println("HandlerInterceptor1...postHandle");
33
34 }
35
36 //执行Handler完成执行此方法
37 //应用场景:统一异常处理,统一日志处理
38 @Override
39 public void afterCompletion(HttpServletRequest request,
40 HttpServletResponse response, Object handler, Exception ex)
41 throws Exception {
42
43 System.out.println("HandlerInterceptor1...afterCompletion");
44 }
45
46 }
1 package cn.itcast.ssm.interceptor;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5
6 import org.springframework.web.servlet.HandlerInterceptor;
7 import org.springframework.web.servlet.ModelAndView;
8
9 public class HandlerInterceptor2 implements HandlerInterceptor {
10
11
12 //进入 Handler方法之前执行
13 //用于身份认证、身份授权
14 //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
15 @Override
16 public boolean preHandle(HttpServletRequest request,
17 HttpServletResponse response, Object handler) throws Exception {
18
19 System.out.println("HandlerInterceptor2...preHandle");
20
21 //return false表示拦截,不向下执行
22 //return true表示放行
23 return true;
24 }
25
26 //进入Handler方法之后,返回modelAndView之前执行
27 //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
28 @Override
29 public void postHandle(HttpServletRequest request,
30 HttpServletResponse response, Object handler,
31 ModelAndView modelAndView) throws Exception {
32
33 System.out.println("HandlerInterceptor2...postHandle");
34
35 }
36
37 //执行Handler完成执行此方法
38 //应用场景:统一异常处理,统一日志处理
39 @Override
40 public void afterCompletion(HttpServletRequest request,
41 HttpServletResponse response, Object handler, Exception ex)
42 throws Exception {
43
44 System.out.println("HandlerInterceptor2...afterCompletion");
45 }
46
47 }
1 package cn.itcast.ssm.interceptor;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5 import javax.servlet.http.HttpSession;
6
7 import org.springframework.web.servlet.HandlerInterceptor;
8 import org.springframework.web.servlet.ModelAndView;
9
10 public class LoginInterceptor implements HandlerInterceptor {
11
12
13 //进入 Handler方法之前执行
14 //用于身份认证、身份授权
15 //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
16 @Override
17 public boolean preHandle(HttpServletRequest request,
18 HttpServletResponse response, Object handler) throws Exception {
19
20 //获取请求的url
21 String url = request.getRequestURI();
22 //判断url是否是公开 地址(实际使用时将公开 地址配置配置文件中)
23 //这里公开地址是登陆提交的地址
24 if(url.indexOf("login.action")>=0){
25 //如果进行登陆提交,放行
26 return true;
27 }
28
29 //判断session
30 HttpSession session = request.getSession();
31 //从session中取出用户身份信息
32 String username = (String) session.getAttribute("username");
33
34 if(username != null){
35 //身份存在,放行
36 return true;
37 }
38
39 //执行这里表示用户身份需要认证,跳转登陆页面
40 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
41
42 //return false表示拦截,不向下执行
43 //return true表示放行
44 return false;
45 }
46
47 //进入Handler方法之后,返回modelAndView之前执行
48 //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
49 @Override
50 public void postHandle(HttpServletRequest request,
51 HttpServletResponse response, Object handler,
52 ModelAndView modelAndView) throws Exception {
53
54 System.out.println("HandlerInterceptor1...postHandle");
55
56 }
57
58 //执行Handler完成执行此方法
59 //应用场景:统一异常处理,统一日志处理
60 @Override
61 public void afterCompletion(HttpServletRequest request,
62 HttpServletResponse response, Object handler, Exception ex)
63 throws Exception {
64
65 System.out.println("HandlerInterceptor1...afterCompletion");
66 }
67
68 }
十、小记
SpringMVC博大精深,是Spring的一个模块,是一种web框架,将MVC应用于B/S模式中,将每一个步骤进行了详细而彻底的解耦合,虽然步骤复杂了一些,真正需要我们实现的地方还是可以承受的,最重要的就是xml的配置文件了,比如说关于DispatcherServlet运行的配置文件(一般命名为springmvc.xml)就包含了这个思想内涵的很多地方,同样这一框架也有强大的安全性和可扩展性,诸如面向切面编程(AOP)等思想都是有着强大生命力的,再加上和mybatis结合,适合一些大中型的企业级项目,学会SpringMVC有着很大的现实意义和使用价值。