一、创建 SSMVCAnnoDemo 项目

点击菜单,选择“File -> New Project” 创建新项目。选择使用 archetype 中的 maven-quickstart 模版创建。

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc

输入对应的项目坐标GroupId 和 ArtifactId

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_spring_02

之后在项目名称中填入项目名称,这里我填的 ProjectName 和上文的 ArtifactId 相同,都是 SuperDemo。

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_spring_03

点击确定后,等待 Maven 帮我们构建好项目的目录结构。当控制台显示 BUILD SUCCESS 就表示初始化完成了。

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc_04

完成初始化之后,我们分别创建 model、interface、provider、consumer 模块,它们的作用分别是:

model:存放 POJO 文件的模块

interface:存放接口文件的模块

provider:提供服务的模块

consumer:调用服务的模块

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_xml_05

二、配置 model 模块

在 SuperDemo 模块的 pom.xml 文件添加 JUnit、Log4J 等公共依赖:

<!-- 单元测试 JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>provided</scope>
</dependency>
<!-- 日志记录 Log4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
<!-- JSON 包 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>

修改后的 pom.xml 为:

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_xml_06

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_spring_07

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.chanshuyi.SuperDemo</groupId>
<artifactId>SuperDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>interface</module>
<module>model</module>
<module>provider</module>
<module>consumer</module>
</modules>
<packaging>pom</packaging>

<name>SuperDemo</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>3.8.1</junit.version>
</properties>

<dependencies>
<!-- 单元测试 JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>provided</scope>
</dependency>
<!-- 日志记录 Log4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
<!-- JSON 包 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
</dependencies>
</project>

pom.xml

下载 ​​MBGGenerator​​(密码:c1dy),这是MyBatis 官方的 MyBatis Generator,我们使用它将数据库表转化成 model、mapper 以及 SqlProvider 文件。

下载文件解压放到 provider 模块的 resources 目录下。进入 resources/mbg 目录,双击运行 generate.bat,程序自动将配置文件 resources/mbgconfig.xml 中配置的表格映射成相对应的文件。

将上面生成后的 com.chanshuyi.model.User 类拷贝至 model 模块的 com.chanshuyi.model 包。

三、配置 interface 模块

打开 interface 模块的 pom.xml 模块,加入对于 SuperDemo 下 model 模块的依赖:

<dependency>
<groupId>com.chanshuyi.SuperDemo</groupId>
<artifactId>model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

创建 com.chanshuyi.dao.IUserDao 接口

package com.chanshuyi.dao;

import com.chanshuyi.model.User;

import java.util.List;
import java.util.Map;

/**
* Created by chanshuyi on 2015/12/26.
*/
public interface IUserDao {
User getUserById(int userId);

/**
*
* @param param Map中的key要与数据库表中的字段名相同
* @return
*/
User getUserByMapSql(Map<String, String> param);

List<User> getUserListByMapSql(Map<String, String> param);
}

创建 com.chanshuyi.service.IUserService 接口

package com.chanshuyi.service;


import com.chanshuyi.model.User;

import java.util.List;
import java.util.Map;

/**
* Created by chanshuyi on 2015/12/26.
*/
public interface IUserService {
User getUserById(int userId);

/**
*
* @param param Map中的key要与数据库表中的字段名相同
* @return
*/
User getUserByMapSql(Map<String, String> param);

List<User> getUserListByMapSql(Map<String, String> param);
}

四、配置 provider 模块

打开 provider 模块的 pom.xml 文件,加入全局属性声明

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.1.6.RELEASE</springframework.version>
<commonsLogging.version>1.2</commonsLogging.version>
</properties>

导入 Spring、MyBatis 等依赖

<dependencies>
<!-- ********************** MyBatis ********************** -->
<!-- MyBatis 核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.1.1</version>
</dependency>
<!-- 添加mybatis与Spring整合的核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.1.1</version>
</dependency>

