搞JAVA的小伙伴们都遇到这样的面试官:
问:你会SSH吗?
答:会
问:说说怎么用的?
答:。。。 (内心爆出一句脏话)
很久没有弄过SSH了,还记得当初用的是hibernate 3, strut2,然而JAVA发展太快了,我们今天要讲述的是 Spring 3.1 + Hibernate 4.2 + Struts 2.3。 搞SSH的都知道,这个版本太蛋疼了,各种不兼容,各种不知道怎么配置。 度娘被蹂躏了千百次,终于将新版的SSH搞定了,分享一下。
首先是架包,搞JAVA最头疼的就是乱七八糟的jar,想用下SSH,发现居然要导入那么多jar,而且架包之间还有依赖,所以最好的就是使用Maven去找架包,但是有些小伙伴没有MAVEN环境怎么办?只能一个一个的去找,一个一个去导入到项目中。苦逼的程序员。
所有依赖的架包我都已经上传,有需要的到附件里下载,a-d.7z, f-h.7z, j-p.7z 和 s-z.7z。
项目结构如图:
配置文件有3个:web.xml, dispatcher-servlet.xml 和 struts.xml
先看最简单的struts.xml, 我把他放在src下面了,就直接打到classpath下面了。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <constant name="struts.objectFactory" value="spring"/> <package name="credit" extends="struts-default" namespace="/"> <action name="city" class="com.bank.credit.action.CityAction"> <result name="success">/bank.jsp</result> </action> </package> </struts>很简单的配置,就陪着了一个city,成功返回bank.jsp
再看看spring的配置:
<?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:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:sec="http://www.springframework.org/schema/security" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>text/plain;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <context:component-scan base-package="com.bank.credit"></context:component-scan> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3307/bank?characterEncoding=UTF-8&characterSetResults=UTF-8" /> <property name="user" value="root" /> <property name="password" value="admin" /> <property name="maxPoolSize" value="100" /> <property name="minPoolSize" value="20" /> <property name="initialPoolSize" value="10" /> <property name="maxIdleTime" value="1800" /> <property name="acquireIncrement" value="10" /> <property name="idleConnectionTestPeriod" value="600" /> <property name="acquireRetryAttempts" value="30" /> <property name="breakAfterAcquireFailure" value="false" /> <property name="preferredTestQuery" value="SELECT NOW()" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg ref="dataSource"></constructor-arg> </bean> <!-- hibernate 需要的信息 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan"> <list> <value>com.bank.credit.entity</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean> <aop:aspectj-autoproxy expose-proxy="true" /> <tx:annotation-driven transaction-manager="txManager" /> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com..service..*.*(..))" /> </aop:config> </beans>主要是配置了数据源和hibernate的sessionFactory还有事务。和网上的一样。
有一个要注意的地方:
<property name="packagesToScan">
<list>
<value>com.bank.credit.entity</value>
</list>
</property>
这个一定要配置正确,不然查询时会报错 【hibernate4 xxx is not mapped】,这个指定对了就不要hibernate的配置文件了,不需要做mapping了,通过注解的方式就可以。另外事务一定要配置。
再看看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" 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_3_0.xsd" version="3.0"> <display-name>credit</display-name> <filter> <filter-name>CharacterEncoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/dispatcher-servlet.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> </web-app>定义了spring的监听器和配置文件,定义了struts的拦截器。这个没什么好讲的。
看下City这个Entity的类:
package com.bank.credit.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "BANK_CITY") public class City { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; @Column(name = "NAME") private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
指定table name 和 column name。
数据库的建表语句:
CREATE TABLE `bank_city` ( `ID` INT(9) NULL DEFAULT NULL, `NAME` VARCHAR(20) NULL DEFAULT NULL ) COLLATE='utf8_general_ci' ENGINE=InnoDB;
看Action类:
package com.bank.credit.action; import java.util.List; import javax.annotation.Resource; import org.apache.struts2.ServletActionContext; import org.springframework.stereotype.Controller; import com.bank.credit.entity.City; import com.bank.credit.service.CityService; import com.opensymphony.xwork2.ActionSupport; @Controller public class CityAction extends ActionSupport { private static final long serialVersionUID = 1L; @Resource private CityService service; public String execute() throws Exception { List<City> citys = service.list(); ServletActionContext.getRequest().setAttribute("CITYLIST", citys); return SUCCESS; } }
类加@Controller 注解, 用到的Service使用@Resource注入
再看下Service的实现类:
package com.bank.credit.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.bank.credit.dao.CityDao; import com.bank.credit.entity.City; import com.bank.credit.service.CityService; @Service public class CityServiceImpl implements CityService{ @Autowired private CityDao dao; @Override public List<City> list() { return dao.listCitys(); } }
类使用@Service注解,使用的DAO使用@Autowired注入
再看下DAO的实现类:
package com.bank.credit.dao.impl; import java.util.List; import org.springframework.stereotype.Repository; import com.bank.credit.dao.CityDao; import com.bank.credit.entity.City; @Repository public class CityDaoImpl extends BaseDao implements CityDao { @Override public List<City> listCitys() { return this.findAll(City.class); } }
类使用@Repository 注解,继承了BaseDao
再看看BaseDao这个类:
package com.bank.credit.dao.impl; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; public class BaseDao { @Autowired private SessionFactory sessionFactory; public Session getSession(){ return sessionFactory.getCurrentSession(); } protected void save(Object obj) { getSession().save(obj); } @SuppressWarnings("unchecked") protected <T> T get(Class<T> clazz, int id) { return (T) getSession().get(clazz, id); } @SuppressWarnings("unchecked") protected <T> List<T> findAll(Class<T> clazz) { return getSession().createCriteria(clazz).list(); } protected void update(Object obj) { getSession().update(obj); } protected void delete(Class<?> clazz, int id) { getSession().delete(get(clazz, id)); } protected void delete(Object obj) { getSession().delete(obj); } }
注入了SessionFacotry,使用的都是Session(Hibernate4)的方法