Spring3+SpingMVC+Hibernate4全注解环境配置
我没有使用maven,直接使用Eclipse创建动态Web项目,jar包复制在了lib下。这样做导致我马上概述的项目既依赖Eclipse和其项目结构,又依赖我复制在lib下的那些jar包版本。
jar包下载地址:http://pan.baidu.com/s/1gdARAy3
但是我现在还是会以这种形式阐述,因为对于接触新事物而言的人,我觉得首先需要的是热情,这样才能有勇气面对尝试过程中的失败。热情从哪里来?热情从在事物获得的每一点成就感而来,现在按照以下步骤,我们来获得一点成就感,然后再讨论技术层面的事情(我记得以前刚学Java的时候,如果没有Eclipse那神奇的自动补全,我一定坚持不下来,早就转行了。不切实际的艰苦只能浪费时间和磨练心性,它在某些时候不一定是必要的,它应当成为一个可选项而不是一条必经路)。
环境Spring3.2.0,Hibernate4.1.6,Eclipse 3.7,Tomcat5.5,JDK1.6.45,Oracle10g(不要对我的环境版本搭配和数据库使用抱有异议,我本地恰好就是JDK1.6.45的,恰好Tomcat就是5.5的,恰好Oracle在新建项目前就已经安装好了)。
这是一个SSH项目,所以我假设各位了解或听过一些J2EE的术语,我们将跃过“从入门到精通”系列的引言,直接让你来看看我到底是怎么做的,还有那中间的波折。
首先,我在Eclipse下建立了一个动态Web项目,这时候除了目录结构外,唯一有点内容的就是WEB-INF下的web.xml了,大话不多说,如果你已经把我贴了下载地址的jar包复制到了lib下,那么在web.xml里复制如下内容。
1 <listener> 2 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 3 </listener> 4 5 <context-param> 6 <param-name>contextConfigLocation</param-name> 7 <!-- <param-value>/WEB-INF/applicationContext.xml</param-value> --> 8 <param-value>classpath:applicationContext.xml</param-value> 9 </context-param> 10 <servlet> 11 <servlet-name>springMVC</servlet-name> 12 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 13 <init-param> 14 <param-name>contextConfigLocation</param-name> 15 <param-value>classpath*:spring-mvc.xml</param-value> 16 </init-param> 17 <load-on-startup>1</load-on-startup> 18 </servlet> 19 <servlet-mapping> 20 <servlet-name>springMVC</servlet-name> 21 <url-pattern>/</url-pattern> 22 </servlet-mapping> 23 <filter> 24 <filter-name>encodingFilter</filter-name> 25 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 26 <init-param> 27 <param-name>encoding</param-name> 28 <param-value>UTF-8</param-value> 29 </init-param> 30 <init-param> 31 <param-name>forceEncoding</param-name> 32 <param-value>true</param-value> 33 </init-param> 34 </filter> 35 <filter-mapping> 36 <filter-name>encodingFilter</filter-name> 37 <url-pattern>/*</url-pattern> 38 </filter-mapping>
Very Nice!现在除了自动的xml头,<welcome-file-list>,就是以上spring配置信息了。这里配置了Spring和SpringMVC,<listener>和contextConfigLocation是对spring的配置,前者是spring的监听类,后者是spring配置文件的路径,这里一目了然,毫无疑问。
然后从servlet开始,都是SpringMVC的配置,这里先后配置了类似全局Filter的类DispatcherServlet的路径,然后是SpringMVC的配置文件,我们将在那儿启用我们的全注解功能。servlet-mapping就真的像Filter一样,配置了需要拦截的请求路径,最后是一些字符集配置,在领略到成就感之前不叙述了,免得打击士气。
和刚才配置的信息一致的,我们在src下建立applicationContext.xml(这名字好长!虽然可以换掉它,但我在项目里一看见这名字就知道它是干什么的了,所以不换了)和servlet-mvc.xml。
首先配置applicationContext:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL" /> <property name="username" value="fm" /> <property name="password" value="admin" /> </bean> <!-- 配置Hibernate --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="packagesToScan" > <list> <value></value> </list> </property> <property name="hibernateProperties"> <props> <prop key="dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.current_session_context_class">thread</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <context:annotation-config /> <context:component-scan base-package="com.eap.filemanager.service" /> <context:component-scan base-package="com.eap.pub.user.service.impl" /> <context:component-scan base-package="com.eap.pub.user.dao" /> </beans>
全部的内容,各位直接复制呗。这里xml头包括了注解的路径,然后配置DataSource,配置Hibernate,最后一段就是启用注解了,说是<context:annotation-config />在这个版本已经不需要写了,反正我项目现在正在跑着,先复制上来再说。最后路径扫描,我是定义到包的,因为通配符好像没起作用,老是报错,我就把所有需要扫描的包都写上去了。
接下来是SpringMVC,配置SpringMVC之前,其实各位已经可以开始和数据库进行交互操作了,可以编写DAO的代码了,我再说一遍,DAO是Data Access Object,这一层该写什么不该写什么,这名字清清楚楚了已经!
servlet-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- ViewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <!-- 使用默认的注解映射 --> <mvc:annotation-driven /> <!-- 自动扫描controller包中的控制器 --> <context:component-scan base-package="com.eap.filemanager.cmd" /> </beans>
xml头,ViewResolver,然后启用注解,然后扫描。
这其中,第二部分的意思就是,SpringMVC里有个跳转类型叫做ModelAndView,它setView之后,就会自动跑到view名字+后缀的文件上去,比如setView("index"),那么在这个配置文件下,就会自动跳转到index.jsp上,而且是WEB-INF/jsp下的index.jsp上,WEB-INF下的jsp无法直接通过地址栏访问,所以这种控制可以让容器对资源访问权限进行管理。
大功告成,最困难的配置文件就这么搞定了,我可是花了好多时间在网上搜了来着,现在你们已经拥有了基石般的配置文件信息,你可以在上面测试通配符啦等你觉得方便的任何内容。
好了,看配置文件上的包也能知道,我的DAO是这么写的。
非常奇怪,使用@Controller和@Resource必须得实现接口,得这么写:
接口:
public interface IUserDao { public List query(String sql); public List queryByName(String name); }
DAO代码:
@Repository public class UserDao implements IUserDao{ Session session; @Autowired UserDao(SessionFactory sessionFactory){ session = sessionFactory.getCurrentSession(); session.beginTransaction(); } public List query(String sql) { SQLQuery query = session.createSQLQuery(sql).addEntity(User.class); return query.list(); } public List queryByName(String username){ String sql = "select * from pub_user where username=?"; SQLQuery query = session.createSQLQuery(sql).addEntity(User.class); query.setString(0, username); return query.list(); } }
这里我可是试了好多种方法,由于我喜欢直接写sql语句,以充分利用关系数据库的“关系”特性(毕竟关系型数据库不是和对象无缝贴合的,要发挥其最大优势应该从数据表之间的关系入手。有异议就提,最好论据充分,我需要证据不是结论,有了证据我也可以自己分析分析了,说不定我还知道点别的,能得出更有用的结论),所以我在这里使用了SQLQuery,否则你可以直接session.createQuery(hql)。但是,这里有一个问题,我继承HibernateDAOSupport反而会获取不到session或别的什么东西。
我在这儿顺便附上JavaBean的,完全注解。
@Entity @Table(name="pub_user") public class User { @Id @Column(name = "id", unique = true, nullable = false) String id; @Column(name="username") String username; @Column(name="passwd") String passwd; @Column(name="user_ip") String userIp; //getter和setter...自己用Eclipse生成吧,我省略掉了 }
DAO这样写,那么我的Service就可以这么写了。一样的先接口,再@Controller
public interface UserService { public List getUsers(); }
@Service public class UserServiceImpl implements UserService{ @Resource IUserDao dao; public List getUsers(){ List list = dao.query("select * from pub_user"); return list; } }
你看哦,我这里@Resource,必须写在接口定义的变量上面,然后Spring会自己去找谁实现了它并且还是@Resource的。关于具体命名管理,还有一些内容就不说了,这个在我们这么点代码的例子中根本就遇不到的。记得我说的,万一有两个DAO都实现了这个接口,那该怎么办呢,这就是命名管理要做的事情,自己去看吧(说不定你还没看完这篇博客就放弃Spring了,那么写上去真是多此一举……什么?你不会放弃?你不会放弃我也不写啊,我又没用到)。
接下来就是@Controller了,这里不需要接口了,嘿嘿(我就说,UserDao都是UserDao<T>,里面的save方法都不用定义具体类型了,干嘛每个模块还要用不同的DAO?既然大家都用一个DAO,干嘛还要依赖接口编程?我直接泛型<T>继承了一个HibernateDAO后,Spring还不许我这么访问DAO。不用拿概念忽悠我,我知道内聚和耦合在什么样的规模下会展现出自身特性的怎样的优缺点,但注解依赖接口编程的强制性让我搭建环境的过程中走了很多弯路。好吧,也有可能明明有办法不用建接口,只是我不知道罢了)。
@Controller public class FileManagerControl{ @Autowired UserService service;//其实我这不是User的Controller,反正Controller过程都一样,大家看看调用过程就行了哦 @RequestMapping({"/"}) public ModelAndView welcome(){ ModelAndView mv = new ModelAndView(); mv.addObject("users", service.getUsers()); mv.setViewName("index"); return mv; } }
这样,http://localhost:8080/[projectName]/,对应@RequestMapping({"/"})(如果里面是"/index.do"那么连接就是http://localhost:8080/[projectName]/index.do了)就能访问ModelAndView设置的index.jsp了。这时候jsp上,${users}将会调用User的toString()方法,很可惜,我试了${users.username},报错,不知道怎么搞。
最后呈上完整项目的同时,顺便也任性一把:http://download.csdn.net/detail/nietzsche0/9038115
这是CSDN下载,需要3个资源分。不是为了资源分,就是任性而已(之前传的,现在就是不想再传一份到网盘,就是不想把资源分下调)。我看登录CSDN下载项目比我搭建环境处理问题要容易得多了,也避免了像我一样,堆积了大量资料结果最后根本就不去做了。