<!-- ********************** Spring ********************** -->
<!-- 添加Spring-core包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-tx包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring ORM 相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-jdbc包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--添加spring-web包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-context包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commonsLogging.version}</version>
</dependency>
<!--添加aspectjweaver包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>

<!-- ********************** JDBC ********************** -->
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.6</version>
</dependency>

<!-- ********************** DUBBO ********************** -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- ********************** Zookeeper ********************** -->
<!-- zookeeper -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.3</version>
<exclusions>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- ********************** 其他 ********************** -->
<!-- 核心接口 -->
<dependency>
<groupId>com.chanshuyi.SuperDemo</groupId>
<artifactId>interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

在 resources 目录下创建 applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

<!-- ================================== import sub-config file ================================== -->
<import resource="spring-mybatis.xml" />
<!-- ================================== /import sub-config file ================================== -->
</beans>

创建 MyBatis 配置文件 spring-mybatis.xml

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
6
7 <!-- 引入外部properties文件 -->
8 <context:property-placeholder location="classpath:jdbc.properties" />
9
10 <!-- ====================================================== Add MyBatis Support Start ====================================================== -->
11 <!-- 配置写数据源 -->
12 <bean id="dataSourceWrite" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
13 <!-- 基本属性 url、user、password -->
14 <property name="url" value="${jdbc.master.url}" />
15 <property name="username" value="${jdbc.master.username}" />
16 <property name="password" value="${jdbc.master.password}" />
17 <!-- 配置初始化大小、最小、最大 -->
18 <property name="initialSize" value="${jdbc.master.initialSize}" />
19 <property name="minIdle" value="${jdbc.master.minIdle}" />
20 <property name="maxActive" value="${jdbc.master.maxActive}" />
21 <!-- 配置获取连接等待超时的时间 -->
22 <property name="maxWait" value="60000" />
23 <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
24 <property name="timeBetweenEvictionRunsMillis" value="60000" />
25 <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
26 <property name="minEvictableIdleTimeMillis" value="300000" />
27 <property name="validationQuery" value="SELECT '1'" />
28 <property name="testWhileIdle" value="true" />
29 <property name="testOnBorrow" value="true" />
30 <property name="testOnReturn" value="false" />
31 <!-- 打开PSCache,并且指定每个连接上PSCache的大小 mysql false -->
32 <property name="poolPreparedStatements" value="false" />
33 <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
34 <!-- 配置监控统计拦截的filters -->
35 <property name="filters" value="config,stat,log4j,wall" />
36 <property name="connectionProperties" value="config.decrypt=false" />
37 </bean>
38 <!-- 配置读数据源 -->
39 <bean id="dataSourceRead" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
40 <!-- 基本属性 url、user、password -->
41 <property name="url" value="${jdbc.slave.url}" />
42 <property name="username" value="${jdbc.slave.username}" />
43 <property name="password" value="${jdbc.slave.password}" />
44 <!-- 配置初始化大小、最小、最大 -->
45 <property name="initialSize" value="${jdbc.slave.initialSize}" />
46 <property name="minIdle" value="${jdbc.slave.minIdle}" />
47 <property name="maxActive" value="${jdbc.slave.maxActive}" />
48 <!-- 配置获取连接等待超时的时间 -->
49 <property name="maxWait" value="60000" />
50 <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
51 <property name="timeBetweenEvictionRunsMillis" value="60000" />
52 <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
53 <property name="minEvictableIdleTimeMillis" value="300000" />
54 <property name="validationQuery" value="SELECT '1'" />
55 <property name="testWhileIdle" value="true" />
56 <property name="testOnBorrow" value="false" />
57 <property name="testOnReturn" value="false" />
58 <!-- 打开PSCache,并且指定每个连接上PSCache的大小 mysql false -->
59 <property name="poolPreparedStatements" value="false" />
60 <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
61 <!-- 配置监控统计拦截的filters -->
62 <property name="filters" value="config,stat,log4j,wall" />
63 <property name="connectionProperties" value="config.decrypt=false" />
64 </bean>
65
66 <!-- 可写的SessionFactory -->
67 <bean id="sqlWriteSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" scope="singleton">
68 <property name="dataSource" ref="dataSourceWrite" />
69 <property name="configLocation" value="classpath:mybatis-config.xml" />
70 </bean>
71 <!-- 只读的SessionFactory -->
72 <bean id="sqlReadOnlySessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" scope="singleton">
73 <property name="dataSource" ref="dataSourceRead" />
74 <property name="configLocation" value="classpath:mybatis-config.xml" />
75 </bean>
76
77 <!-- 可写的Session -->
78 <bean id="writableSQLSession" class="org.mybatis.spring.SqlSessionTemplate">
79 <constructor-arg index="0" ref="sqlWriteSessionFactory" />
80 </bean>
81 <!-- 只读的Session -->
82 <bean id="readonlySQLSession" class="org.mybatis.spring.SqlSessionTemplate">
83 <constructor-arg index="0" ref="sqlReadOnlySessionFactory" />
84 </bean>
85 <!-- ====================================================== Add MyBatis Support End ====================================================== -->
86 </beans>

