SSM(Spring+SpringMVC+Mybatis)框架整合Demo+详细讲解

时间:2022-04-12 05:08:37

前言

学习ssm框架之后,自我感觉对分层架构各个层面还不是很熟悉,于是今天就整合了一个Demo,其中各个包是我个人对MVC和持久层的理解而命名的,结合各个层面的阐述和项目的代码,才恍然大悟。
在此,笔者也强烈建议大家在理解ssm基础上结合项目更易于理解、学习。文中如有误处,欢迎读者提出宝贵的建议,勿喷,文明你我 他,部分内容摘自其他 出处。。。

持久层:DAO层(mapper)

  • DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此, 
  • DAO层的设计首先是设计DAO的接口,
  • 然后在Spring的配置文件中定义此接口的实现类,
  • 然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰,
  • DAO层的数据源配置,以及有关数据库连接的参数都在Spring的配置文件中进行配置。

业务层:Service层(Modal层)

  • Service层:Service层主要负责业务模块的逻辑应用设计。
    首先设计接口,再设计其实现的类
    接着再在Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理。
    Service层的业务实现,具体要调用到已定义的DAO层的接口,
    封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。
  • 表现层:Controller层(Handler层)

    • Controller层:Controller层负责具体的业务模块流程的控制在此层里面要调用Service层的接口来控制业务流程,
    • 控制的配置也同样是在Spring的配置文件里面进行,针对具体的业务流程,会有不同的控制器,我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,这样不仅使程序结构变得清晰,也大大减少了代码量。

    View层

    • 此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示.

    各层联系

    • DAO层,Service层这两个层次都可以单独开发,互相的耦合度很低,完全可以独立进行,这样的一种模式在开发大项目的过程中尤其有优势。Controller,View层因为耦合度比较高,因而要结合在一起开发,但是也可以看作一个整体独立于前两个层进行开发。这样,在层与层之前我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切显得非常清晰简单。

    • Service逻辑层设计

      • Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的业务处理方法。

开发环境

Myeclipse+Tomcat+MySQL

效果图

SSM(Spring+SpringMVC+Mybatis)框架整合Demo+详细讲解SSM(Spring+SpringMVC+Mybatis)框架整合Demo+详细讲解SSM(Spring+SpringMVC+Mybatis)框架整合Demo+详细讲解SSM(Spring+SpringMVC+Mybatis)框架整合Demo+详细讲解

代码实现

新建框架包,持久层:entity(对象)、dao。业务层:modal、实现类impl。控制表现层:control。视图层:login.jsp、main.jsp
配置文件夹config:applicationContext.xml、log4j.properties(日志)、myBatis-config.xml、newfile.sql(数据库操作)、spring-mvc.xml
实体类User.java
package cn.mob.jekin.entity;

import java.io.Serializable;

public class User implements Serializable{
private Integer userId;
private String userName;
private String userPass;

public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPass() {
return userPass;
}
public void setUserPass(String userPass) {
this.userPass = userPass;
}


}
公共接口:BaseMapper.java
package cn.mob.jekin.dao;

public interface BaseMapper<T> {
//添加单个对象
public int insert(T entity);

//修改单个对象
public int update(T entity);

//删除单个对象
public int delete(T entity);

//查询单个对象
public T select(T entity);
}
UserMapper.java
package cn.mob.jekin.dao;

import cn.mob.jekin.entity.User;

