问题?SSM(springmvc+spring+mybatis)整合过程
一、SSM框架比较S2SH框架的优缺点比较
站在个人使用这两个框架的观点儿上来说的话,我觉得这个不能定死的说,常用的S2SH,SpringMVC等,还可以考虑jFinal。
首先说S2SH,这个是用的比较多的,特别是在中小型项目中,针对大型项目就不行了,是Struts和hibernate过于庞大,过于重量级,项目大了之后配置文件多的也是麻烦事,配置文件多了之后一方面不好操作,另外比较蛋疼的是没法断点调试,特别是对底层数据库优化就做不到了。
至于SpringMVC.这个相对于S2SH来说比较轻量级的框架,数据库操作层可以选择ibatis(被Google收购后就叫MyBatis了,开源的),统一管理sql甚是方便,采用纯注解更好,所以在这点儿上来说优于S2SH,可以对数据库进行优化。
再说jFinal,这个是刚出来不就得新框架,个人觉得是个很逆天的框架,零xml文件(有个数据库配置的txt文件)所有东西启动需要加载的都在java类里面(****Config.java)调试神马的就太方便了以至于你能在启动的时候就调试(比如加载数据源开始),特别的轻量级
很好用。
二、整合过程
看看整个流程结构图:
1. 创建表(包括关联关系—这个关联关系不一定要有,只是列名要有,并且和关联表列名相同)
2. 创建PO实体对象
3. 创建mapper映射文件
4. 创建personDao接口及实现类
5. 创建service接口及实现类
6. 创建controller
7. 创建列表页面jsp
8. 配置sqlMapConfig.xml
9. 配置beans.xml
10. 配置springmvc-servlet.xml
11. 配置web.xml
12. 发布并测试
当然整个顺序是可以改变的,只要逻辑没问题即可:
具体实现:
1. 创建表,web工程,导入jar包
(包括关联关系—这个关联关系不一定要有,只是列名要有,并且和关联表列名相同)
user表
book表
新建名为SSM的web工程:
导入jar包,(mybatis包及依赖,spring(springmvc包及依赖包),数据库驱动包)
aopalliance-1.0.jar
asm-3.3.1.jar
cglib-2.2.2.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
commons-lang3-3.1.jar
commons-logging-1.1.1.jar
ehcache-core-2.6.5.jar
freemarker-2.3.19.jar
javassist-3.11.0.GA.jar
junit-4.9.jar
log4j-1.2.16.jar
mybatis-3.2.2.jar
mybatis-ehcache-1.0.2.jar
mybatis-spring-1.2.0.jar
mysql-connector-java-5.1.10-bin.jar
ognl-3.0.6.jar
slf4j-api-1.6.2.jar
slf4j-log4j12-1.6.2.jar
spring-aop-3.2.2.jar
spring-beans-3.2.2.jar
spring-context-3.2.2.jar
spring-core-3.2.2.jar
spring-expression-3.2.2.jar
spring-jdbc-3.2.2.jar
spring-orm-3.2.2.jar
spring-tx-3.2.2.jar
spring-web-3.2.2.jar
spring-webmvc-3.2.2.jar
jar包在下载页中有,注意(struts的三个包是不要的)
2. 创建PO实体对象
这里建得User实体类:
<span style="font-family:Microsoft YaHei;font-weight: normal;">package com.itcast.ssm.domain;
import java.io.Serializable;
import java.util.List;
public class User implements Serializable {
private List<Book> books;//一对多的体现
private Integer id;
private String username;
private String password;
private Integer age;
private String remark;
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password="
+ password + ", age=" + age + ", remark=" + remark + "]";
}
}
</span>
Book实体类:
<span style="font-family:Microsoft YaHei;font-weight: normal;">package com.itcast.ssm.domain; import java.io.Serializable; public class Book implements Serializable{ private Integer id; private String book_name; private Double book_money; //不配双向关联的 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBook_name() { return book_name; } public void setBook_name(String book_name) { this.book_name = book_name; } public Double getBook_money() { return book_money; } public void setBook_money(Double book_money) { this.book_money = book_money; } @Override public String toString() { return "Book [id=" + id + ", book_name=" + book_name + ", book_money=" + book_money + "]"; } }</span>
3. 创建mapper映射文件(在src下),及mapper接口
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="com.itcast.ssm.mapper.UserMapper"> <resultMap type="com.itcast.ssm.domain.User" id="UserRM"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="age" column="age"/> <result property="remark" column="remark"/> </resultMap> <resultMap type="com.itcast.ssm.domain.User" id="bookRm" extends="UserRM"> <collection property="books" ofType="com.itcast.ssm.domain.Book"> <id property="id" column="book_id"/> <result property="book_name" column="book_name"/> <result property="book_money" column="book_money"/> </collection> </resultMap> <!-- 带条件的查询 --> <select id="find" parameterType="map" resultMap="UserRM"> select * from user where 1=1 <if test="name!=null">and username like #{name}</if> <if test="ageStart!=null">and age>=#{ageStart}</if> <if test="ageEnd!=null"><![CDATA[and age<=]]>#{ageStart}</if> </select> <!-- 插入 --> <insert id="insert" parameterType="com.itcast.ssm.domain.User" > insert into user (username,password,age,remark) values( #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, #{remark,jdbcType=VARCHAR} ) </insert> <!-- 联合查询 --> <select id="findBook" parameterType="int" resultMap="bookRm"> select p.id,p.username,p.password,p.age,p.remark, b.id as book_id,b.book_name,b.book_money from (select * from user where id=#{id}) p left join (select * from book where userid=#{id}) b on p.id=b.userid </select> </mapper>
UserMapper.java(接口),这个的命名规则是在mapper.xml文件中namespace="com.itcast.ssm.mapper.UserMapper",包下面的接口,和mapper.xml放在一起
package com.itcast.ssm.mapper; import java.util.List; import java.util.Map; import com.itcast.ssm.domain.User; public interface UserMapper { public List<User> find(Map map); public void insert(User user); public User findBook(Integer id); }
4. 创建UserDao接口及实现类
UserDao接口:
package com.itcast.ssm.dao; import java.util.List; import java.util.Map; import com.itcast.ssm.domain.User; public interface UserDao { public List<User> findUser(Map map); public boolean addUser(User user); public User findBook(Integer id); }
UserDaoImpl.java:这个是关键*********,和hibernate一样使用继承的方式将spring中的注入的数据源拿到。
package com.itcast.ssm.dao.Imple; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.support.SqlSessionDaoSupport; import org.springframework.stereotype.Repository; import com.itcast.ssm.dao.UserDao; import com.itcast.ssm.domain.User; import com.itcast.ssm.mapper.UserMapper; @Repository public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{ /** * mybatis3.0.0+mybatis-spring1.0.0无需自己注入,底层给你注入 * mybatis3.2.2+mybatis-spring1.2.0去除了这个,需要自己注入sqlsessionFactory * */ /*super.setSqlSessionFactory(sessionFactory):调用父类方法,将sqlsessionfactory注入进去*/ @Resource public void setSessionFactory(SqlSessionFactory sqlSessionFactory) { super.setSqlSessionFactory(sqlSessionFactory); } /* (non-Javadoc) * @see com.itcast.ssm.dao.Imple.UserDao#findUser(java.util.Map) */ public List<User> findUser(Map map){ UserMapper userMapper = this.getSqlSession().getMapper(UserMapper.class); /*Map map = new HashMap(); map.put("name", "李军"); map.put("ageStart", 8); map.put("ageEnd", 30);*/ List<User> users = userMapper.find(map); for(User user:users){ System.out.println(user.toString()); } System.out.println("--INTO FINDUSER METHOD!!!--"); return users; } public boolean addUser(User user) { // TODO Auto-generated method stub UserMapper mapper = this.getSqlSession().getMapper(UserMapper.class); mapper.insert(user); System.out.println("--INTO ADDUSER METHOD!!!--"); return true; } public User findBook(Integer id) { // TODO Auto-generated method stub UserMapper userMapper = this.getSqlSession().getMapper(UserMapper.class); System.out.println("--INTO FINDBOOK DAO METHOD!!!--"); return userMapper.findBook(id); } }
5. 创建service接口及实现类
UserService.java
package com.itcast.ssm.service; import java.util.List; import java.util.Map; import com.itcast.ssm.domain.User; public interface UserService { public List<User> findUser(Map map); public boolean addUser(User user); public User findBook(Integer id); }
UserServiceImpl.java:这个和s2sh中的service一样,注解加注入即可
package com.itcast.ssm.service.Impl; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.springframework.stereotype.Service; import com.itcast.ssm.dao.UserDao; import com.itcast.ssm.domain.User; import com.itcast.ssm.service.UserService; @Service public class UserServiceImpl implements UserService{ @Resource private UserDao dao; public List<User> findUser(Map map) { // TODO Auto-generated method stub return this.dao.findUser(map); } public boolean addUser(User user) { // TODO Auto-generated method stub return this.dao.addUser(user); } public User findBook(Integer id) { // TODO Auto-generated method stub return this.dao.findBook(id); } }
6. 创建controller:这个就和s2sh的action层逻辑控制层作用一样了,不过这里使用的是springmvc的架构,而不是struts2.
<span style="font-weight: normal;"><span style="font-family:Microsoft YaHei;font-size:18px;">package com.itcast.ssm.controller;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.itcast.ssm.domain.User;
import com.itcast.ssm.service.UserService;
@Controller
public class UserController {
@Resource
private UserService userService;
//controller在加载的时候,会同时创建/user/list;/user/list.action
//所以无论加不加.action都可以访问得到和web.xml中配置的.action无关
@RequestMapping("/user/list.action")
public String userList(Model model){
List<User> list =this.userService.findUser(null);
for(User user:list){
System.out.println(user.toString());
}
model.addAttribute("userlist", list);
return "/user/userlist.jsp";
}
@RequestMapping("/user/toadd.action")
public String tocreat(){
return "/user/addUser.jsp";
}
@RequestMapping("/user/add.action")
public String addUser(User user){
System.out.println(user.toString());
this.userService.addUser(user);
System.out.println("--INTO ADDUSER METHOD END!!!--");
return "redirect:/user/list.action";
}
@RequestMapping("/user/tobook.action")
public String toBook(Integer id,Model model){
User user = this.userService.findBook(id);
model.addAttribute("booklist", user);
return "/user/listBook.jsp";
}
}</span></span><span style="font-family:Microsoft YaHei;font-size: 13.3333px;">
</span>
到这里为止,类部分已经配置完。
7. 创建页面jsp
userlist.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <% 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>My JSP 'userlist.jsp' starting page</title> </head> <body> <a href="${pageContext.request.contextPath }/user/toadd.action">添加</a> <table> <tr> <td>Status:</td> <td>ID:</td> <td>USER:</td> <td>PASS:</td> <td>AGE:</td> <td>REMARK:</td> </tr> <c:forEach items="${userlist }" var="v" varStatus="status"> <tr> <td>${status.index+1 }</td> <td>${v.id }</td> <td><a href="${pageContext.request.contextPath }/user/tobook.action?id=${v.id}">${v.username }</a></td> <td>${v.password }</td> <td>${v.age }</td> <td>${v.remark }</td> </tr> </c:forEach> </table> </body> </html>
addUser.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>My JSP 'addUser.jsp' starting page</title> <script type="text/javascript"> function formSubmit(){ document.forms[0].action = "${pageContext.request.contextPath }/user/add.action"; document.forms[0].submit(); } </script> </head> <body> <a href="#" onclick="formSubmit();">保存</a><!-- 两种提交方式都可以,这里只是掩饰多一种方式提交 --> <form action="${pageContext.request.contextPath }/user/add.action" method="post"> <table> <tr> <td>User:</td> <td><input type="text" name="username" /></td> </tr> <tr> <td>Pass:</td> <td><input type="text" name="password"/></td> </tr> <tr> <td>Age:</td> <td><input type="text" name="age"/></td> </tr> <tr> <td>Remark:</td> <td><input type="text" name="remark"/></td> </tr> <tr> <td><input type="submit" value="提交"></td> <td><input type="reset" value="重置"></td> </tr> </table> </form> </body> </html>
listBook.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <% 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>${booklist.username }的书籍列表</title> </head> <body> <h2>${booklist.username }的书籍列表:<a href="${pageContext.request.contextPath }/user/list.action">返回</a></h2> <table> <tr> <td>列表序号:</td> <td>书籍序号:</td> <td>书籍名称:</td> <td>书籍金额:</td> </tr> <c:forEach items="${booklist.books }" var="p" varStatus="status"> <tr> <td>${status.index+1 }</td> <td>${p.id}</td> <td>${p.book_name}</td> <td>${p.book_money}</td> </tr> </c:forEach> </table> </body> </html>
8. 配置sqlMapConfig.xml
sqlMapConfig.xml:名字不能乱写,这个在mybatis的时候配置得多,主要是配置数据源的,有点儿和hibernate的配置文件相同加载数据源,及映射文件的,但是在这里交给spring容器管理了。所以配置也是空,但是需要配置这个文件。
<?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> </configuration>
9. 配置beans.xml:这个就是配置spring容器,唯一不同的是将mapper文件和sqlMapConfig.xml加载进来
将jdbc.properties文件放入src下,里面放的驱动信息
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-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/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <!-- 包扫描,spring管理dao、service层 --> <context:component-scan base-package="com.itcast.ssm.dao,com.itcast.ssm.service"></context:component-scan> <!-- JDBC.properties属性配置文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 数据源DataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverclass}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- sqlSessionFactory :id名字不是乱写的,要注入用的--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!-- spring和mybatis整合 --> <!-- 1)引入mybatis核心配置文件 --> <property name="configLocation" value="classpath:sqlMapConfig.xml"/> <!-- 2)扫描指定目录下的所有Mapper.xml --> <property name="mapperLocations" value="classpath:com/itcast/ssm/mapper/*.xml"></property> </bean> <!-- 事务 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 通知 --> <tx:advice id="tbAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="find*" read-only="true"/> <tx:method name="get*" read-only="true"/> <tx:method name="view*" read-only="true"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 切点 --> <aop:config> <aop:pointcut expression="execution(* com.itcast.ssm.service.*.*(..))" id="pointCut"/> <aop:advisor advice-ref="tbAdvice" pointcut-ref="pointCut"/> </aop:config> </beans>
10. 配置springmvc-servlet.xml
注意:这个是springmvc中的核心文件,主要作用struts2一样的,handlMapping来控制映射转向
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd "> <!-- 1.包扫描controller --> <context:component-scan base-package="com.itcast.ssm.controller"></context:component-scan> <!-- 2.内部资源视图解析器 --> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages"/> <property name="suffix" value=""/> </bean> </beans>
11. 配置web.xml
需要配置spring容器,springmvc,这两个是必要的。
<?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"> <!-- 1.spring容器 listener --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 2.springmvc servlet --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> <!-- 3.spring 中文乱码 filter --> <!-- 编码过滤器,解决中文乱码 --> <filter> <filter-name>SpringEncoding</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>SpringEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
最后加一个log4j的日志文件,需要打印日志,当然加不加都无所谓,只是加了打印日志更清晰,在jar包中也有log4j.jar包
src下加log4j.properties
12. 发布并测试
添加
查看用户的书籍
整个搭建过程完成,并且测试成功。
三、细节重要点
细节都在其中写着的,不懂的看我相关博客
http://blog.csdn.net/mr_li13/article/details/51335624
http://blog.csdn.net/mr_li13/article/details/51351959
http://blog.csdn.net/mr_li13/article/details/51375098
http://blog.csdn.net/mr_li13/article/details/51394404
案例及相关jar下载地址:点击打开下载链接