配置 MyBatis 注解扫描路径,创建 mybatis-config.xml 配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<mappers>
<!-- 配置扫描的Mapper类 -->
<package name="com.chanshuyi.dao.mapper"/>
</mappers>
</configuration>

创建数据库配置文件 jdbc.properties

############################  MySQL/Oracle/SQLServer Database Configuratioin Info ###############################
# MySQL Master DB Info
jdbc.master.dialet=org.hibernate.dialect.MySQLDialect
jdbc.master.driverClassName=com.mysql.jdbc.Driver
jdbc.master.url=jdbc:mysql://127.0.0.1:3306/superdemo
jdbc.master.username=root
jdbc.master.password=sa

# MySQL Slave DB Info
jdbc.slave.dialet=org.hibernate.dialect.MySQLDialect
jdbc.slave.driverClassName=com.mysql.jdbc.Driver
jdbc.slave.url=jdbc:mysql://localhost:3306/superdemo
jdbc.slave.username=root
jdbc.slave.password=sa

############################## Connection Pool Configuration Info ##############################################
# MySQL Master DB Setting
jdbc.master.initialSize = 10
jdbc.master.minIdle = 0
jdbc.master.maxActive = 30

# MySQL Slave DB Setting
jdbc.slave.initialSize = 10
jdbc.slave.minIdle = 0
jdbc.slave.maxActive = 30

创建 resources/log4j.properties 文件,提供日志记录。

#Console Log
log4j.rootLogger=info, console, file

# Write to Console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=INFO
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%5p %d{MM-dd HH:mm:ss}(%F:%L): %m%n

# Write to File
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=${catalina.home}app/log/log.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%5p %d{MM-dd HH:mm:ss}(%F:%L): %m%n

在 com.chanshuyi.dao.mapper.UserMapper 类中增加 getUserListByMapSql 接口:

/**
* 根据参数构造SQL进行查询
* @param param
* @return
*/
@SelectProvider(type = UserSqlProvider.class, method = "getUserListByMapSql")
List<User> getUserListByMapSql(@Param("param") Map<String, String> param);

在 UserSqlProvider 类增加对上面接口 SQL 的实现:

/**
* 获取查询SQL
* @param param
* @return
*/
public String getUserListByMapSql(Map<String, Object> param) {
StringBuilder builder = new StringBuilder();
Map<String, String> realParam = (Map<String, String>)param.get("param");

//add select part
builder.append(" select * from user where 1 = 1 ");

//add condition part
String conditionStr = "";
if(!StringUtil.isNullOrEmpty(realParam)){
conditionStr = getQueryCondition(realParam);
if(!StringUtil.isNullOrEmpty(conditionStr)){
builder.append(conditionStr);
}
}

return new String(builder);
}

public String getQueryCondition(Map<String, String> param){
StringBuilder builder = new StringBuilder();

//if param is null or empty, return empty String
if(param == null || param.size() < 1){
return "";
}

for(String key : param.keySet()){
String value = param.get(key);
if(value != null && !value.isEmpty()){
builder.append(" and " + key + " = '" + value + "'");
}
}

return new String(builder);
}

