Spring整合Struts2 wel.xml中写spring核心配置文件路径问题,顺便总结下我学习SSH整合的过程

作者分享了学习Spring、Hibernate和Struts2框架的整合经验,包括配置SessionFactory、整合Spring进行声明式事务管理以及如何使用AOP思想简化代码。同时也遇到了启动服务器时找不到Spring配置文件的BUG以及Struts2命名空间相关的错误,并尝试了不同的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     这两天我学习了Spring整合Hibernate和Struts2的知识,在这篇博客中分享一下我的学习心得和遇到的问题(第一次写博客~(>_<)~ ,不好的地方请见谅!我还只是个小白~)

其中Hibernate的整合很成功,步骤:

1、导入资源文件db.properties(里面是连接数据库的信息,如图:)


2、配置C3P0数据源(Hibernate底层与数据库连接就是基于的C3P0连接池实现的)


3、配置SessionFactory:

在配置这个工厂bean的时候需要写三个参数:①数据源;②hibernate核心配置文件hibernate.cfg.xml的路径;③实体类的hbm映射文件路径(这个特别方便,今后可以不需在hibernate.cfg.xml中声明了,而且可以用*通配符,一键导入)

Spring整合了SessionFactory还有个很大的作用,那就是今后不用再像学hibernate时那样写HibernateUtil类了,全部交给Spring帮我们在dao实现层来生成SessionFactory然后获得session了。


4、配置Spring的声明式事务:有三个步骤:

①配置hibernate的事务管理器:这个有什么用呢?跟SessionFactory一样,我们不需要像学hibernate的时候那样在dao实现层通过session.beginTransaction()来开启事务了,交给Spring来帮我们开启hibernate对数据库操作的事务

②配置Spring的事务属性:Spring事务属性包括:事务隔离级别、回滚事务、只读事务、过期事务,还有Spring的事务传播行为也在这里配置,Spring的事务属性和事务传播行为我觉得还是比较重要,需要大家去实实在在学一学