public interface UserMapper extends BaseMapper<User> {
public User login(User user);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.mob.jekin.dao.UserMapper" >
<resultMap id="userResultMap" type="cn.mob.jekin.entity.User" >
<id column="user_id" property="userId" jdbcType="INTEGER" />
<result column="user_name" property="userName" jdbcType="VARCHAR" />
<result column="user_pass" property="userPass" jdbcType="VARCHAR" />
</resultMap>
<!-- 用户登陆 -->
<select id="login" parameterType="User" resultMap="userResultMap">
select * from user where user_name =#{userName} and user_pass =#{userPass}
</select>

</mapper>
注意:1、映射文件命名要和接口对象UserMapper一致,xml文件必须声明定义<!DOCTYPE>
2、column对应数据列名(数据库对大小写不敏感),property对应实体类属性名
3、select中的id对应UserMapper.java方法名,parameterType对应参数类型
公共接口BaseService:
package cn.mob.jekin.modal;

public interface BaseService<T> {
// 添加单个对象
public int insert(T entity) throws Exception;

// 修改单个对象
public int update(T entity) throws Exception;

// 删除单个对象
public int delete(T entity) throws Exception;

// 查询单个对象
public T select(T entity);
}
UserService:
package cn.mob.jekin.modal;

import cn.mob.jekin.entity.User;

public interface UserService extends BaseService<User> {
public User login(User user);
}
上面写起来是不是感觉在复述上面内容呢SSM(Spring+SpringMVC+Mybatis)框架整合Demo+详细讲解低耦合嘛,are you understand???
接口实现类UserServiceImpl.java
package cn.mob.jekin.modal.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.mob.jekin.dao.UserMapper;
import cn.mob.jekin.entity.User;
import cn.mob.jekin.modal.UserService;

@Service("userService")
public class UserServiceImpl implements UserService{

@Autowired
private UserMapper userMapper;

@Override
public int insert(User entity) throws Exception {
// TODO Auto-generated method stub
return 0;
}

@Override
public int update(User entity) throws Exception {
// TODO Auto-generated method stub
return 0;
}

@Override
public int delete(User entity) throws Exception {
// TODO Auto-generated method stub
return 0;
}

@Override
public User select(User entity) {
// TODO Auto-generated method stub
return null;
}

@Override
public User login(User user) {
// TODO Auto-generated method stub
return userMapper.login(user);
}

}
如果想理解更深,可以查看注解@源码了解它们之间的交互联系。
控制层公共类:BaseAction.java
package cn.mob.jekin.control;

import javax.annotation.Resource;
import javax.servlet.ServletContext;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/base")
public class BaseAction {

@Resource
ServletContext application;

// 方法参数folder通过@PathVariable指定其值可以从@RequestMapping的{folder}获取,同理file也一样
@RequestMapping("/goURL/{folder}/{file}")
public String goURL(@PathVariable String folder, @PathVariable String file) {
System.out.println("goURL.folder|file===" + folder + "/" + file);
return "forward:/WEB-INF/" + folder + "/" + file + ".jsp";
}
}


注意:此处的映射地址@RequestMapping对应的是用户访问请求的地址,代码已做注解,时间问题不多讲,实在不懂跑一次看console打印就明白。
控制分发UserAction.java
package cn.mob.jekin.control;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.mob.jekin.entity.User;
import cn.mob.jekin.modal.UserService;

@Controller
@RequestMapping("/user")
public class UserAction extends BaseAction {

@Resource
private UserService userService;

@RequestMapping(value="/login")
public String login(User user,HttpServletRequest request,HttpSession session){
System.out.println("---action.user:"+user);
User acc= userService.login(user);
if(acc!=null){
//存session
session.setAttribute("user", acc);
return "forward:/main.jsp";
}else{
request.setAttribute("msg", "用户名或密码错误!");
return "forward:/login.jsp";
}

}
}
drop database if exists ssm;

create database ssm default character set utf8;

use ssm;

drop table if exists user;


/*============================*/
/* Table: 用戶表结构 */
/*============================*/
create table user
(
/* 用戶编号,自动增长 */
user_id int not null auto_increment,
/* 用戶登录名 */
user_name varchar(20),
/* 用戶姓名 */
user_pass varchar(20),
/* 用戶密码 */
primary key (user_id)
);

/* 添加用戶数据, */
insert into user (user_name,user_pass) values ('admin','123');
insert into user (user_name,user_pass) values ('Jekin','123');

select * from user;
只有生成数据库, 添加表内 容,后面才能登录成功。
log4j.properties
# Rules reminder:
# DEBUG < INFO < WARN < ERROR < FATAL

# Global logging configuration
log4j.rootLogger=debug,stdout

# My logging configuration...
log4j.logger.cn.jbit.mybatisdemo=DEBUG


## Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n

log4j.logger.org.apache.ibatis=DEBUG
## log4j.logger.org.apache.jdbc.SimpleDataSource=DEBUG
log4j.logger.org.apache.ibatis.jdbc.ScriptRunner=DEBUG
## log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapclientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
如果出现Tomcat内存溢出,直接删除Tomcat/logs/localhost_access_log.2017-01-04文件,其他原因参考:
http://outofmemory.cn/c/java-outOfMemoryError
applicationContext.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">


<!-- 配置数据源,记得去掉myBatis-config.xml的数据源相关配置 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl"
value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8" />
<property name="user" value="root" />
<property name="password" value="admin123" />
</bean>
<!-- 配置session工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:myBatis-config.xml" />
<!--配置扫描式加载SQL映射文件,记得去掉mybatis-config配置-->
<property name="mapperLocations" value="classpath:cn/mob/jekin/dao/*.xml"/>

</bean>

<!-- 配置事务管理器,管理数据源事务处理 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置事务通知 -->
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 默认只处理运行时异常,可加rollback-for="Exception/Throwable"等处理所有异常或包括错误 -->
<tx:method name="insert*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="update*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="delete*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<!-- 配置切面织入的范围,后边要把事务边界定在service层 -->
<aop:config>
<aop:advisor advice-ref="advice"
pointcut="execution(* cn.mob.jekin.service.impl.*.*(..))" />
</aop:config>
<!-- 配置SessionTemplate,已封装了繁琐的数据操作 -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<!-- 自动扫描组件,要把controller去除,他们是在spring-mvc.xml中配置,如果不去除会影响事务管理。 -->
<context:component-scan base-package="cn.mob">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>

<!-- 配置 转换器,对于在basePackage设置的包(包括子包)下的接口类,
如果接口类的全类名在Mapper.xml文件中和定义过命名空间一致,
将被转换成spring的BEAN,在调用
的地方通过@Autowired方式将可以注入接口实例 -->

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
<property name="basePackage" value="cn.mob.jekin.dao" />
</bean>




</beans>
注意:将数据库、用户名、密码修改成个人的数据库。
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>
<!-- 通过别名简化对类的使用 -->
<typeAliases>
<!-- 通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean, 并且默认设置一个别名,默认的名字为非限定类名来作为它的别名。 -->
<package name="cn.mob.jekin.entity" />
</typeAliases>
</configuration>
spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
">
<!-- 配置支持JSON注解 -->
<mvc:annotation-driven></mvc:annotation-driven>

<!-- 扫描所有的controller 但是不扫描service -->
<context:component-scan base-package="cn.mob">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Service" />
</context:component-scan>



</beans>

<mvc:annotation-driven/>相当于注册了DefaultAnnotationHandlerMapping(映射器)和AnnotationMethodHandlerAdapter(适配器)两个bean.即解决了@Controller注解的使用前提配置。 

context:component-scan  对指定的包进行扫描,实现注释驱动Bean定义,同时将bean自动注入容器中使用。即解决了@Controller标识的类的bean的注入和使用。

视图层:/WebRoot/common/common.jspf抽取公共部分
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="proPath" value="${pageContext.request.contextPath}" />
<link rel="stylesheet" type="text/css"
href="${proPath}/jquery-easyui-1.3.5/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="${proPath}/jquery-easyui-1.3.5/themes/icon.css">
<script type="text/javascript" src="${proPath}/jquery-easyui-1.3.5/jquery.min.js"></script>
<script type="text/javascript" src="${proPath}/jquery-easyui-1.3.5/jquery.easyui.min.js"></script>
<script type="text/javascript" src="${proPath}/jquery-easyui-1.3.5/locale/easyui-lang-zh_CN.js"></script>
easyui下载地址:http://www.jeasyui.net/download/如果觉得需要,可以将整个导入。项目中js存放路径/WebRoot/jquery-easyui-1.3.5
登录界面/WebRoot/login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<%@ include file="/common/common.jspf"%>
<title>Login page</title>
</head>
<body>
<div id="loginDiv">
<form id="ff" method="post" action="${proPath}/user/login.action">
<div>
<label for="userName">账号:</label>
<!-- 采用 js验证 -->
<input type="text" name="userName" />
</div>
<div>
<label for="userPass">密码:</label>
<!-- 行内验证
<input class="easyui-validatebox" type="text" name="name"
data-options="required:true,missingMessage:'请填写密码!'" />
-->
<input type="text" name="userPass" />
</div>

</form>
<div style="color:red">${requestScope.msg}</div>
</div>
<script type="text/javascript">
/*
*${选择器}把dom对象转为jquery对象,一般再处理成easyUI对象
*例如 把$("name='userName'")validatebox({})转为easyUI对象
*easyUI对象就可以使用相关的语法进行处理,如:$('selector').plugin('method', parameter);
*/
//这里的大括号相关于写json格式的数据:{属性:值,属性:值}
$("[name='userName']").validatebox({
required : true,
missingMessage : '请填写账号!'
});
$("[name='userPass']").validatebox({
required : true,
missingMessage : '请填写密码!'
});
//禁用验证
$("#ff").form("disableValidation");

//把div的内容作为对话框方式弹出
$('#loginDiv').dialog({
title : '登陆入口',
width : 250,
height : 150,
closed : false,
cache : false,
//设置关闭按钮可见
closable : false,
//模式化窗口.如果为true将锁屏
modal : true,
buttons:[{
text:'登陆',
handler:function(){
alert("可以登陆了");
//启用验证
$("#ff").form("enableValidation");
//进行验证,通过就提交
if($("#ff").form("validate")){
//提交
$("#ff").submit();

}

}
},{
text:'取消',
handler:function(){

}
}]

});

</script>
</body>
</html>
主界面/WebRoot/main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Main</title>
</head>

<body>
登录成功,欢迎您 :${sessionScope.user.userName}
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
这里面主要是spring监听器、servlet的配置,还有编码过滤器。
项目总体代码都在上面,也有注释,如果还不懂自行谷百。最近不知咋啦,CSDN资源总是上传不了,所以上传不了项目代码,后期需要我尽量再试试,也可以加群讨论下载(QQ:583138104)本来还有很多想补充SSM(Spring+SpringMVC+Mybatis)框架整合Demo+详细讲解算了,还没吃饭呢