2008年的SSH入门门槛——插入一个用户要配多少东西

2008年的SSH入门门槛——插入一个用户要配多少东西

Struts 1.1 + Spring 2.0 + Hibernate 3。这是2008年Java Web开发的"标准三件套"。那时候写一个"插入用户"功能,不是今天的三行代码,是在五层配置文件里找到了正确的标签、配对了正确的依赖链。这篇文章是一个当年的SSH学习项目,逐步拆解"插入一条用户记录"到底经历了多少层。


一、背景:2008年的SSH三件套

2008年做Java Web,开口就是SSH——Struts做MVC,Spring做容器,Hibernate做ORM。不是选其中一个,是三个都要用,少一个就不叫"企业级"。

当时的入门门槛不是理解概念,是把这三个东西配通。因为它们不是一个爹生的——Struts是Apache的,Spring是SpringSource的,Hibernate是JBoss的。三个不同组织开发的框架要在一个项目里合作,全靠XML配置把它们的接触点手工接上。

一个最简单的"插入用户"功能,经历的层数是今天Spring Boot的十倍。


二、Struts 1——前端的请求入口

<!-- struts-config.xml -->
<form-beans>
    <form-bean name="userform" type="com.myssh.form.UserForm"/>
</form-beans>

<action-mappings>
    <action path="/user"
            type="com.myssh.action.UserAction"
            parameter="status">
        <forward name="success" path="/success.jsp"/>
        <forward name="fail" path="/fail.jsp"/>
    </action>
</action-mappings>

前端JSP用 <html:form action="/user.do?status=insert"> 提交表单。Struts 1的 ActionServlet 拦截 *.do,读到 path="/user",根据 parameter="status"insert 值找到 UserAction 里的 insert() 方法。

<!-- test.jsp -->
<html:form action="/user.do?status=insert">
    用户名:<html:text property="username"/>
    密码:<html:password property="password"/>
    <html:submit>提交</html:submit>
</html:form>

Struts 1 的 ActionForm 要把表单字段一个一个人肉声明:

public class UserForm extends ActionForm {
    private String username;
    private String password;
    // getter/setter... 每个字段都要写
}

今天一个 @RequestParam@ModelAttribute 的事,那时要写一个完整的ActionForm类。


三、Spring 2——IOC容器把三层串起来

<!-- applicationContext.xml -->
<!-- 数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
    <property name="username" value="YFSI"/>
    <property name="password" value="YFSI"/>
</bean>

<!-- Hibernate Session工厂 -->
<bean id="sessionFactory"
      class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list><value>com/myssh/po/User.hbm.xml</value></list>
    </property>
</bean>

<!-- DAO -->
<bean id="iuserdao" class="com.myssh.dao.impl.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<!-- Service -->
<bean id="iuserservice" class="com.myssh.service.impl.UserServiceImpl">
    <property name="iuserdao" ref="iuserdao"/>
</bean>

<!-- Action(Struts与Spring的接触点) -->
<bean name="/user" class="com.myssh.action.UserAction">
    <property name="iuserservice" ref="iuserservice"/>
</bean>

依赖注入链:UserAction → UserServiceImpl → UserDaoImpl → SessionFactory → DataSource。每个节点都是XML里一个 <bean> 标签。

注意Action的bean name是 /user——它必须和 struts-config.xml 里的 path="/user" 对得上。这是Struts和Spring之间唯一的连接点,配错了Struts找不到Action。


四、Struts与Spring的桥接——DelegatingRequestProcessor

<!-- struts-config.xml -->
<controller>
    <set-property property="processorClass"
                  value="org.springframework.web.struts.DelegatingRequestProcessor"/>
</controller>

这一行是整个SSH集成的关键。Struts 1默认用 RequestProcessor 创建Action实例。DelegatingRequestProcessor 把它劫持了——创建Action时不自己 new,而是去Spring容器里按 path 名称查找bean。

所以Action的bean name必须和struts-config里的path一致——这就是SSH时代"Struts认path、Spring认beanName"的设计约定。不对上就是一串 NullPointerException


五、Hibernate 3——对象到Oracle表的映射

<!-- User.hbm.xml -->
<hibernate-mapping>
    <class name="com.myssh.po.User" table="user1" schema="YFSI">
        <id name="id" column="id" type="integer">
            <generator class="increment"/>
        </id>
        <property name="username" column="username" type="string"/>
        <property name="password" column="password" type="string"/>
    </class>
</hibernate-mapping>

POJO只有三个字段——id、username、password。但每个字段都要在XML里显式声明类型、列名、映射关系。今天 @Entity + @Column 的事,那时候是一份独立的XML文件。


六、DAO实现——HibernateDaoSupport

public class UserDaoImpl extends HibernateDaoSupport implements IUserDao {
    public boolean insert(User user) {
        try {
            this.getHibernateTemplate().save(user);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

HibernateDaoSupport 是Spring对Hibernate的封装——通过 getHibernateTemplate() 拿到模板对象,调 save()update()delete()。这个模式的好处是:不用手动开Session、不用管事务、不用close连接。Spring帮你管了。

但代价也很明显——你要继承 HibernateDaoSupport,破坏了自己DAO的继承体系。如果你的DAO还需要继承别的基类,就没法做了。


七、完整调用链——从JSP到Oracle的五层传递

test.jsp
  │ POST /user.do?status=insert
  ▼
ActionServlet (*.do路由)
  │
  ▼
DelegatingRequestProcessor(从Spring容器取Action)
  │
  ▼
UserAction.insert()
  │ 从ActionForm取出username/password
  │ 构造User PO
  │ 调 iuserservice.insert(user)
  ▼
UserServiceImpl.insert()
  │ 调 iuserdao.insert(user)
  ▼
UserDaoImpl.insert()
  │ 调 getHibernateTemplate().save(user)
  ▼
Hibernate → INSERT INTO YFSI.user1 VALUES(1, 'admin', '123456')
  │
  ▼
返回 success.jsp 或 fail.jsp

从点击提交到执行SQL,穿过六层。每一步都靠XML配置把接口和实现串起来。今天的Spring Boot让你感觉"写一个功能只要三行代码"——不是功能真的简化了,是这六层的XML配置全被Spring Boot自动配置替代了


八、SSH时代的三座大山

当年的痛苦今天的解法
web.xml配置手动配Servlet/Taglib/ContextLoaderSpring Boot自动注册
Struts-Spring桥接DelegatingRequestProcessor配错就404Spring MVC原生集成
Hibernate映射每张表一个hbm.xmlJPA注解 + @Entity
依赖注入每个bean一个 <property>@Autowired自动装配
事务管理HibernateTransactionManager手配@Transactional一个注解

一个插入用户的Demo,配置文件的篇幅是业务代码的三倍。这不是过度设计——是这三个框架设计之初就是独立的,合在一起全靠XML粘合剂。理解了这套粘合剂,就知道后来的Spring Boot消灭了什么。


九、结语

2008年的SSH学习成本不在Java本身——在配通三套框架的接触点。Struts认path,Spring认beanName,Hibernate认mappingResource,三者之间的对应关系全靠人脑记住。这套SSH三件套统治了Java Web开发整整五年,直到2013年Spring Boot出现,一键消灭了这堆XML。

现在回头看这个只有"插入用户"的项目,代码不到100行,配置超过200行。它不是复杂——是那个年代的技术选型就是这样的。理解了它,就理解了Spring Boot为什么能一统天下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值