maven快速入门第十三讲——使用maven整合SSH
发布日期:2021-06-30 17:54:54 浏览次数:2 分类:技术文章

本文共 20035 字,大约阅读时间需要 66 分钟。

前言

在本讲中,我会使用maven来整合Hibernate-5.0.7.Final、Struts-2.3.24和Spring-4.2.4.RELEASE这三个框架,实现从数据库中查询所有客户的需求。

在正式编写代码实现这个需求之前,我们得做一些准备工作,提前创建一个数据库(例如s2sh_crm),并在该数据库下新建一张客户表,这里笔者使用的数据库是MySQL。

create database s2sh_crm;use s2sh_crm;CREATE TABLE `cst_customer` (	`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',	`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',	`cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',	`cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',	`cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',	`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',	`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',	PRIMARY KEY (`cust_id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

经过前面几讲的学习:

想必你已经可以创建出一个如下结构的聚合工程了。

在这里插入图片描述
在使用maven整合SSH时,需要依赖struts-2.3.24、spring-framework-4.2.4.RELEASE以及hibernate-5.0.7.Final等,于是我们会在父工程的pom.xml文件中添加如下依赖,其实在实际企业开发中会有架构师专门来编写pom.xml文件。

4.0.0
com.meimeixia
crm-parent
0.0.1-SNAPSHOT
pom
crm-dao
crm-service
crm-web
4.2.4.RELEASE
2.3.24
5.0.7.Final
org.apache.struts
struts2-core
${struts.verison}
javassist
javassist
org.hibernate
hibernate-core
${hibernate.version}
org.springframework
spring-context
4.2.2.RELEASE
org.apache.struts
struts2-spring-plugin
${struts.verison}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-context-support
${spring.version}
org.springframework
spring-aop
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-orm
${spring.version}
org.springframework
spring-web
${spring.version}
org.aspectj
aspectjweaver
1.8.7
org.slf4j
slf4j-api
1.7.12
org.slf4j
slf4j-log4j12
1.7.12
mysql
mysql-connector-java
5.1.48
runtime
com.mchange
c3p0
0.9.5.5
jstl
jstl
1.2
javax.servlet
servlet-api
2.5
provided
junit
junit
4.9
test
org.apache.maven.plugins
maven-compiler-plugin
3.5.1
1.8
1.8
utf-8
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
8080
/crm
utf-8

从中可以看出父工程的pom.xml文件中抽取了一些重复的配置,比如:锁定jar包的版本、设置编译版本等,也可以看出子工程中要用到的依赖都在父工程的pom.xml文件中先定义好了,将来子工程在开发的时候就不需要再引坐标了。

温馨提示:此处并没有添加junit的依赖,只是锁定了junit的版本为4.9,各个子工程开发完毕之后,在编写JUnit单元测试用例时,还需要在其pom.xml文件中添加junit的依赖。

crm-dao子模块的开发与测试

创建Customer实体类和其相对应的映射配置文件

首先,在src/main/java目录下新建一个com.meimeixia.crm.domain包,并在该包下创建一个Customer实体类。

package com.meimeixia.crm.domain;import java.io.Serializable;/** * PO(Persistence Object):持久化类 * 持久化类有如下7个规范: * 1. 公有类 * 2. 公有无参构造 * 3. 私有属性 * 4. 公有的getter与setter * 5. 实现java.io.Serializable接口 * 6. 不能用final修饰 * 7. 如果是基础类型,要使用它的包装类  *  * @author liayun * */public class Customer implements Serializable {
private static final long serialVersionUID = 1L;//加上也行,不加也行 private Long custId; private String custName; private String custSource; private String custIndustry; private String custLevel; private String custPhone; private String custMobile; public Long getCustId() {
return custId; } public void setCustId(Long custId) {
this.custId = custId; } public String getCustName() {
return custName; } public void setCustName(String custName) {
this.custName = custName; } public String getCustSource() {
return custSource; } public void setCustSource(String custSource) {
this.custSource = custSource; } public String getCustIndustry() {
return custIndustry; } public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry; } public String getCustLevel() {
return custLevel; } public void setCustLevel(String custLevel) {
this.custLevel = custLevel; } public String getCustPhone() {
return custPhone; } public void setCustPhone(String custPhone) {
this.custPhone = custPhone; } public String getCustMobile() {
return custMobile; } public void setCustMobile(String custMobile) {
this.custMobile = custMobile; } }

