整合SSH(Spring+Struts+Hibernate)

news2024/11/24 5:24:07

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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1320108.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】计算一年内的总天数(还有跨年日期)

花了一段时间才找到Python中求一年中总日数&#xff08;total day of the Year&#xff09;的格式代码&#xff0c;所以也把计算方法记录下来。 基本 首先&#xff0c;简单地找出一年中的总天数&#xff0c; strftime() 和 strptime() 的格式代码是 %j ↓看这里 使用 strft…

算法基础之Prim算法求最小生成树

Prim算法求最小生成树 核心思想&#xff1a;Prim 算法 类似于dijkstra算法 更新距离时改为到**集合(生成树)**的距离 最小生成树长这样 每次迭代放一个最近(有边)点&#xff0c;一条最短边进生成树 #include <cstring>#include <iostream>#include <algori…

08-Event Sources和Sink架构

1 PingSource -> Kubernetes Service Sink 架构模型 示例1 部署一个kubernetes类型的sink&#xff0c;这里面还是以event-display为例&#xff0c;下面是资源清单 --- apiVersion: apps/v1 kind: Deployment metadata:name: event-display spec:replicas: 1selector:matc…

Axie Infinity 之后,Ronin 的潜力何在?

作者&#xff1a;stellafootprint.network 数据来源&#xff1a;Ronin Dashboard 备受欢迎的 Web3 游戏 Pixels 在 2023 年 10 月下旬从 Polygon 迁移到了专为游戏设计的区块链 Ronin。Pixels 此前作为 Polygon 上活跃用户&#xff08;钱包数量&#xff09;最多的 Web3 游戏&…

【重点】【DFS】【子集】78.子集

题目 法1&#xff1a;DFS 必须掌握的方法&#xff01;&#xff01;&#xff01; 我们也可以用递归来实现子集枚举。 假设我们需要找到一个长度为 nnn 的序列 aaa 的所有子序列&#xff0c;代码框架是这样的&#xff1a; void dfs(int cur, int n, LinkedList<Integer>…

HTML5+CSS3小实例:3D发光切换按钮效果

目录 一、运行效果 图片效果 二、项目概述 三、开发环境 四、实现步骤及代码 1.创建空文件夹 2.完成页面内容 3.完成css样式 五、项目总结 六、源码获取 一、运行效果 图片效果 二、项目概述 该项目是一个基于HTML和CSS的动态小猫动画。通过使用CSS样式和动画效果…

开源支付项目,还有强大的聚合支付项目,值得借鉴学习,收藏备用

开源支付项目,还有强大的聚合支付项目,值得借鉴学习,收藏备用 自学编程之道2023-03-18 14:26 移动支付随处可见,以前都是微信、支付宝分别各一个收款码,二维码多了之后就不好管理了,随着支付方式的增多,现在基本上都用聚合支付,多种支付方式,一码搞定。针对支付及聚…

Linux常用网络指令

网络参数设定使用的指令 手动/自动设定与启动/关闭 IP 参数&#xff1a;ifconfig, ifup, ifdown ifconfig ifconfig常用于修改网络配置以及查看网络参数的指令 [rootwww ~]# ifconfig {interface} {up|down} < 观察与启动接口 [rootwww ~]# ifconfig interface {options…

项目管理:产品经理如何保障项目按时完成

一个项目的成功要考虑多方因素&#xff0c;即使经过了精细的策划&#xff0c;但是在项目推进过程中也会遇到各种问题。 产品经理的任务就不仅仅在于完成产品策划&#xff0c;还需要承担项目管理工作&#xff0c;跟进项目进度&#xff0c;必要时还得出面协调、解决冲突&#x…

猜数字小游戏(猜错了会关机推荐让室友帮你玩)

前言 今天来带大家写一个简易的猜数字小游戏&#xff0c;如果连着猜错n次&#xff08;自己设定&#xff09;就会导致电脑关机&#xff0c;还在等什么呢&#xff1f;赶紧学会咯&#xff0c;发给你的室友让他帮你玩吧&#xff01; 正文 随机数的生成 首先我们还要学会如何创建随…

