SSH2整合完整案例
注解配置:Struts2+Spring2.5+Hibernate3.3+Oracle11g
本文介绍
1.Struts2+Spring2.5+Hibernate3.3的整合
2.采用单元测试
3.加入了lob类型的操作配置
4.介绍oralce驱动 本文采用oracle11g
5.在HIbernate中采用“枚举”设置映射关系
jar的下载:
Struts2: http://struts.apache.org/download.cgi#struts2013
Hibernate: http://www.hibernate.org/ 点击Hibernate Core 下载
Spring: http://www.springsource.org/download
Oracle的驱动介绍
- class12.jar(jdk 1.2 / 1.3 )
- class14.jar(jdk 1.4 / 1.5)
- 其实只要安装了oracle 就不用下载驱动包了,在安装程序中就有D:\app\Admin\product\11.1.0\db_1\jdbc\lib 这个目录下 根据使用的jdk 选择对应的驱动包就可以了。(例如: ojdbc6.jar)
SSH2整合需要的Jar
1.Strusts
- javassist-3.4.GA.jar
- commons-fileupload-1.2.1.jar
- commons-logging-1.0.4.jar
- freemarker-2.3.15.jar
- ognl-2.7.3.jar
- struts2-core-2.1.8.jar
- xwork-core-2.1.6.jar
- struts2-spring-plugin-2.1.8.jar
2.Hibernate
- commons-collections-3.1.jar
- dom4j-1.6.1.jar
- ehcache-1.2.3.jar
- ejb3-persistence.jar
- hibernate-annotations.jar
- hibernate-cglib-repack-2.1_3.jar
- hibernate-commons-annotations.jar
- hibernate-entitymanager.jar //为了使用 枚举 类型的映射 这个包
- hibernate3.jar
- javassist-3.4.GA.jar
- jta-1.1.jar
- log4j.jar
- slf4j-api-1.5.2.jar
- slf4j-log4j12.jar
3.Spring
- aspectjrt.jar
- aspectjweaver.jar
- c3p0-0.9.1.2.jar
- cglib-nodep-2.1_3.jar
- common-annotations.jar
- log4j-1.2.15.jar
- spring.jar
整合步骤先整合 Spring2.5+Hibernate3.3 成功后在整合 Struts2 这样就不容易报错,而且 报错误后也便于找出问题。
spring配置文件模版可以到 spring自带的一些例子中进行拷贝。
applicationContext.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
- <!-- 采用扫描 + 注解的方式进行开发 可以提高开发效率,后期维护变的困难了,可读性变差了 -->
- <context:component-scan base-package="com.sh"/>
- <!-- 采用c3p0数据源 这个是在企业中用的比较多的一个数据源 -->
- <!-- destroy-method="close"的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用 -->
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
- <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
- <property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
- <property name="user" value="luob"/>
- <property name="password" value="m123"/>
- <!-- 连接池中的最大连接数 -->
- <property name="maxPoolSize" value="150"/>
- <!-- 连接池中的最小连接数 -->
- <property name="minPoolSize" value="1"></property>
- <!-- 初始化连接池中的 连接数,取值 在 minPoolSize 和 maxPoolSize 之间,default:3-->
- <property name="initialPoolSize" value="3"/>
- <!-- 最大空闲时间,60s内该连接没有被使用则被丢弃,若为0 永不丢弃.default:0 -->
- <property name="maxIdleTime" value="60"/>
- <!-- 当连接数不够时,每次同时创建多少个连接 -->
- <property name="acquireIncrement" value="1"/>
- <!-- 每60s检查连接池中的所有空间连接,如果没有被使用,就被放弃, default:0 -->
- <property name="idleConnectionTestPeriod" value="60"/>
- </bean>
- <!--从c3p0数据源中抽取出JDBC的代理对象-->
- <bean id="nativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.C3P0NativeJdbcExtractor" lazy-init="true" />
- <!--9i: org.springframework.jdbc.support.lob.OracleLobHandler -->
- <!--10g以后:org.springframework.jdbc.support.lob.DefaultLobHandler(mysql,DB2等都可以用这个) -->
- <bean id="lobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true">
- <!-- 9i: 指定操作lob类型数据的jdbc代理对象 如果上面的 lobHandler 换了下面的就不需要了 -->
- <property name="nativeJdbcExtractor">
- <ref local="nativeJdbcExtractor" />
- </property>
- </bean>
- <!-- 将Hibernate中的事物交给Spring进行接管 -->
- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <!-- 指定sessiongFactory中的数据源 -->
- <property name="dataSource" ref="dataSource"/>
- <!-- 指定hibernate的属性 -->
- <property name="hibernateProperties">
- <value>
- <!-- hibernate使用的 方言 -->
- hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
- <!-- 根据实体的映射文件生成表结构 -->
- hibernate.hbm2ddl.auto=update
- <!-- 格式化sql -->
- hibernate.format_sql=false
- <!-- 是否打印出sql语句 -->
- hibernate.show_sql=false
- </value>
- </property>
- <!-- 定义lob操作对象 -->
- <property name="lobHandler">
- <ref bean="lobHandler" />
- </property>
- <!-- 指定hibernate的映射文件 -->
- <property name="mappingResources">
- <list>
- <value>com/sh/employee/model/Employee.hbm.xml</value>
- </list>
- </property>
- </bean>
- <!-- 配置使用基于Hibernate的事务管理器 -->
- <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <!-- spring需要通过sessionFactory来开启事务 -->
- <property name="sessionFactory" ref="sessionFactory"/>
- </bean>
- <!--Spring中的事物配置声明.1 基于xml 配置方式 2.基于注解来声明那些类-->
- <tx:annotation-driven transaction-manager="txManager"/>
- </beans>
Employee.java
- package com.sh.employee.model;
- public class Employee {
- private String username;
- private String password;
- //枚举类型
- private Gender gender=Gender.MAN;
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public Gender getGender() {
- return gender;
- }
- public void setGender(Gender gender) {
- this.gender = gender;
- }
- public Employee(String username, String password) {
- super();
- this.username = username;
- this.password = password;
- }
- public Employee() {
- super();
- // TODO Auto-generated constructor stub
- }
- public Employee(String username, String password, Gender gender) {
- super();
- this.username = username;
- this.password = password;
- this.gender = gender;
- }
- }
Gender.java
- package com.sh.employee.model;
- public enum Gender {
- //分为字面值 :MAN / WOMAN
- //索引值:0 1
- MAN,WOMAN
- }
Employee.hbm.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.sh.employee.model">
- <class name="Employee">
- <id name="username" length="20"/>
- <property name="password" length="20" not-null="true"/>
- <property name="gender" not-null="true" length="5">
- <type name="org.hibernate.type.EnumType">
- <param name="enumClass">com.sh.employee.model.Gender</param>
- <!--type:12 为java.sql.Types.VARCHAR常量值,即保存枚举字面值到数据库。
- 如果不指定(删除)type:则保存枚举索引值到数据库(从0 开始) -->
- <param name="type">12</param>
- </type>
- </property>
- </class>
- </hibernate-mapping>
web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <!-- 指定spring的配置文件,默认从web根目录寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <!-- 如果有多个文件 使用 "," 分开 -->
- <param-value>classpath:applicationContext.xml</param-value>
- </context-param>
- <!-- 对spring容器进行实例化 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!--配置Struts2的过滤器 -->
- <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>/*</url-pattern>
- </filter-mapping>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
EmployeeService.java
- package com.sh.employee.interfaces;
- import java.util.List;
- import com.sh.employee.model.Employee;
- public interface EmployeeService {
- void save(Employee employee);
- void update(Employee employee);
- Employee find(String userName);
- void delete(String... userName);
- List<Employee> list();
- }
EmployeeServiceBean.java
- package com.sh.employee.service;
- import java.util.List;
- import javax.annotation.Resource;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import com.sh.employee.interfaces.EmployeeService;
- import com.sh.employee.model.Employee;
- /**
- *@author LuoB.
- */
- //@Service: 定义业务层。采用扫描加注解 将这个类交给spring管理 。
- //-----此时 在spring容器中默认的bean的名称为 这个类的简单类名 employeeServiceBean
- //@Transactional:定义这个类采用事物管理。这样所有的方法都有事物特性了。
- //-----如果某个方法不需要事物 采用这个标识:@Transactional(propagation=Propagation.NOT_SUPPORTED)
- @Service @Transactional
- public class EmployeeServiceBean implements EmployeeService {
- //采用注解方式注入SessionFactory
- //factory.openSession(); 表示开启一个新的session,这样就不能使用spring的事物管理了
- //spring的事物管理一般是先获取当前的session,然后 将这个begin。
- //factory.getCurrentSession();【在Hibernate3.0后才提供的这样的一个方法】得到 spring事物管理创建好的session
- @Resource SessionFactory factory;
- public void delete(String... userName) {
- //中间的load 替换了 get方法 因为速度和效率 比get 高
- for (String string : userName) {
- factory.getCurrentSession().delete(factory.getCurrentSession().load(Employee.class, string));
- }
- }
- @Transactional(propagation=Propagation.NOT_SUPPORTED)
- public Employee find(String userName) {
- // TODO Auto-generated method stub
- return (Employee)factory.getCurrentSession().get(Employee.class, userName);
- }
- @SuppressWarnings("unchecked")
- public List<Employee> list() {
- //Hql 进行查询
- /*Session session=factory.openSession();
- Transaction ts= session.beginTransaction();
- ts.commit();
- ts.rollback();*/
- return factory.getCurrentSession().createQuery("from Employee").list();
- }
- public void save(Employee employee) {
- //持久化方法 -内部还是调用save方法
- factory.getCurrentSession().persist(employee);
- }
- public void update(Employee employee) {
- // merge对update更新了有 save和update的功能
- factory.getCurrentSession().merge(employee);
- }
- }
EmployeeAction.java
- package com.sh.employee.action;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Controller;
- import com.opensymphony.xwork2.ActionContext;
- import com.sh.employee.interfaces.EmployeeService;
- //@Controller 标识这个action为spring中的一个控制层,在spring中为类的简单类名
- @Controller
- public class EmployeeAction {
- @Resource EmployeeService employeeService;
- public String execute(){
- ActionContext.getContext().put("employees",employeeService.list());
- return "list";
- }
- }
EmployeeManageAction.java
- package com.sh.employee.action;
- import javax.annotation.Resource;
- import org.springframework.context.annotation.Scope;
- import org.springframework.stereotype.Controller;
- import com.opensymphony.xwork2.ActionContext;
- import com.sh.employee.interfaces.EmployeeService;
- import com.sh.employee.model.Employee;
- //因为Struts2在每次接受到请求后,会迅速的创建actionContext,ValueStack,action
- //然后把Action存在在ValueStack中 所以Action可以被OGNL访问.
- //但是把Action交给Spring管理后,action 就是单利模式了,这样 就违背了Struts2的设计理念。
- //所以 我们需要 将action 声明为 原型 @Scope("prototype")
- @Controller @Scope("prototype")
- public class EmployeeManageAction {
- @Resource EmployeeService employeeService;
- //如果 某个action 不声明为原型(比如: EmployeeAction) 千万不要在该action中 保存用户提交过来的数据
- //比如下面 如果是但单利模式 所有的请求都可以访问这个对象了
- private Employee employee;
- public Employee getEmployee() {
- return employee;
- }
- public void setEmployee(Employee employee) {
- this.employee = employee;
- }
- public String addUI(){
- return "add";
- }
- public String add(){
- employeeService.save(employee);
- ActionContext.getContext().put("msg", "保存成功!");
- return "message";
- }
- }
struts.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
- "http://struts.apache.org/dtds/struts-2.3.dtd">
- <struts>
- <!-- 设置struts的对象工厂,由spring进行创建 (更换Struts2的工厂)-->
- <!-- 实际上这个常量不配置也可以,如果项目中使用了struts2-spring-plugin-2.1.8.jar 那么可以不用配置
- 如果使用了其他的第三方plugin,建议明确配置struts2的对象工厂 -->
- <constant name="struts.objectFactory" value="spring"/>
- <package name="employee" namespace="/employee" extends="struts-default">
- <!-- 此时action开始由spring进行创建和管理,因此不用写上action的类名。
- 需要写上action在spring中的简单类名 -->
- <!-- http://localhost:8080/SSH2/employee/list.action -->
- <action name="list" class="employeeAction">
- <result name="list">/WEB-INF/page/employee.jsp</result>
- </action>
- <!-- http://localhost:8080/SSH2/employee/manage_addUI.action -->
- <action name="manage_*" class="employeeManageAction" method="{1}">
- <result name="add">/WEB-INF/page/employeeAdd.jsp</result>
- <result name="message">/WEB-INF/page/message.jsp</result>
- </action>
- </package>
- </struts>
employee.jsp
- <body>
- 采用OGNL表达式获取<br/>
- <s:iterator value="#request.employees">
- <s:property value="username"/>,<s:property value="password"/>,<s:property value="gender"/><br/>
- </s:iterator>
- <br/>采用JSTL/EL表达式获取<br/>
- <c:forEach var="emp" items="${employees}" varStatus="st">
- ${emp.username},${emp.password},${gender}<br/>
- </c:forEach>
- [url=<s:url action=]">员工添加[/url]
- </body>
employeeAdd.jsp
- <body>
- <s:form action="manage_add" namespace="/employee" method="post" theme="simple">
- 用户名:<s:textfield name="employee.username"/><br/>
- 密码:<s:textfield name="employee.password"/><br/>
- 性别:<s:radio list="#{'MAN':'男','WOMEN':'女'}" listKey="key" listValue="value" name="employee.gender"/><br/>
- <s:submit value="保存"/>
- </s:form>
- </body>
message.jsp
- <body>
- <h1><font color="red">${msg}</font></h1>
- [url=${pageContext.request.contextPath}/employee/list.action]返回员工列表[/url]
- </body>
--访问http://localhost:8080/SSH2/employee/list.action
--访问http://localhost:8080/SSH2/employee/list.action
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)