上面用到了 StringUtil.java,我们在 com.chanshuyi.util 中导入它:

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_xml_06

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_spring_07

package com.mszz.util;

import java.util.Collection;
import java.util.Map;

/**
* 字符串工具类
* @author chenxinquan
*
*/
public class StringUtil {
/**
* 判断对象或对象数组中每一个对象是否为空: 对象为null,字符序列长度为0,集合类、Map为empty
* @author zl
* @param obj
* @return
*/
public static boolean isNullOrEmpty(Object obj) {
if (obj == null)
return true;

if (obj instanceof CharSequence)
return ((CharSequence) obj).length() == 0;

if (obj instanceof Collection)
return ((Collection) obj).isEmpty();

if (obj instanceof Map)
return ((Map) obj).isEmpty();

if (obj instanceof Object[]) {
Object[] object = (Object[]) obj;
if (object.length == 0) {
return true;
}
boolean empty = true;
for (int i = 0; i < object.length; i++) {
if (!isNullOrEmpty(object[i])) {
empty = false;
break;
}
}
return empty;
}
return false;
}
}

StringUtil.java

View Code

创建 com.chanshuyi.dao.impl.BaseDao.java 类,提供基本的数据库读写对象,并用注解方式将 SqlSession 注入。

package com.chanshuyi.dao.impl;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;

/**
* 所有Service的基类,用来注入sqlSession
*/
public class BaseDao {
/**
* 可写的sqlSession
*/
@Autowired
protected SqlSession writableSQLSession;

/**
* 只读的sqlSession
*/
@Autowired
protected SqlSession readonlySQLSession;
}

创建 com.chanshuyi.dao.impl.UserDaoImpl.java 继承 BaseDao.java、实现 IUserDao 接口,并用 @Repository 创建名称为 userDao 的对象。

package com.chanshuyi.dao.impl;

import com.chanshuyi.dao.IUserDao;
import com.chanshuyi.dao.mapper.UserMapper;
import com.chanshuyi.model.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

/**
* Created by Administrator on 2015/12/26.
*/
@Repository("userDao")
public class UserDaoImpl extends BaseDao implements IUserDao {

private static Log logger = LogFactory.getLog(UserDaoImpl.class);

@Override
public User getUserById(int userId) {
UserMapper mapper = readonlySQLSession.getMapper(UserMapper.class);
return mapper.selectByPrimaryKey(userId);
}

/**
*
* @param param
* @return
*/
@Override
public User getUserByMapSql(Map<String, String> param) {
logger.info("getUserByMapSql 根据动态参数查询用户对象");
return getUserListByMapSql(param).size() > 0 ? getUserListByMapSql(param).get(0) : null;
}

/**
* get**MapSql()类的方法只能用于各参数的等于查询
* 例如:select * from user where username = 1 and password = 3 (正确)
* select * from user where username in (1,2,3) (错误,无法实现)
* @param param
* @return
*/
@Override
public List<User> getUserListByMapSql(Map<String, String> param) {
logger.info("getUserListByMapSql 根据动态参数查询用户对象列表");
UserMapper mapper = readonlySQLSession.getMapper(UserMapper.class);
return mapper.getUserListByMapSql(param);
}
}

创建 com.chanshuyi.service.impl.UserServiceImpl 类,并添加 @Service 注解创建名称为 userService 的对象,并将 userDao 对象注入。

package com.chanshuyi.service.impl;

import com.chanshuyi.dao.IUserDao;
import com.chanshuyi.model.User;
import com.chanshuyi.service.IUserService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
* Created by Administrator on 2015/6/18.
*/
@Service("userService")
public class UserServiceImpl implements IUserService {

private static Log logger = LogFactory.getLog(UserServiceImpl.class);

@Autowired
IUserDao userDao;

@Override
public User getUserById(int userId) {
return userDao.getUserById(userId);
}

@Override
public User getUserByMapSql(Map<String, String> param) {
return userDao.getUserByMapSql(param);
}

@Override
public List<User> getUserListByMapSql(Map<String, String> param) {
return userDao.getUserListByMapSql(param);
}
}