Windows10 如何开机自动启动redis

前言 当我们在Windows 10上使用Redis时&#xff0c;通常希望能够使Redis服务在系统启动时自动启动&#xff0c;以便我们无需手动介入就能够方便地访问和管理数据。在这个过程中&#xff0c;我们将通过下载、安装和配置Redis为Windows服务的方式&#xff0c;使其成为系统的一部分…

python与机器学习4,激活函数

目录 1 激活函数1: 单位阶跃函数 1.1 函数形式 1.2 函数图形 1.3 函数特点 1.4 代码实现这个 单位阶跃函数 2 激活函数2 sigmoid函数 2.1 函数形式 2.2 函数图形 2.3 函数特点 2.3.1 是一个连续函数&#xff0c;且是一个渐变的曲线 2.3.2 是连续区间的[0,1] , 可以…

JVM基础扫盲

什么是JVM JVM是Java设计者用于屏蔽多平台差异&#xff0c;基于操作系统之上的一个"小型虚拟机"&#xff0c;正是因为JVM的存在&#xff0c;使得Java应用程序运行时不需要关注底层操作系统的差异。使得Java程序编译只需编译一次&#xff0c;在任何操作系统都可以以相…

定制 Electron 窗口标题栏

Electron 是一款流行的桌面应用开发框架&#xff0c;基于 Web 技术构建&#xff0c;提供了强大的跨平台能力。在开发过程中&#xff0c;经常需要定制窗口标题栏以创造独特的用户体验。 1. 完全隐藏默认标题栏 有时候&#xff0c;我们希望创建一个自定义的标题栏&#xff0c;完…

光伏收益计算工具:实现可持续能源投资的决策支持

随着全球能源结构的转型&#xff0c;光伏发电作为主要的可再生能源之一&#xff0c;其投资前景日益光明。然而&#xff0c;光伏发电项目的投资决策需要基于准确的收益预测。因此&#xff0c;光伏收益计算工具应运而生&#xff0c;为投资者提供决策支持。 光伏收益计算工具是一种…

护肤品品牌怎么创建百度百科词条?

护肤品品牌创建百度百科词条&#xff0c;需要遵循一定的步骤和原则&#xff0c;同时保证内容的真实性和权威性。以下是伯乐网络传媒给大家分享的详细创建流程和注意事项&#xff1a; 一、准备工作 收集资料&#xff1a;首先&#xff0c;需要收集品牌的详细资料&#xff0c;包括…

【Matlab】如何可视化多项式函数(附完整MATLAB代码)

可视化多项式函数 前言多项式函数MATLAB 对理解多项式函数的帮助 正文思考步骤 代码实现及图像显示对于一元多项式函数对于多元多项式函数 前言 多项式函数 多项式函数是数学中常见的一类函数&#xff0c;它的一般形式可以表示为&#xff1a; [ f ( x ) a n x n a n − 1 x…

基于Python Django的内容管理系统Wagtail CMS部署与公网访问

文章目录 前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 前言 Wagtail是一个用Python编写的开源CMS&#xff0c;建立在Django Web框架上。Wagtail 是一个基于 Django 的开源内容管理系统&#xf…

X86汇编语言:从实模式到保护模式(代码+注释)--c10、11(保护模式:32位x86处理器编程架构+进入保护模式)

保护模式&#xff1a;32位x86处理器编程架构 IA-32架构的基本执行环境 寄存器扩展 通用寄存器&#xff08;32&#xff09;&#xff1a;EAX EBX ECX EDX ESI EDI EBP ESP 指令寄存器&#xff08;32&#xff09;&#xff1a;EIP 标志寄存器&#xff08;32&#xff09;&#xff…

PFA试剂瓶本底低PFA取样瓶可采集、储存电子级酸

PFA取样瓶是一种可靠、耐用的用于采集、储存、运输和分析食品、医药、环境和化工等领域样品的容器。相对于传统的取样瓶材料如玻璃或塑料&#xff0c;PFA取样瓶拥有多种优点&#xff0c;使其成为当前许多行业的首选。 首先&#xff0c;PFA取样瓶的材质是聚四氟乙烯共聚物&#…