0.前言, 由于工作需要故来学习SSH的整合,structs其实相当于(把view和controller结合起来,没有像现在的前后端分离,请求会发送给Action处理,在structs.xml映射地址和类) Hibernate(就是处理数据库的,几乎自动化,也可以写sql语句)
Struts:Struts 是一个基于 MVC(Model-View-Controller)设计模式的 Web
应用程序框架。它提供了一个请求处理流程,将请求的参数进行解析,并根据配置文件中的映射规则将请求转发给相应的控制器(Action)。Struts
还提供了一些标签库和表单验证等功能,简化了开发过程。Spring:Spring 是一个轻量级的开源框架,用于构建企业级 Java 应用程序。它提供了依赖注入(Dependency
Injection)、面向切面编程(Aspect-Oriented Programming)等核心功能。在 SSH 框架中,Spring
负责管理对象的生命周期、依赖关系以及事务管理等。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;
}