DAO 和 SERVICE 层的配置写好之后,需要在 applicationContext.xml 文件中配置扫描路径:

<!-- 开启注解相关处理器 -->
<context:annotation-config/>
<!-- 自动扫描Spring注解(如:autowired) -->
<context:component-scan base-package="com.chanshuyi.dao.impl, com.chanshuyi.service.impl"/>

到这里基本 provider 大部分配置已经结束,下面我们需要启动 provider 模块,让它对外提供服务。

创建 com.chanshuyi.util.SystemDetails 类,用来打印系统的基本信息:

package com.chanshuyi.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class SystemDetails {
/**
* 输出系统基本信息
*/
public static void outputDetails() {
timeZone();
currentTime();
os();
}

/**
* 输出系统时区
*/
private static void timeZone() {
Calendar cal = Calendar.getInstance();
TimeZone timeZone = cal.getTimeZone();
System.out.println("系统时区:" + timeZone.getDisplayName());
}

/**
* 输出系统时间
*/
private static void currentTime() {
String fromFormat = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat format = new SimpleDateFormat(fromFormat);
Date myDate = new Date();
System.out.println("系统时间:" + format.format(myDate));
}

/**
* 输出系统基本配置
*/
private static void os() {
String osName = System.getProperty("os.name"); //操作系统名称
System.out.println("当前系统:" + osName);
String osArch = System.getProperty("os.arch"); //操作系统构架
System.out.println("当前系统架构" + osArch);
String osVersion = System.getProperty("os.version"); //操作系统版本
System.out.println("当前系统版本:" + osVersion);
}
}

创建 com.chanshuyi.util.BeanFactoryUtil,用于加载 Spring 配置文件:

package com.chanshuyi.util;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanFactoryUtil {
private static ApplicationContext ctx_producer = null;

public final static String ApplicationContextRoot = "";
public final static String ApplicationContextPath = ApplicationContextRoot + "applicationContext.xml";

public static void init() {
if (ctx_producer == null) {
synchronized (BeanFactoryUtil.class) {
if(ctx_producer == null){
String[] configLocations = new String[]{ApplicationContextPath};
ctx_producer = new ClassPathXmlApplicationContext(configLocations);
}
}
}
}

public static ApplicationContext getContext() {
if (ctx_producer == null) {
init();
}
return ctx_producer;
}
}

创建 com.chanshuyi.Launcher 类,用于启动 provider 服务,加载 Spring 配置文件,对外提供服务:

package com.chanshuyi;