③配置事务切入点并关联事务属性:这里用到了Spring最强大的两大功能之一,AOP[面向切面编程](另一个功能是Spring通过IOC[依赖注入]使我们程序之间得到解耦而且便于管理程序,具体IOC是什么,请大家参考我转载的这一篇博客(讲的超级鸡巴好):http://blog.youkuaiyun.com/qq_28202597/article/details/49532025)

那么,它的作用是什么呢?从我现在学习的知识水平来讲一下我的理解:咱们dao实现层中的每一个方法都是对数据库的一个CRUD操作,而在这些操作前我们是不是应该开启事务,然后在这些操作完后还要关闭事务,咱们对数据库的一次读取或操作才算完整。那么AOP的作用就是帮我们把这些操作的一前一后给“切了”,然后再在前后加入你想要加入的东西----数据库事务的开启与关闭,当然后还可以加入其他的功能。其实,我上面说的对dao层进行切割是不准确的,我们真正的实际开发中,还会有个service层,这层才是我们项目中每一个业务逻辑的方法所在,我们真正要切的才是这一层,然后在一前一后插入我们想要的业务逻辑功能。

然后将dao实现层、service实现层的各个类注入到Spring的IOC容器中,让他来帮我们管理。Spring是怎么做到的呢?可以看上面我发的那个博客链接,真的讲得很好,Spring的IOC容器就是通过的里面所说的IOC(依赖注入)后来叫做DI(控制反转)来实现的。至于注入方法,可以通过Spring的配置文件中配置bean,也可以通过注解的方法,这个不说了。然后写个单元测试类看看是否成功。

到这里,我们Spring整合Hibernate就基本算完成了,整合完后给我们带来了哪些好处呢?我明显感觉到以前我在用Hibernate写dao实现层的代码和现在整合后的对比,就能看出简化了不少,从session工厂得到session、开启事务、关闭事务等等重复繁琐的代码都没有了,全交给Spring来为我们完成,可读性提高了。这一切的实现,还得来源AOP的强大,说起AOP,让我想起我们J2EE方向的两个同学,他们学习能力都能强,比我们学的东西多多了,在我还不知道什么是AOP的时候他们已经学完了Spring。当王玺学完AOP后,高调的对所有人说:妈蛋!AOP简直就是为我而生的!太尼玛强大了!当杨开睿学完AOP后,每遇见一个同学,就问他你知道什么是AOP吗?不知道啊?来来,让我拿张纸出来给你讲讲什么是AOP。当时感觉他们两个人对AOP疯狂的着了魔,我就对这门技术充满了期待。。。= =!感觉扯远了,言归正传。说到AOP,这是一种面对切面编程的思想,它底层的实现是依靠JAVA强大的动态代理,说起动态代理,那就要回到几个月前的暑假苦逼的我从学习威哥JAVASE开始讲起,那时的我,哎,大二结束了什么编程知识都没学到,都怪撸啊撸毁我一年啊。想想马上大三醒悟过来开始下定决定好好学习JAVA,暑假的两个月我没回家待在学校每天早8晚9的刻苦跟着威哥视频学习JAVA。。。。。。。。尼玛又扯远了~~~~管他的,反正写完也没多少人看,就当我自言自语吧  = =!反正那个时候学到动态代理一看什么handler啊,匿名内部类啊把我头都整晕了,后来我就多花时间去搞这个动态代理,反正我学得很慢,那两个月每天学习的时间那是相当多的,暑假一完我才学完视频里的JAVASE和一半的JAVAWeb,但是现在回过头想想,没有那辛苦的两个月入门,现在又怎么会在J2EE这条道路上走下去呢。。。。继续哈,后来学了动态代理,现在理解起来AOP就让我轻松了许多。事实证明啊,我们在学习的道路上,是不容易一帆风顺的,前方总会有坎坷与山峰,别走得太快,停下来解决完困难后再前行,不能为了追求速度,而忽略了学习的本质,那就是理解。说到这里我要感谢我的隔壁室友杨开睿,他是一个很有天赋的人也很努力的人,我从他身上看到做我们这一行的,我们要学习的是技术,而不是使用技术的方法,所以他对底层非常熟悉,我相信他也是花了很多时间和精力去各种查资料的。对了,http://edu.51cto.com/lesson/id-37009.html 这是我学习尚硅谷的Spring的视频连接。哦还有,我个人觉得我们每学习一种有视频教学的技术后,用上一段时间后,然后再回到书本上去吸收它的根本会达到事半功倍的效果。如果学习一种技术,一开始就抱着书来看的话,不管你困不困,反正我是要看睡着的。

好了,现在该是Spring整合Struts2了。首先,

1、对了我刚刚写加入的jar包的步骤,加入Hibernate和Spring的jar包,现在加入Struts2的jar包

2、在web.xml中加入Struts2的核心过滤器


3、在web.xml中加入Spring的监听器配置和Spring核心配置文件所在路径。


这里的 * 是因为我是用配置文件的方式用来注入dao、service、action的类,我写在另一个Spring的配置文件中的,让服务器启动的时候去加载所有的applicationContext*文件

好了,说到这里,我是这一篇经验分享的帖,也是一篇求助帖。我遇到一个超级奇葩的BUG,当我启动服务器的时候,总会报一个找不到【Spring/applicationContext.xml】的错误,我根本就没有Spring这个文件包啊,我也查了一些资料说其实这里的<context-param>可以不写,那么tomcat启动的时候就会在默认的WEB-INF下去找,那我也试了试把applicationContext.xml放在了WEB-INF下,然后参数配置代码删了或者直接写成/WEB-INF/allicationConext.xml都还是会报找不到【Spring/applicationContext.xml】的错误
。在启动了十几次后无论怎么改,都是报这个错误。后来我找了我们班最6的两个人还是没找出来,就这个问题困扰了我一天,第二天去实验室找了我们老师还是没发现原因,他让我把工程打包发他邮箱回去试试。中午回到寝室我就在怀疑是不是我用的IDE的问题,毕竟我用的破解版Myeclipse,然后我就抱着试一试的心态把工程放到Eclipse上跑一下,,成功了,在Eclipse居然就没报错。然后我同时开启Myeclipse运行,也成功了!!!!这个问题奇不奇葩?后来我把Eclipse和Myeclipse都关了,重新只开Myeclipse。结果。。。。没报错!就这样神奇的BUG的不在了~~看看有木有人跟我出现过一样的BUG

第二个奇葩错误,既然服务器没报错了,我就测试了一下Struts2。结果一直报我的namespace=“/” 有错,我把命名空间删了或者改名字都报同样的错,仔细一看,下面还有一个不能实例化employeeDao的错误,难道我dao、service、action没有注入到IOC容器中吗,我又换了注解的方式来注入结果就成功了。我纳闷就又换回xml注入,这次把两个xml写在一起,结果还是报错。目前为止我就只有用注解的方式来注入,这是为神魔啊为神魔?我就想知道是我错了还是又是BUG,那我错又是错在哪里?虽然现在用注解来注入是主流,但这个问题终究他是个问题啊~~看有木有人帮我分析分析哪里出错了。


=====以上是我一些整合SSH的学习经验分享和问题求助希望大家指正,虽然我知道我的这个处女博客是没人看的ㄟ(▔︵▔ㄟ)=====


<think>好的,用户现在需要一个zynq_qspi.c的代码放在OpenOCD的flash/nor目录下,但不太清楚依据是什么。我需要仔细分析用户的需求和之前的对话历史,给出合适的回答。 首先,回顾之前的对话,用户在使用Zynq Z7 Lite开发板时遇到了通过DDR3配置FSBL的麻烦,想通过OpenOCD绕过DDR3直接烧录到Flash。之前的回答详细介绍了这种方法的优势、技术实现要点等,现在用户进入具体实施阶段,需要编具体的驱动代码。 用户的问题是关于编zynq_qspi.c的依据,也就是需要哪些参考资料和规范。我应该从以下几个方面来考虑: 1. **硬件文档**:必须参考Zynq-7000的技术参考手册,特别是QSPI控制器的部分,包括寄存器地址、操作模式、时钟配置等。例如,用户需要知道如何初始化QSPI控制器,如何发送命令,读数据等。 2. **OpenOCD的Flash驱动框架**:OpenOCD有自己的架构,编NOR Flash驱动需要遵循其接口规范。用户需要了解struct flash_driver的结构,以及需要实现的函数如probe、erase、write等。 3. **SPI NOR Flash芯片手册**:具体的Flash芯片型号(如Winbond W25Q128)的指令集、时序要求、状态寄存器等。例如,页编程指令0x02,读取指令0x0B等,以及擦除块的大小和超时时间。 4. **Xilinx的启动流程要求**:FSBL的镜像需要包含Boot Header,用户需要确保生成的镜像符合Zynq的启动规范,否则无法正确启动。 5. **现有代码参考**:OpenOCD中已有的QSPI驱动或其他Zynq相关的驱动,例如zynqmp_qspi.c,可以参考其实现方式,结构,函数调用等,帮助用户理解如何编代码。 接下来需要将这些点组织成结构清晰的回答,分为几个主要部分,比如硬件文档、OpenOCD框架、Flash芯片手册、启动规范等,每个部分详细说明依据和注意事项。 同时,用户可能需要具体的示例或步骤,比如如何在代码中定义QSPI寄存器基地址,如何实现probe函数,如何处理擦除和入操作,以及如何生成符合要求的镜像。此外,还需要提醒用户注意时序配置、状态轮询、错误处理等常见问题,避免潜在的错误。 最后,可能需要给出一个简单的代码结构示例,帮助用户更直观地理解如何开始编zynq_qspi.c,以及推荐相关工具和调试方法,比如使用JTAG调试器,结合OpenOCD的log信息进行调试。 总结来说,回答需要涵盖用户编驱动所需的所有技术依据,从硬件到软件,从规范到具体实现,结构清晰,逐步说明,确保用户能够根据这些依据正确编代码。</think>以下是编`zynq_qspi.c`代码的技术依据与实现指南,按优先级分步解析: --- ### **一、核心依据来源** #### 1. **硬件文档** - **Zynq-7000 TRM(技术参考手册)** 重点关注 *Chapter 22: Quad-SPI Controller*,需实现以下关键功能: - **寄存器基地址**:`0xE000D000`(QSPI控制器寄存器起始地址) - **操作模式**: - 直接访问模式(Direct Mode)用于Flash配置 - 间接访问模式(Indirect Mode)用于数据传输 - **时钟配置**: $$ f_{\text{SPI}} = \frac{f_{\text{CPU}}}{2^{(CLK\_DIV+1)}} $$ 需在`ConfigReg`中设置`CLK_DIV`字段(例如0x04表示分频系数32) #### 2. **SPI NOR Flash芯片手册** - **以Winbond W25Q128为例**: - **指令集**: | 指令名 | 操作码 | 功能 | |-------------|--------|--------------------------| | Write Enable| 0x06 | 使能擦除/编程操作 | | Page Program| 0x02 | 按页入(256字节/页) | | Sector Erase| 0x20 | 擦除4KB扇区 | | Read Data | 0x0B | 快速读取(支持QSPI模式) | - **状态寄存器**: ```c #define W25Q_STATUS_BUSY (1 << 0) // 位0为忙状态位 ``` #### 3. **OpenOCD框架规范** - **NOR Flash驱动接口** 需实现`struct flash_driver`定义的以下函数: ```c struct flash_driver zynq_qspi_flash = { .name = "zynq_qspi", .commands = zynq_qspi_command_handlers, .flash_bank_command = zynq_qspi_flash_bank_command, .erase = zynq_qspi_erase, .write = zynq_qspi_write, .read = zynq_qspi_read, .probe = zynq_qspi_probe, .auto_probe = zynq_qspi_auto_probe, .erase_check = default_flash_blank_check, }; ``` --- ### **二、代码实现关键步骤** #### 1. **QSPI控制器初始化** ```c // 设置QSPI为间接模式并配置时钟 static int zynq_qspi_init(struct flash_bank *bank) { uint32_t ctrl_reg = read_reg(QSPI_CR_OFFSET); ctrl_reg |= CR_ENABLE | CR_MASTER_MODE; // 使能控制器和主机模式 ctrl_reg &= ~CR_CLK_POL; // 时钟极性低电平有效 ctrl_reg |= (0x04 << CR_CLK_DIV_SHIFT); // 设置分频系数 write_reg(QSPI_CR_OFFSET, ctrl_reg); // ... 其他配置(如FIFO阈值) } ``` #### 2. **Flash探测(Probe)** ```c static int zynq_qspi_probe(struct flash_bank *bank) { // 发送JEDEC ID指令(0x9F)并读取响应 zynq_qspi_write_cmd(0x9F); uint8_t manuf_id = zynq_qspi_read_data(); uint16_t device_id = (zynq_qspi_read_data() << 8) | zynq_qspi_read_data(); // 匹配Flash型号 if (manuf_id == 0xEF && device_id == 0x4018) { bank->size = 16 * 1024 * 1024; // W25Q128容量16MB bank->sectors = malloc(4096 * sizeof(struct flash_sector)); for (int i = 0; i < 4096; i++) { bank->sectors[i].size = 4 * 1024; // 4KB扇区 } } } ``` #### 3. **擦除与入逻辑** ```c // 扇区擦除实现 static int zynq_qspi_erase(struct flash_bank *bank, int first, int last) { for (int sector = first; sector <= last; sector++) { uint32_t addr = sector * 4096; zynq_qspi_write_enable(); // 发送0x06 zynq_qspi_write_cmd(0x20); // Sector Erase指令 zynq_qspi_write_addr(addr); wait_busy(); // 轮询状态寄存器直到完成 } } // 数据入(按页编程) static int zynq_qspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { while (count > 0) { zynq_qspi_write_enable(); zynq_qspi_write_cmd(0x02); // Page Program指令 zynq_qspi_write_addr(offset); for (int i = 0; i < 256; i++) { // 每页256字节 zynq_qspi_write_data(buffer[i]); } offset += 256; buffer += 256; count -= 256; wait_busy(); } } ``` --- ### **三、验证与调试要点** #### 1. **寄存器级调试** - 通过OpenOCD `mdw`命令直接查看QSPI寄存器: ``` OpenOCD> mdw 0xE000D000 10 // 查看QSPI控制器前16个寄存器 ``` #### 2. **时序验证** - 使用逻辑分析仪捕获SCK信号,验证时钟频率是否符合: $$ t_{\text{SCK}} = \frac{1}{f_{\text{SPI}}} \geq 20ns \quad (\text{对于W25Q128}) $$ #### 3. **镜像格式验证** - 使用BootGen生成带Boot Header的镜像: ```bash bootgen -image boot.bif -arch zynq -o BOOT.BIN ``` - `boot.bif`示例内容: ``` the_ROM_image: { [bootloader] fsbl.elf system.bit u-boot.elf } ``` --- ### **四、常见问题与解决** 1. **Flash未响应** - 检查硬件连接:确认CS信号是否正确拉低 - 验证电压电平:QSPI接口电压需与Flash芯片匹配(通常1.8V或3.3V) 2. **入失败** - 确保发送`Write Enable`指令(0x06)后状态寄存器`WEL`位被置1 - 检查是否超出Flash物理地址范围(例如W25Q128最大地址为0xFFFFFF) 3. **性能优化** - 启用QSPI四线模式(需修改CR寄存器中的`FRAMESIZE`字段) - 使用DMA传输(需配置QSPI DMA控制寄存器`0xE000D028`) --- 通过以上依据和代码框架,您可系统化实现`zynq_qspi.c`驱动。建议参考Xilinx官方UG585文档第22章和OpenOCD源码中的`drivers/flash/nor/stm32f1x.c`作为实现模板。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值