然后,我们就要创建一个与以上实体类相对应的映射配置文件了,即Customer.hbm.xml。你有没想过,这个映射配置文件应该放置在哪儿呢?那肯定是放在src/main/resources目录下。之前都是将这样的映射配置文件与其相对应的实体类放在同一个包下,所以我们也可以在src/main/resources目录下新建一个com.meimeixia.crm.domain包,并在该包下创建一个Customer.hbm.xml映射配置文件。

创建相应的接口与实现类

首先,在src/main/java目录下新建一个com.meimeixia.crm.dao包,并在该包下创建一个ICustomerDao接口。

package com.meimeixia.crm.dao;import java.util.List;import com.meimeixia.crm.domain.Customer;public interface ICustomerDao {
public List
findAll(); }

然后,在src/main/java目录下再新建一个com.meimeixia.crm.dao.impl包,并在该包下创建以上接口的一个实现类。

package com.meimeixia.crm.dao.impl;import java.util.List;import org.springframework.orm.hibernate5.support.HibernateDaoSupport;import com.meimeixia.crm.dao.ICustomerDao;import com.meimeixia.crm.domain.Customer;public class CustomerDao extends HibernateDaoSupport implements ICustomerDao {
public List
findAll() {
return (List
) getHibernateTemplate().find("from Customer"); } }

Spring框架整合Hibernate框架

首先,创建Hibernate核心配置文件,该核心配置文件的位置是在src/main/resources目录下面,名称是hibernate.cfg.xml。

org.hibernate.dialect.MySQLDialect
true
false
none
true
none

然后,就要整合Spring框架与Hibernate框架了。整合不麻烦,就看你看不看得懂了,反正我是看懂了。我们可以在src/main/resources目录下新建一个名为spring的包,并在该包下创建一个名称为applicationContext-dao.xml的Spring配置文件,内容如下:

至此,crm-dao子模块就开发完毕了。

编写JUnit单元测试用例

crm-dao子模块开发完毕之后,接下来,我们就要编写JUnit单元测试用例了。温馨提示:大家在实际项目开发中,开发完一个模块后,一定要记得编写JUnit单元测试用例进行测试,这是一个合格的程序员的基本素养。

首先,确保pom.xml文件中添加了junit的依赖。

在这里插入图片描述
然后,在src/test/java目录下新建一个com.meimeixia.crm.dao.test包,并在该包下创建一个单元测试类,例如CustomerDaoTest.java。