import com.chanshuyi.util.BeanFactoryUtil;
import com.chanshuyi.util.SystemDetails;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Launcher {

private static Log logger = LogFactory.getLog(Launcher.class);

/**
* @param args
*/
public static void main(String[] args) {
System.out.println("=======================");
System.out.println(" Core包启动 ");
SystemDetails.outputDetails();
System.out.println("=======================");

getLocalip();
// 初始化spring
logger.info("开始初始化core服务");
BeanFactoryUtil.init();

try{
System.in.read();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 取得本机ip地址 注意:Spring RmiServiceExporter取得本机ip的方法:InetAddress.getLocalHost()
*/
private static void getLocalip() {
try {
System.out.println("服务暴露的ip: "
+ java.net.InetAddress.getLocalHost().getHostAddress());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

我们还要创建一个 spring-provider.xml 文件,告诉 dubbo 我们的基本信息以及对外提供的服务:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 添加 DUBBO SCHEMA -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<!-- 应用名 -->
<!-- 需要用到多个注册中心,因此在 dubbo.properties 中声明 -->
<dubbo:application name="superdemo_provider"/>
<!-- 连接到哪个本地注册中心 -->
<dubbo:registry id="superdemo_zk" address="zookeeper://localhost:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="28080"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service registry="superdemo_zk" timeout="3000" interface="com.chanshuyi.service.IUserService" ref="userService"/>
</beans>

记得在 applicationContext.xml 文件中将 spring-provider.xml 文件导入进去:

<import resource="spring-provider.xml" />

五、配置 consumer 模块

打开 pom.xml 文件,导入全局配置变量以及所需的 SpringMVC、Dubbo、Zookeeper、com.chanshuyi.SuperDemo.interface 依赖:

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.1.6.RELEASE</springframework.version>
<commonsLogging.version>1.2</commonsLogging.version>
</properties>

<dependencies>
<!-- ********************** Spring ********************** -->
<!-- Spring MVC 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加Spring-core包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-tx包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring ORM 相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-jdbc包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--添加spring-web包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-context包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commonsLogging.version}</version>
</dependency>
<!--添加aspectjweaver包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>

<!-- ********************** DUBBO ********************** -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.3</version>
<exclusions>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- ********************** Zookeeper ********************** -->
<!-- zookeeper -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>

<!-- ********************** interface 接口 ********************** -->
<dependency>
<groupId>com.chanshuyi.SuperDemo</groupId>
<artifactId>interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

之后导入 Tomcat 启动插件,我们将通过 Maven 方式启动 Tomcat,这样就不必在本地配置一个 Tomcat 服务器。

<!--  Maven的Tomcat插件(支持Maven以"tomcat7:run"方式启动web项目)  -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>5050</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
<finalName>mgr</finalName>
<server>tomcat7</server>
</configuration>
</plugin>

配置完成后的 pom.xml 文件是这样的:

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_xml_06

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_spring_07

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>SuperDemo</artifactId>
<groupId>com.chanshuyi.SuperDemo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.chanshuyi.SuperDemo</groupId>
<artifactId>app</artifactId>
<packaging>war</packaging>
<name>app Maven Webapp</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.1.6.RELEASE</springframework.version>
<commonsLogging.version>1.2</commonsLogging.version>
</properties>

<dependencies>
<!-- ********************** Spring ********************** -->
<!-- Spring MVC 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加Spring-core包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-tx包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring ORM 相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-jdbc包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--添加spring-web包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-context包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commonsLogging.version}</version>
</dependency>
<!--添加aspectjweaver包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>

<!-- ********************** DUBBO ********************** -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.3</version>
<exclusions>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- ********************** Zookeeper ********************** -->
<!-- zookeeper -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>

<!-- ********************** interface 接口 ********************** -->
<dependency>
<groupId>com.chanshuyi.SuperDemo</groupId>
<artifactId>interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

<build>
<finalName>consumer</finalName>
<!-- Maven的Tomcat插件(支持Maven以"tomcat7:run"方式启动web项目) -->
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>5050</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
<finalName>mgr</finalName>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
</project>

View Code

之后在 main 目录下创建 java 目录,并设置为 Java Source(源码目录):

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_spring_12

之后创建 com.chanshuyi.controller.UserController 类:

package com.chanshuyi.controller;

import com.chanshuyi.service.IUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
* Created by Administrator on 2015/6/18.
*/
@Controller("userAction")
@RequestMapping(value="/login")
public class UserController{

private static Logger logger = LoggerFactory.getLogger(UserController.class);

private String message;

private String username;

private String password;

@Autowired
private IUserService userService;

@Autowired
private HttpServletRequest request;

@RequestMapping("")
public String login(@RequestParam(value = "username", required = false) String username,
@RequestParam(value = "password", required = false) String password){
try{
Map<String, String> param = new HashMap<String, String>();
param.put("username", username);
param.put("password", password);
if(userService.getUserByMapSql(param) != null){
message = "登录成功!";
logger.info(message);
}else{
message = "登录失败!";
logger.info(message);
}
}catch(Exception e){
logger.warn(e.getMessage());
e.printStackTrace();
}
request.setAttribute("message", message);
return "index"; // 转到webapp/index.jsp页面
}

/******** set/get ********/
public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

创建 dubbo 配置文件 spring-consumer.xml,这个文件告诉 dubbo 本模块的基本信息以及请求的服务:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 添加 DUBBO SCHEMA -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<!-- 应用名 -->
<!-- 需要用到多个注册中心,因此在 dubbo.properties 中声明 -->
<dubbo:application name="superdemo_consumer"/>
<!-- 连接到哪个本地注册中心 -->
<dubbo:registry id="superdemo_zk" address="zookeeper://localhost:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="28080"/>
<!-- 声明需要引用的服务接口 -->
<dubbo:reference registry="superdemo_zk" id="userService" interface="com.chanshuyi.service.IUserService" check="false"/>

</beans>

别忘了在 applicationContext.xml 中将 spring-consumer.xml 加入进去

<import resource="spring-consumer.xml" />

创建 webapp/index.jsp 文件

<%@page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=utf-8" %>
<%@ page isELIgnored="false"%>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h2>Hello World!</h2>
<%-- 通过Struts传递参数,数据传递方式必须选择post,否则编码错误! --%>
<form action="login" method="post" >
<p id="message">${message}</p>
<b>Username:</b><input type="text" id="name" name="username" /><br>
<b>Password:</b><input type="password" id="password" name="password"/><br>
<input type="submit" value="Login"/>
</form>
</body>
</html>

修改 web.xml 文件,加载 SpringMVC 处理器

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>

<!-- 字符集过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- spring MVC的核心就是DispatcherServlet,使用springMVC的第一步就是将下面的servlet放入web.xml
servlet-name属性非常重要,默认情况下,DispatchServlet会加载这个名字-servlet.xml的文件,如下,就会加载
dispather-servlet.xml,也是在WEN-INF目录下。-->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 设置dispatchservlet的匹配模式,通过把dispatchservlet映射到/,默认servlet会处理所有的请求,包括静态资源 -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

创建 SprngMVC 配置文件 spring-servlet.xml 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-lazy-init="true">

<!-- 通过mvc:resources设置静态资源,这样servlet就会处理这些静态资源,而不通过控制器 -->
<!-- 设置不过滤内容,比如:css,jquery,img 等资源文件 -->
<!--<mvc:resources location="/*.html" mapping="/**.html" />-->
<!--<mvc:resources location="/css/*" mapping="/css/**" />-->
<!--<mvc:resources location="/js/*" mapping="/js/**" />-->
<!--<mvc:resources location="/images/*" mapping="/images/**" />-->

<!-- 添加注解驱动 -->
<mvc:annotation-driven />
<!-- 默认扫描的包路径 -->
<context:component-scan base-package="com.chanshuyi.controller" />

<!-- mvc:view-controller可以在不需要Controller处理request的情况,转向到设置的View -->
<!-- 像下面这样设置,如果请求为/,则不通过controller,而直接解析为/index.jsp -->
<!--<mvc:view-controller path="/" view-name="index" />-->
<!-- 配置 SpringMVC Controller 转发JSP页面的路径 -->
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<!-- 配置jsp路径前缀 -->
<property name="prefix" value="/"></property>
<!-- 配置URl后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>

配置好之后将整个项目编译一次,为整个项目配置 Maven 命令:

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc_13

六、启动 provider 模块和 consumer 模块测试

启动 provider 模块

先启动 zookeeper,再打开 Launcher.java 运行 main() 方法就可以了。看看控制台和 zookeeper 输出,如果没有报错,那就是启动成功了。

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_xml_14

启动 consumer 模块

为 consumer 模块配置 Maven 启动命令:"tomcat7:run"

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc_15

点击启动项目

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc_16

测试联通

打开浏览器输入:​​http://localhost:5050/index.jsp​​ 

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc_17

输入 admin/password,点击 Login 按钮

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc_18

提示登录成功,说明项目已经成功部署好。

 

链接:​​http://pan.baidu.com/s/1pKamdib​​ 密码:vutw

玩转 SSH(七):使用 dubbo + zookeeper 实现服务模块化_bc_19