整合SSH(Spring+Struts+Hibernate)

发布时间:2023年12月18日

0.前言, 由于工作需要故来学习SSH的整合,structs其实相当于(把view和controller结合起来,没有像现在的前后端分离,请求会发送给Action处理,在structs.xml映射地址和类) Hibernate(就是处理数据库的,几乎自动化,也可以写sql语句)

  1. Struts:Struts 是一个基于 MVC(Model-View-Controller)设计模式的 Web
    应用程序框架。它提供了一个请求处理流程,将请求的参数进行解析,并根据配置文件中的映射规则将请求转发给相应的控制器(Action)。Struts
    还提供了一些标签库和表单验证等功能,简化了开发过程。

  2. Spring:Spring 是一个轻量级的开源框架,用于构建企业级 Java 应用程序。它提供了依赖注入(Dependency
    Injection)、面向切面编程(Aspect-Oriented Programming)等核心功能。在 SSH 框架中,Spring
    负责管理对象的生命周期、依赖关系以及事务管理等。

  3. Hibernate:Hibernate 是一个 Java ORM(Object-Relational Mapping)框架,用于将 Java
    对象与数据库表进行映射。它提供了一种面向对象的方式来操作数据库,屏蔽了底层的数据库细节。通过 Hibernate,开发人员可以使用面向对象的方式进行数据库操作,提高了开发效率。

1.直接gitee下载了项目进行研究

https://gitee.com/yjcode/Spring_Struts_Hibernate_Register/tree/master

2.项目结构
在这里插入图片描述
3.项目初期遇到循环依赖的问题,一个tomcat部署了2个有相同依赖的项目

解决方法:删除多个部署的项目变成下面的样子(或者一个也可以)

在这里插入图片描述
4.项目依赖 spring3+struts2.5+hibernate3.6

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-hibernate -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-hibernate</artifactId>
  <version>1.2.9</version>
</dependency>
<!-- 添加Hibernate依赖 -->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>3.6.10.Final</version>
</dependency>
<!-- 添加javassist -->
<dependency>
  <groupId>javassist</groupId>
  <artifactId>javassist</artifactId>
  <version>3.12.0.GA</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>3.2.9.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>3.2.9.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>3.2.9.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>3.2.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>3.2.9.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>3.2.9.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>3.2.9.RELEASE</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>3.2.9.RELEASE</version>
  <scope>compile</scope>
</dependency>
<!--struts依赖-->
<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-core</artifactId>
  <version>2.5.14.1</version>
</dependency>
<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-spring-plugin</artifactId>
  <version>2.5.20</version>
</dependency>

<!--数据库 mysql 驱动-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.0.7</version>
</dependency>
<!--切面依赖-->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.7.4</version>
</dependency>
<dependency>
  <groupId> org.aspectj</groupId >
  <artifactId> aspectjweaver</artifactId >
  <version> 1.6.11</version >
</dependency>

5.怎么使用

1.写structs配置文件,后期可以使用注解优化

 //class对应的是bean的名字/类的全限定名称com.jamsee.XXClassName

//result对应的是函数返回String的标志 或者数据
//name对应可以访问 http://localhost:8090/listProduct 或者listProduct.action
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
//测试成功

在这里插入图片描述

2.怎么在页面使用EL表达式,并且循环遍历

${products[1].id}
<s:iterator value="products" var="p">
    <tr>
        <td>${p.id}</td>
        <td>${p.name}</td>
        <td>${p.price}</td>
        <td><a href="editProduct?product.id=${p.id}">edit</a></td>
        <td><a href="deleteProduct?product.id=${p.id}">delete</a></td>
    </tr>
</s:iterator>

//会调用action的方法,完成成员的变化,思路确实比较清晰,可是我要的数据如果是一次性的呢?不放在成员里面呢? 可以每次删除设置为空
在这里插入图片描述

3.怎么国际化(一直困扰我的问题,怎么已经从中文切换到英文,其实应该是前端做的,但是后端来做该怎么做)
//遇到的坑,直接创建国际化文本文件,一系列操作还是乱码,我直接写个类插入到成员变量里面,页面直接可以使用,后期可以改造成为自动注入解决乱码问题

在这里插入图片描述

在这里插入图片描述

public class ProductAction3 extends ActionSupport {
    ResourceBundle rb;
    @Override
    public String execute() throws Exception {
        Locale defaultLocale = Locale.getDefault();
        System.out.println("default country:" + defaultLocale.getCountry());
        System.out.println("default language:" + defaultLocale.getLanguage());
        //自定义本地化信息
        Locale currentLocale = new Locale("zh", "CN");
        // 定位到国际化文件,国际化资源文件名由basename+Locale组成:如MessagesBundle_zh_CN.properties,basename为任意合法名字
        ResourceBundle rb = ResourceBundle.getBundle("messages",currentLocale, new UTF8Control());
        //读取文件中的值
         System.out.println(rb.getString("k1"));
         System.out.println(rb.getString("k2"));
        this.setRb(rb);
        return SUCCESS;
    }