package com.meimeixia.crm.dao.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.meimeixia.crm.dao.impl.CustomerDao;public class CustomerDaoTest {
@Test public void tt() {
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-dao.xml"); CustomerDao customerDao = (CustomerDao) ac.getBean("customerDao"); System.out.println(customerDao.findAll().size()); }}

运行以上单元测试方法,可以看到eclipse控制台打印了如下图所示的内容。

在这里插入图片描述
从上图可以知道crm-dao子模块测试完美通过,没有任何毛病!接下来,就要开发crm-service子模块了。

crm-service子模块的开发与测试

创建相应的接口与实现类

首先,在src/main/java目录下新建一个com.meimeixia.crm.service包,并在该包下创建一个ICustomerService接口。

package com.meimeixia.crm.service;import java.util.List;import com.meimeixia.crm.domain.Customer;public interface ICustomerService {
public List
findAll(); }

然后,在src/main/java目录下再新建一个com.meimeixia.crm.service.impl包,并在该包下创建以上接口的一个实现类。

package com.meimeixia.crm.service.impl;import java.util.List;import com.meimeixia.crm.dao.ICustomerDao;import com.meimeixia.crm.domain.Customer;import com.meimeixia.crm.service.ICustomerService;public class CustomerService implements ICustomerService {
private ICustomerDao customerDao; public void setCustomerDao(ICustomerDao customerDao) {
this.customerDao = customerDao; } @Override public List
findAll() {
return customerDao.findAll(); } }

配置Spring的事务管理

这里,我会使用Spring基于XML配置文件方式的声明式事务管理来管理事务。于是,在src/main/resources目录下新建一个名为spring的包,并在该包下创建一个名称为applicationContext-service.xml的Spring配置文件,内容如下:

从以上Spring配置文件的内容中可以看出,CustomerService实现类交给Spring来管理了。

编写JUnit单元测试用例

crm-service子模块开发完毕之后,接下来,我们就要编写JUnit单元测试用例了。首先,肯定要确保pom.xml文件中添加了junit的依赖。

在这里插入图片描述
然后,在src/test/java目录下新建一个com.meimeixia.crm.service.test包,并在该包下创建一个单元测试类,例如CustomerServiceTest.java。

package com.meimeixia.crm.service.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.meimeixia.crm.service.ICustomerService;public class CustomerServiceTest {
@Test public void tt() {
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-service.xml"); ICustomerService customerService = (ICustomerService) ac.getBean("customerService"); System.out.println(customerService.findAll().size()); } }

千万不要忘了在applicationContext-service.xml配置文件中添加如下配置,即在该配置文件中引入crm-dao子模块中的applicationContext-dao.xml配置文件。

在这里插入图片描述
为什么要这样做呢?因为你不加以上配置,运行CustomerServiceTest单元测试类中的测试方法就会报错,错误提示信息如下图所示。
在这里插入图片描述
导致报错的原因就是没有加载所有与Spring有关的配置文件,也即是说还没有加载到crm-dao子模块中的applicationContext-dao.xml配置文件,而LocalSessionFactoryBean类就配置在该配置文件中。

此时,再次运行CustomerServiceTest单元测试类中的测试方法,你便会看到eclipse控制台打印出了如下图所示的内容。

在这里插入图片描述
从上图可以知道crm-service子模块测试完美通过,没有任何毛病!但像上面这样做,有一个缺点,编写JUnit单元测试用例时要加上那句配置,然而最终我们都是将各个子模块聚合到一起,最后将crm-web子模块打成war包,发布到tomcat服务器上去运行,这句配置又要去掉,这样会显得很麻烦。那有没有更加好的方法来助我们编写JUnit单元测试用例呢?其实是有的,你只须将CustomerServiceTest单元测试类写成下面这样就行了。

package com.meimeixia.crm.service.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.meimeixia.crm.service.ICustomerService;public class CustomerServiceTest {
@Test public void tt() {
//classpath*:spring/applicationContext-*.xml:读取所有classpath路径下的spring目录中的所有以applicationContext-打头的配置文件 ApplicationContext ac = new ClassPathXmlApplicationContext("classpath*:spring/applicationContext-*.xml"); ICustomerService customerService = (ICustomerService) ac.getBean("customerService"); System.out.println(customerService.findAll().size()); } }

在这里插入图片描述

crm-web子模块的开发

首先,在src/main/java目录下新建一个com.meimeixia.crm.web.action包,并在该包下创建一个CustomerAction类。

package com.meimeixia.crm.web.action;import java.util.List;import com.meimeixia.crm.domain.Customer;import com.meimeixia.crm.service.ICustomerService;import com.meimeixia.crm.service.impl.CustomerService;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;/** * 客户Action类 * @author liayun * */public class CustomerAction extends ActionSupport {
//注入客户业务 private ICustomerService customerService; public void setCustomerService(CustomerService customerService) {
this.customerService = customerService; } /** * 列出所有的客户信息,并返回给list.jsp页面 * @return */ public String list() {
//查出所有客户信息 List
customerList = customerService.findAll(); //所有客户信息放入值栈中 ActionContext.getContext().put("list", customerList); //返回list.jsp页面 return "list"; } }

然后,将以上CustomerAction类交给Spring来管理。于是,我们需要在src/main/resources目录下新建一个名为spring的包,并在该包下创建一个名称为applicationContext-action.xml的Spring配置文件,内容如下:

接着,就要在Struts2配置文件中(即struts.xml)对以上CustomerAction类进行配置了。于是,我们需要在src/main/resources目录下新建一个struts.xml配置文件,内容如下:

/list.jsp

相应地,我们还要在src/main/webapp目录下新建一个展示客户列表的jsp页面,即list.jsp。

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Insert title here
${customer.custId } ----> ${customer.custName }

紧接着,我们还得在src/main/resources目录下新建一个applicationContext.xml配置文件,它用于加载所有的Spring上下文。

最后,千万别忘了在web.xml配置文件中配置Struts2的核心过滤器以及Spring的核心监听器。

crm-web
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath:applicationContext.xml
struts
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts
/*

至此,crm-web子模块总算是开发完了。

运行调试

运行方式一

这种运行方式是指在crm-web子工程的pom.xml文件中配置tomcat插件运行。

在这里插入图片描述
温馨提示:如果子工程和父工程中都配置了tomcat插件,那么访问的端口和路径以子工程为准。

我草泥马的,运行时给我报错了,eclipse控制台打印出了如下错误提示信息。

[INFO] Scanning for projects...[INFO] [INFO] -----------------------< com.meimeixia:crm-web >------------------------[INFO] Building crm-web 0.0.1-SNAPSHOT[INFO] --------------------------------[ war ]---------------------------------[INFO] [INFO] >>> tomcat7-maven-plugin:2.2:run (default-cli) > process-classes @ crm-web >>>[WARNING] The POM for com.meimeixia:crm-service:jar:0.0.1-SNAPSHOT is missing, no dependency information available[INFO] ------------------------------------------------------------------------[INFO] BUILD FAILURE[INFO] ------------------------------------------------------------------------[INFO] Total time:  0.352 s[INFO] Finished at: 2019-12-27T09:36:17+08:00[INFO] ------------------------------------------------------------------------[ERROR] Failed to execute goal on project crm-web: Could not resolve dependencies for project com.meimeixia:crm-web:war:0.0.1-SNAPSHOT: Could not find artifact com.meimeixia:crm-service:jar:0.0.1-SNAPSHOT -> [Help 1][ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.[ERROR] Re-run Maven using the -X switch to enable full debug logging.[ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

如何解决该问题呢?可以参考我的这篇文章——。

有可能你在对父工程进行install时,会报如下图所示的错误。

在这里插入图片描述
至于怎么解决这个问题,同样可以参考我的这篇文章——。

再次通过crm-web子工程的pom.xml文件中配置的tomcat7插件来运行crm-web子工程,可以发现此时并不会报错,该子工程确实是部署到tomcat服务器上去了,并成功运行起来了,如下图所示。

在这里插入图片描述
紧接着,打开Google Chrome浏览器,访问http://localhost:8080/crm/customer_list这样的url地址,这时发现又又又他妈的报错了,详细的错误提示信息如下:

java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy51 implementing com.meimeixia.crm.service.ICustomerService,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.meimeixia.crm.service.impl.CustomerService] for property 'customerService': no matching editors or conversion strategy found	org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:302)	org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:576)	org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:603)	org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:204)	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1527)	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1486)	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)	org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1048)	com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(SpringObjectFactory.java:161)	com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:178)	com.opensymphony.xwork2.factory.DefaultActionFactory.buildAction(DefaultActionFactory.java:22)	com.opensymphony.xwork2.ObjectFactory.buildAction(ObjectFactory.java:148)	com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:295)	com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:395)	com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194)	org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)	org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37)	com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)	org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:554)	org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)	org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)

至于如何解决这个问题,可以参考我的这篇文章——。

运行crm-web子工程时,它会从本地仓库下载所依赖的jar包,所以当crm-web子工程依赖的jar包内容修改了必须及时发布到本地仓库,比如:crm-web子工程依赖的crm-service子工程中的内容修改了,需要及时将crm-service子工程发布到本地仓库。

在这里插入图片描述
再次通过crm-web子工程的pom.xml文件中配置的tomcat7插件来运行该子工程,运行成功之后,通过Google Chrome浏览器访问http://localhost:8080/crm/customer_list这样的url地址,这时,你便会看到如下图所示的效果了,即查询出了所有客户信息。
在这里插入图片描述

运行方式二

在父工程的pom.xml文件中配置tomcat插件运行(自动聚合并执行)。父工程的作用就是将各个子工程聚合到一起。

在这里插入图片描述
至于如何运行父工程,不用我说了吧!但有一点需要注意,最后是将crm-web子工程打成了war包,并发布到了tomcat服务器上,最终运行的依然是crm-web子工程。

推荐使用这种运行方式,因为如果子工程都在本地,采用这种运行方式则不需要子工程修改就立即发布到本地仓库,父工程会自动聚合并使用最新代码执行。

运行方式三

将crm-web子工程部署到本地tomcat服务器上去运行。

转载地址:https://liayun.blog.csdn.net/article/details/103711761 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:maven快速入门番外篇——运行maven项目时报错:Failed to execute goal on project ...
下一篇:maven快速入门第十二讲——版本锁定与版本常量

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年05月02日 12时12分06秒