一、创建 SSMVCAnnoDemo 项目
点击菜单,选择“File -> New Project” 创建新项目。选择使用 archetype 中的 maven-webapp 模版创建。
输入对应的项目坐标GroupId 和 ArtifactId
之后在项目名称中填入项目名称,这里我填的 ProjectName 和上文的 ArtifactId 相同,都是 SSMVCAnnoDemo。
点击确定后,等待 Maven 帮我们构建好项目的目录结构。当控制台显示 BUILD SUCCESS 就表示初始化完成了。
初始化完成后的目录结构是这样的:
在 main 目录下创建 java 目录并将其设置为源码目录:
之后创建 com.chanshuyi.action 等包,创建完成后的目录结构如下:
二、导入依赖的包和插件
设置 POM.XML 配置文件中的全局属性:
UTF-8
2.3.24
4.1.6.RELEASE
3.8.1
1.2
依次引入 MyBatis、Spring、SpringMVC、MySQL、Druid、JUnit、Log4J 等的依赖 Jar 包:
org.mybatis
mybatis
3.1.1
org.mybatis
mybatis-spring
1.1.1
org.springframework
spring-webmvc
${springframework.version}
org.springframework
spring-core
${springframework.version}
org.springframework
spring-tx
${springframework.version}
org.springframework
spring-orm
${springframework.version}
org.springframework
spring-jdbc
${springframework.version}
org.springframework
spring-web
${springframework.version}
org.springframework
spring-context
${springframework.version}
org.springframework
spring-beans
${springframework.version}
commons-logging
commons-logging
${commonsLogging.version}
org.aspectj
aspectjweaver
1.8.5
javax.servlet
jstl
1.2
taglibs
standard
1.1.2
javax.servlet
javax.servlet-api
3.0.1
provided
mysql
mysql-connector-java
5.1.21
com.alibaba
druid
1.0.6
junit
junit
${junit.version}
test
org.slf4j
slf4j-api
1.7.6
org.slf4j
slf4j-log4j12
1.7.6
之后导入 Tomcat 启动插件,我们将通过 Maven 方式启动 Tomcat,这样就不必在本地配置一个 Tomcat 服务器。
org.apache.tomcat.maven
tomcat7-maven-plugin
2.1
5050
/
UTF-8
mgr
tomcat7
配置完成后的 POM.XML 是这样的:
4.0.0
com.chanshuyi.SSMVCAnnoDemo
SSMVCAnnoDemo
war
1.0-SNAPSHOT
SSMVCAnnoDemo Maven Webapp
http://maven.apache.org
UTF-8
2.3.24
4.1.6.RELEASE
3.8.1
1.2
org.mybatis
mybatis
3.1.1
org.mybatis
mybatis-spring
1.1.1
org.springframework
spring-webmvc
${springframework.version}
org.springframework
spring-core
${springframework.version}
org.springframework
spring-tx
${springframework.version}
org.springframework
spring-orm
${springframework.version}
org.springframework
spring-jdbc
${springframework.version}
org.springframework
spring-web
${springframework.version}
org.springframework
spring-context
${springframework.version}
org.springframework
spring-beans
${springframework.version}
commons-logging
commons-logging
${commonsLogging.version}
org.aspectj
aspectjweaver
1.8.5
javax.servlet
jstl
1.2
taglibs
standard
1.1.2
javax.servlet
javax.servlet-api
3.0.1
provided
mysql
mysql-connector-java
5.1.21
com.alibaba
druid
1.0.6
junit
junit
${junit.version}
test
org.slf4j
slf4j-api
1.7.6
org.slf4j
slf4j-log4j12
1.7.6
SSMVCAnnoDemo
org.apache.tomcat.maven
tomcat7-maven-plugin
2.1
5050
/
UTF-8
mgr
tomcat7
pom.xml
三、开发模型层(MyBatis)
创建 SpringMVC 配置文件 resources/spring-servlet.xml
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">
创建 spring-mybatis.xml 文件,配置一个只读的数据源以及一个只写的数据源
创建 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/SSMDemo
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/SSMDemo
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
在本地 MySQL 数据库创建一个 SSMDemo 数据库,执行下面的语句创建 user 表并插入一条测试数据。
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) DEFAULT NULL,
`password` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'admin', 'password');
创建 mybatis-config.xml 文件,并配置需要扫描包路径
下载 MBGGenerator(密码:c1dy),这是MyBatis 官方的 MyBatis Generator,我们使用它将数据库表转化成 model、mapper 以及 SqlProvider 文件。
下载文件解压放到 resources 目录下。进入 resources/mbg 目录,双击运行 generate.bat,程序自动将配置文件 resources/mbgconfig.xml 中配置的表格映射成相对应的文件。
四、开发视图层(Spring)
创建 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进行查询
*@paramparam
*@return
*/@SelectProvider(type= UserSqlProvider.class, method = "getUserListByMapSql")
List getUserListByMapSql(@Param("param") Map param);
在 UserSqlProvider 类增加对上面接口 SQL 的实现:
/*** 获取查询SQL
*@paramparam
*@return
*/
public String getUserListByMapSql(Mapparam) {
StringBuilder builder= newStringBuilder();
Map realParam = (Map)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 newString(builder);
}public String getQueryCondition(Mapparam){
StringBuilder builder= newStringBuilder();//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 newString(builder);
}
上面用到了 StringUtil.java,我们在 com.chanshuyi.util 中导入它:
packagecom.mszz.util;importjava.util.Collection;importjava.util.Map;/*** 字符串工具类
*@authorchenxinquan
**/
public classStringUtil {/*** 判断对象或对象数组中每一个对象是否为空: 对象为null,字符序列长度为0,集合类、Map为empty
*@authorzl
*@paramobj
*@return
*/
public static booleanisNullOrEmpty(Object obj) {if (obj == null)return true;if (obj instanceofCharSequence)return ((CharSequence) obj).length() == 0;if (obj instanceofCollection)return((Collection) obj).isEmpty();if (obj instanceofMap)return((Map) obj).isEmpty();if (obj instanceofObject[]) {
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;
}
}returnempty;
}return false;
}
}
StringUtil.java
View Code
创建 com.chanshuyi.dao.impl.BaseDao.java 类,提供基本的数据库读写对象,并用注解方式将 SqlSession 注入。
packagecom.chanshuyi.dao.impl;importorg.apache.ibatis.session.SqlSession;importorg.springframework.beans.factory.annotation.Autowired;/*** 所有Service的基类,用来注入sqlSession*/
public classBaseDao {/*** 可写的sqlSession*/@AutowiredprotectedSqlSession writableSQLSession;/*** 只读的sqlSession*/@AutowiredprotectedSqlSession readonlySQLSession;
}
创建DAO层接口 IUserDao.java:
packagecom.chanshuyi.dao;importcom.chanshuyi.model.User;importjava.util.List;importjava.util.Map;/*** Created by chanshuyi on 2015/12/26.*/
public interfaceIUserDao {
User getUserById(intuserId);/***
*@paramparam Map中的key要与数据库表中的字段名相同
*@return
*/User getUserByMapSql(Mapparam);
List getUserListByMapSql(Mapparam);
}
创建 UserDaoImpl.java 继承 BaseDao.java、实现 IUserDao 接口,并用 @Repository 创建名称为 userDao 的对象。
packagecom.chanshuyi.dao.impl;importcom.chanshuyi.dao.IUserDao;importcom.chanshuyi.dao.mapper.UserMapper;importcom.chanshuyi.model.User;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.springframework.stereotype.Repository;importjava.util.List;importjava.util.Map;/*** Created by Administrator on 2015/12/26.*/@Repository("userDao")public class UserDaoImpl extends BaseDao implementsIUserDao {private static Log logger = LogFactory.getLog(UserDaoImpl.class);
@Overridepublic User getUserById(intuserId) {
UserMapper mapper= readonlySQLSession.getMapper(UserMapper.class);returnmapper.selectByPrimaryKey(userId);
}/***
*@paramparam
*@return
*/@Overridepublic User getUserByMapSql(Mapparam) {
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) (错误,无法实现)
*@paramparam
*@return
*/@Overridepublic List getUserListByMapSql(Mapparam) {
logger.info("getUserListByMapSql 根据动态参数查询用户对象列表");
UserMapper mapper= readonlySQLSession.getMapper(UserMapper.class);returnmapper.getUserListByMapSql(param);
}
}
创建 IUserService.java 和 UserServiceImpl.java。在 UserServiceImpl 中添加 @Service 注解创建名称为 userService 的对象,并将 userDao 对象注入。
packagecom.mszz.service;importcom.mszz.model.User;importjava.util.List;importjava.util.Map;/*** Created by chanshuyi on 2015/12/26.*/
public interfaceIUserService {
User getUserById(intuserId);/***
*@paramparam Map中的key要与数据库表中的字段名相同
*@return
*/User getUserByMapSql(Mapparam);
List getUserListByMapSql(Mapparam);
}
packagecom.chanshuyi.service.impl;importcom.chanshuyi.dao.IUserDao;importcom.chanshuyi.model.User;importcom.chanshuyi.service.IUserService;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importjava.util.List;importjava.util.Map;/*** Created by Administrator on 2015/6/18.*/@Service("userService")public class UserServiceImpl implementsIUserService {private static Log logger = LogFactory.getLog(UserServiceImpl.class);
@Autowired
IUserDao userDao;
@Overridepublic User getUserById(intuserId) {returnuserDao.getUserById(userId);
}
@Overridepublic User getUserByMapSql(Mapparam) {returnuserDao.getUserByMapSql(param);
}
@Overridepublic List getUserListByMapSql(Mapparam) {returnuserDao.getUserListByMapSql(param);
}
}
五、开发控制层(Struts)
创建 com.chanshuyi.action.UserController 类
packagecom.chanshuyi.controller;importcom.chanshuyi.service.IUserService;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.ResponseBody;importjavax.servlet.http.HttpServletRequest;importjava.util.HashMap;importjava.util.Map;/*** Created by Administrator on 2015/6/18.*/@Controller("userAction")
@RequestMapping(value="/login")public classUserController{private static Logger logger = LoggerFactory.getLogger(UserController.class);privateString message;privateString username;privateString password;
@AutowiredprivateIUserService userService;
@AutowiredprivateHttpServletRequest request;
@RequestMapping("")public String login(@RequestParam(value = "username", required = false) String username,
@RequestParam(value= "password", required = false) String password){try{
Map param = new HashMap();
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 ********/
publicString getMessage() {returnmessage;
}public voidsetMessage(String message) {this.message =message;
}publicString getUsername() {returnusername;
}public voidsetUsername(String username) {this.username =username;
}publicString getPassword() {returnpassword;
}public voidsetPassword(String password) {this.password =password;
}
}
创建 webapp/index.jsp 文件
Hello World!
${message}
Username:
Password:
修改 web.xml 文件,加载 SpringMVC 处理器
/p>
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
Archetype Created Web Application
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
encodingFilter
/*
spring
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:/spring-servlet.xml
1
spring
/
六、启动项目测试
为工程配置 Maven 命令 “tomcat7:run”
点击启动项目
输入 admin/password,点击 Login 按钮
提示登录成功,说明项目已经成功部署好。
与 Spring 框架项目对比
因为我们一般用 SpringMVC 的时候都是用注解的形式,所以SpringMVC 框架的项目都是注解形式,没有 XML 配置文件方式。下面我们来对比一下用 SpringMVC 和用 Spring + Struts 的实现区别。
1、使用 SpringMVC 框架时需要配置与 Spring 不同的 web.xml 配置,并且读取的根配置文件不再是 applicationContext.xml,而是 servletName-servlet.xml(servletName 表示的是配置在 web.xml 中的servlet 名称)。
2、因为使用了 SpringMVC,所以不再需要 Struts 来接收用户请求,而是直接通过 @RequestMapping 注解的方式在 Controller 类上进行注解映射,也就少了 struts.xml 这个配置文件。而一般情况下用 SpringMVC 的项目更习惯于将 Action 写成 Controller。