用SpringMVC+Spring+Mybati这三个框架用了这么长的时间了,虽然说会用,但是有种知其然不知其所以然的感觉,工作之余特地自己搭建了一个,对里面的各种配置了解得深入了一点,现总结如下,会穿插一点lz个人对其中的理解,有误之处还望轻碰后指出,如果对后来人有所帮助,lz会非常开心,因为lz开始学的时候就是参考了非常多前辈写的博客才有今天的。
1楼主用的是Myeclipse,创建一个java web 项目:需要说明的是,next到最后不要忘了点击Generate web.xml deployment descriptor,会在WEB-INF中自动生成web.xml文件,不用在别的位置拷贝。
2,web.xml
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
说明1:classpath。
需要说明的是很多初学者(包括楼主)对这个classpath不知指的是哪个路径
classpath:首先 classpath是指 WEB-INF文件夹下的classes目录 ,可能有的人就会懵逼,在环境中哪里WEB-INF 哪里有classes,在计算机中找到你创建的项目进入到WEB-INF中就会发现有一个classes文件夹
如下:
附:在web.xml中classpath和classpath*的区别
classpath 和 classpath* 区别:
classpath:只会到你指定的class路径中查找找文件;
classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找.
如果我在web.xml中定义的是:classpath:META-INF/spring/application-context.xml
那么只有META-INF/spring底下的application-context.xml会被加载到上下文中。
“**/” 表示的是任意目录;
“*/applicationContext-.xml” 表示任意目录下的以”applicationContext-“开头的XML文件。
程序部署到tomcat后,src目录下的配置文件会和class文件一样,自动copy到应用的 WEB-INF/classes目录下
classpath:与classpath*:的区别在于, 前者只会从第一个classpath中加载,而 后者会从所有的classpath中加载 如果要加载的资源, 不在当前ClassLoader的路径里,那么用classpath:前缀是找不到的, 这种情况下就需要使用classpath*:前缀 ,在多个classpath中存在同名资源,都需要加载, 那么用classpath:只会加载第一个,这种情况下也需要classpath*:前缀
注意:
用classpath*:需要遍历所有的classpath,所以加载速度是很慢的,因此,在规划的时候,应该尽可能规划好资源文件所在的路径,尽量避免使用classpath*。
参考:https://zhidao.baidu.com/question/919326352548812699.html,http://perfy315.iteye.com/blog/2009258
classpath:applicationContext.xml读取的是web.xml同级目录下classes中的Spring配置文件applicationContext.xml
说明一点,注意导入的包不要少添加了,或者class的包名加类不要写错了,写完用ctrl+鼠标左键
检查一下如果能跳转到包下就说明没问,如果点不动则说明包没导入或包名加类写的有问题。
说明2:contextConfigLocation
ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。加载applicationContext.xml文件,如果在web.xml中不写任何参数配置信息,默认的路径是/WEB-INF/applicationContext.xml,在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml;
如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数:
说明3:可以在web.xml中配置监听器来输出Log4j日志。
说明4:Spring使用IntrospectorCleanupListener清理缓存,这个监听器的作用是在web应用关闭时刷新JDK的JavaBeans的Introspector缓存,以确保Web应用程序的类加载器以及其加载的类正确的释放资源。
param>
<param-name>contextConfigLocationparam-name>
<param-value>
/WEB-INF/classes/applicationContext-*.xml
param-value>
param>
由此可见applicationContext.xml的文件位置就可以有两种默认实现:
第一种:直接将之放到/WEB-INF下,之在web.xml中声明一个listener;
第二种:将之放到classpath下,但是此时要在web.xml中加入,用它来指明你的applicationContext.xml的位置以供web容器来加载。
参考:http://blog.csdn.net/ysughw/article/details/8992322
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
说明1:
DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:
1、文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
2、通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
3、 通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
4、通过ViewResolver解析逻辑视图名到具体视图实现;
5、本地化解析;
6、渲染具体的视图等;
7、如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。
8、 如果只配置拦截类似于*.do格式的url,则对静态资源的访问是没有问题的,但是如果配置拦截了所有的请求(如我们上面配置的“/”),就会造成js文件、css文件、图片文件等静态资源无法访问。
9、处理静态页面,JS,CSS文件,
第一种是采用,(一般Web应用服务器默认的Servlet名称是”default”,所以这里我们激活Tomcat的defaultServlet来处理静态文件,在web.xml里配置如下代码即可:)
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>/js/*url-pattern>
<url-pattern>/css/*url-pattern>
<url-pattern>/images/*url-pattern>
<url-pattern>/fonts/*url-pattern>
servlet-mapping>
第二种是采用,在springmvc的配置文件中加入以下代码:
<mvc:resources mapping="/js/**" location="/static_resources/javascript/"/>
<mvc:resources mapping="/styles/**" location="/static_resources/css/"/>
<mvc:resources mapping="/images/**" location="/static_resources/images/"/>
说明2:
load-on-startup:表示启动容器时初始化该Servlet;
url-pattern:表示哪些请求交给Spring Web MVC处理, “/” 是用来定义默认servlet映射的。也可以如“*.html”表示拦截所有以html为扩展名的请求。
/ 会匹配到/login这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url
/ 会匹配所有url:路径型的和后缀型的url(包括/login,.jsp,.js和.html等)
参考:http://blog.csdn.net/lqx1988221/article/details/12620689
web.xml就写这么多。
3:applicationContext.xml
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:db.properties">property>
bean>
或者在添加如下语句:、
<context:property-placeholderlocation="classpath:db.properties"/>
db.properties为:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123456
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
bean>
读取配置文件中键值对通过${}来赋值
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis.cfg.xml"/>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lydia,com.tarena" />
<property name="sqlSessionFactory" ref="sqlSessionFactory">property>
bean>
有时候我们指定的基包下面的并不全是我们定义的Mapper接口,为此MapperScannerConfigurer还为我们提供了另外两个可以缩小搜索和注册范围的属性。一个是annotationClass,另一个是markerInterface。
annotationClass:当指定了annotationClass的时候,MapperScannerConfigurer将只注册使用了annotationClass注解标记的接口。
markerInterface:markerInterface是用于指定一个接口的Mapper,当指定了markerInterface之后,MapperScannerConfigurer将只注册继承自markerInterface的接口。
如果上述两个属性都指定了的话,那么MapperScannerConfigurer将取它们的并集,而不是交集。即使用了annotationClass进行标记或者继承自markerInterface的接口都将被注册为一个MapperFactoryBean。
摘自http://elim.iteye.com/blog/1843309,感谢楼主分享。
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save" propagation="REQUIRED"/>
<tx:method name="get" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut expression="execution(* cn.sxt.service.impl.*.*(..))" id="pointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
aop:config>
<context:component-scan base-package="cn.sxt"/>
用法:
@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。
参考:http://blog.csdn.net/bao19901210/article/details/41724355
4mvc.xml
<context:component-scan base-package="cn.sxt.controller"/>
5 mybatis.cfg.xml
<mappers>
<mapper resource="cn/sxt/vo/user.mapper.xml" />
mappers>
6user.mapper.xml
namespace="cn.sxt.vo.user.mapper">
<select id="list" resultType="cn.sxt.vo.User">
select * from user
select>
7UserDaoImpl
/*@Repository用于标注数据访问组件,即DAO组件*/
@Repository("userDao")
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{
@Autowired
@Override
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
@Override
public List list() {
// TODO Auto-generated method stub
return getSqlSession().selectList("cn.sxt.vo.user.mapper.list");
}
}
8UserServiceImpl
@Service("userService")
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
public List list(){
return userDao.list();
}
}
@Controller
public class UserController {
@Autowired
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@RequestMapping("/list")
public String list(ModelMap map){
map.addAttribute("list",userService.list());
return "/list.jsp";
}
}
@Service用于标注业务层组件
@Controller用于标注控制层组件(如struts中的action
@Repository用于标注数据访问组件,即DAO组件
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
附demo源码:http://download.csdn.net/detail/btwangzhi/9752783