    public ResourceBundle getRb() {
        return rb;
    }

    public void setRb(ResourceBundle rb) {
        this.rb = rb;
    }
}

//工具类

/**
 * @author jams
 * @Type UTF8Control.java
 * @Desc
 * @date 2023/12/18 17:12
 */
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class UTF8Control extends ResourceBundle.Control {

    @Override
    public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException {
        String bundleName = toBundleName(baseName, locale);
        String resourceName = toResourceName(bundleName, "properties");
        InputStream stream = null;
        if (reload) {
            URL url = loader.getResource(resourceName);
            if (url != null) {
                URLConnection connection = url.openConnection();
                if (connection != null) {
                    // 使用 UTF-8 编码读取资源文件
                    connection.setUseCaches(false);
                    stream = connection.getInputStream();
                }
            }
        } else {
            // 使用 UTF-8 编码读取资源文件
            stream = loader.getResourceAsStream(resourceName);
        }
        if (stream != null) {
            try (Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
                return new PropertyResourceBundle(reader);
            }
        }
        return super.newBundle(baseName, locale, format, loader, reload);
    }
}

/**
 * Revision history
 * -------------------------------------------------------------------------
 * <p>
 * Date Author Note
 * -------------------------------------------------------------------------
 * 2023/12/18 用户名 create
 */ 

//list.jsp写
<s:property value=“rb.getString(‘k1’)” /> // 得到国际化的文本,后端工具传过来的请求
//问题: 后端怎么知道是哪个国家? 答案: 请求的全部数据放ctx中,传请求过来可以拿到,代码如下
//前端
href=“product.action?locale=en_US”
href=“product.action?locale=zh_CN”

@Override
public String execute() throws Exception {
    ActionContext ctx = ActionContext.getContext();
    
    // 获取前端传递的区域信息
    String localeString = ctx.getParameters().get("locale").getValue();
    
    // 解析区域信息,设置 Locale 对象
    String[] localeParts = localeString.split("_");
    Locale currentLocale = new Locale(localeParts[0], localeParts[1]);
    
    // 定位到国际化文件,国际化资源文件名由basename+Locale组成:如MessagesBundle_zh_CN.properties,basename为任意合法名字
    ResourceBundle rb = ResourceBundle.getBundle("messages", currentLocale, new UTF8Control());
    
    // 读取文件中的值
    String k1 = rb.getString("k1");
    String k2 = rb.getString("k2");
    
    this.setRb(rb);
    
    return SUCCESS;
}
    

4.hibernate怎么使用?
//写配置文件的表和字段名和类型,不存在表会自动创建,其实高版本可以使用@Table来指定的,更方便

	<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="pojo">
    <class name="Product" table="product_h">
        <id name="id" column="id">
            <generator class="native">
            </generator>
        </id>
        <!--version元素必须紧挨着id后面  -->
      <!--  <version name="version" column="ver" type="int"></version>-->
        <property name="name"/>
        <property name="price" column="price"/>
        <!--<many-to-one name="category" class="Category" column="cid" />
        <set name="users" table="user_product" lazy="false">
            <key column="pid" />
            <many-to-many column="uid" class="User" />
        </set>-->
    </class>

</hibernate-mapping>

//继承一下HibernateTemplate,增删改查方法如下

  @Component("productDAOImpl")
public class ProductDAOImpl extends HibernateTemplate implements ProductDAO2{
    @Autowired
    private SessionFactory sf;
    public List<Product> list() {
        return find("from Product");  //sql语句在这里写真香!!! 不过会sql注入攻击
    }

    @Override
    public void add(Product p) {
        save(p);
    }

    @Override
    public Product getP(Class<Product> productClass, int id) {
        return (Product)get(productClass,id);
    }

    @Override
    public void deleteP(Product p) {
        delete(p);
    }

    @Override
    public void updateP(Product p) {
        update(p);
    }


}

//使用自己的sql进行查询(下面事务可以不写,因为我们在spring开启了)

@Autowired
private SessionFactory sessionFactory;

public List<Product> customQuery() {
    //相当于预编译语句
    String sql = "SELECT * FROM products WHERE price > :price";
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = null;
    List<Product> products = null;

    try {
        tx = session.beginTransaction();
        //这里开始看
        SQLQuery query = session.createSQLQuery(sql);
        query.addEntity(Product.class);
        query.setParameter("price", 100);
        products = query.list();
        tx.commit();
    } catch (Exception e) {
        if (tx != null) {
            tx.rollback();
        }
        e.printStackTrace();
    } finally {
        session.close();
    }

    return products;
}
文章来源:https://blog.csdn.net/weixin_47039303/article/details/135048849
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。