myBatis系列之六:与SpringMVC集成
前面几篇文章已经讲到了mybatis与spring 的集成。但这个时候,所有的工程还不是web工程,虽然我一直是创建的web 工程。今天将直接用mybatis与Spring mvc 的方式集成起来,源码在本文结尾处下载.主要有以下几个方面的配置:
1.web.xml 配置spring dispatch servlet ,比如为:hbatis
2.hbatis-servlet.xml文件配置
3.spring applicationContext.XML文件配置(与数据库相关,与mybatis sqlSessionFaction 整合,扫描所有mybatis mapper 文件等.)
4.编写controller类
5.编写页面代码
先有个大概映像,整个工程图如下:
一.web.xml配置spring dispatchservlet,比如为:hbatis
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>MyBatisStudy03</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
<!-- 监听容器事件,初始化和关闭Web应用上下文并调用ContextCleanupListener清理资源 -->
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
<!-- Web应用关闭时,清理ServletContext中spring相关的可销毁资源 -->
</listener>
<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>
<servlet>
<servlet-name>hbatis</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/hbatis-servlet.xml</param-value>
</init-param>-->
<!-- 未配置时,SpringMVC会到WEB-INF目录下找${servlet-name}-servlet.xml -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hbatis</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
二.在web.xml同目录下配置hbatis-servlet.xml 文件
这个文件名前面部分必须与你在web.xml里面配置的DispatcherServlet的servlet名字对应,其内容为:
<?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"
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
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 注册RequestMappingHandlerMapping, RequestMappingHandlerAdapter和ExceptionHandlerExceptionResolver以提供对@RequestMapping,@ExceptionHandler等注解的支持 -->
<mvc:annotation-driven />
<!-- 扫描控制器包下有特定注解的类,并实例化和依赖注入 -->
<context:component-scan base-package="com.bijian.study.controller" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!-- FreeMarker视图处理器 -->
<bean id="viewResolverFtl"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
<property name="contentType" value="text/html;charset=utf-8" />
<property name="prefix" value="" />
<property name="cache" value="false" />
<property name="viewNames">
<array>
<value>*.ftl</value>
</array>
</property>
<!--<property name="suffix" value=".ftl"/> -->
<!-- 优先级,数值越小优先级越高 -->
<property name="order" value="0" />
</bean>
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPaths">
<list>
<!-- 模板加载路径 -->
<value>/WEB-INF/ftl/</value>
</list>
</property>
</bean>
</beans>
三.配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- 数据库配置文件 -->
<context:property-placeholder location="classpath:/database.properties" />
<!-- 数据源配置 -->
<!--本示例采用DBCP连接池,应预先把DBCP的jar包复制到工程的lib目录下。 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="${driverClassName}" p:url="${url}" p:username="${user_name}"
p:password="${password}" />
<!-- sqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--dataSource属性指定要用到的连接池 -->
<property name="dataSource" ref="dataSource" />
<!--configLocation属性指定mybatis的核心配置文件 -->
<property name="configLocation" value="classpath:Configuration.xml" />
<!-- 可以在Configuration.xml或此处配置映射文件,但其中不能有相同id的parameterMap, resultMap或sql等 -->
<property name="mapperLocations" value="classpath*:com/bijian/study/model/*.xml" />
</bean>
<!-- 扫描指定包以获取映射器 -->
<bean id="mapperConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bijian.study.dao" />
</bean>
</beans>
类路径下的database.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.235.1:3306/hbatis?characterEncoding=utf8
user_name=bijian
password=123456
注:因为MapperScannerConfigurer可能会导致username取的是系统用户的账号,而造成数据库连接失败,所以改成其它值:user\_name。
四.编写controller层
UserController.java
package com.bijian.study.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.bijian.study.dao.IUserMapper;
import com.bijian.study.model.Article;
@Controller
@RequestMapping("/article")
public class UserController {
@Autowired
private IUserMapper mapper;
@RequestMapping("/list")
public String showAll(ModelMap modelMap) {
List<Article> articles = mapper.getArticlesByUserId(1);
modelMap.addAttribute("articles", articles);
return "main.ftl";
}
@RequestMapping("/list2")
public ModelAndView listall(HttpServletRequest request,
HttpServletResponse response) {
List<Article> articles = mapper.getArticlesByUserId(1);
ModelAndView mav = new ModelAndView("list");
mav.addObject("articles", articles);
return mav;
}
}
五.Configuration.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>
<!-- 别名 -->
<typeAlias alias="User" type="com.bijian.study.model.User"/>
<typeAlias alias="Article" type="com.bijian.study.model.Article"/>
</typeAliases>
<!-- 与spring 集成之后,这些可以完全删除,数据库连接的管理交给 spring 去管理 -->
<!--
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.235.1:3306/hbatis" />
<property name="username" value="bijian" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
-->
<!-- 这里交给sqlSessionFactory 的 mapperLocations属性去得到所有配置信息 -->
<!--
<mappers>
<mapper resource="com/bijian/study/model/User.xml" />
</mappers>
-->
</configuration>
mybatis的Configure.xml配置文件,与上一讲的差不多,唯一不同的就是不用再配置类似如下的: <mapper resource="com/bijian/study/model/User.xml"/> ,所有这些都交给在配置sqlSessionFactory的时候,由<property name="mapperLocations" value="classpath\*:com/bijian/study/model/\*.xml" />去导入了。
六.DAO层
package com.bijian.study.dao;
import java.util.List;
import com.bijian.study.model.Article;
import com.bijian.study.model.User;
public interface IUserMapper {
User getUserById(int id);
List<User> getUsers(String name);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
List<Article> getArticlesByUserId(int id);
}
七.模型及MyBatis配置
User.java
package com.bijian.study.model;
public class User {
private int id;
private String name;
private int age;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
// 如果有带参数的构造器,编译器不会自动生成无参构造器。当查询需要返回对象时,ORM框架用反射来调用对象的无参构造函数,导致异常:java.lang.NoSuchMethodException: com.bijian.study.model.User.<init>()
// 这时需要明确写出:
public User() {
}
public User(int id, String address) {
this.id = id;
this.address = address;
}
public User(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
}
Article.java
package com.bijian.study.model;
public class Article {
private int id;
private User user;
private String title;
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
User.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.bijian.study.dao.IUserMapper">
<select id="getUserById" parameterType="int" resultType="User">
select *
from `user` where id = #{id}
</select>
<resultMap type="User" id="userList"><!-- type为返回列表元素的类全名或别名 -->
<id column="id" property="id" />
<result column="name" property="name" />
<result column="age" property="age" />
<result column="address" property="address" />
</resultMap>
<select id="getUsers" parameterType="string" resultMap="userList"><!-- resultMap为上面定义的User列表 -->
select * from `user` where name like #{name}
</select>
<insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
<!-- useGeneratedKeys指定myBatis使用数据库自动生成的主键,并填充到keyProperty指定的属性上。如果未指定,返回对象拿不到生成的值 -->
insert into user(name,age,address) values(#{name},#{age},#{address})
</insert>
<update id="updateUser" parameterType="User">
update `user` set name=#{name}, age=#{age}, address=#{address}
where id=#{id}
</update>
<delete id="deleteUser" parameterType="int">
delete from `user` where id=#{id}
</delete>
<resultMap type="com.bijian.study.model.Article" id="articleList">
<id column="a_id" property="id" />
<result column="title" property="title" />
<result column="content" property="content" />
<!-- user属性映射到User类 -->
<!--
<association property="user" javaType="User">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="address" property="address" />
</association>
-->
<association property="user" javaType="User" resultMap="userList"/>
</resultMap>
<select id="getArticlesByUserId" parameterType="int" resultMap="articleList">
select u.id, u.name, u.age, u.address, a.id a_id, a.title, a.content
from article a
inner join user u
on a.user_id=u.id and u.id=#{id}
</select>
</mapper>
六.**视图层**
main.ftl
<#list articles as article>
<div>${article.id}. ${article.title}: ${article.content}</div>
</#list>
list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>article list</title>
</head>
<body>
<c:forEach items="${articles}" var="item">
${item.id }--${item.title }--${item.content }<br />
</c:forEach>
</body>
</html>
七.运行测试
启动工程
浏览器输入:http://localhost:8080/MyBatisStudy03/article/list,结果如下:
浏览器输入:http://localhost:8080/MyBatisStudy03/article/list2,结果如下:
PS:在开发过程中,遇到spring MVC整合freemarker抛出java.lang.IllegalAccessError: tried to access method freemarker.ext.servlet.AllHttpScopesHashModel异常,详细异常信息如下:
java.lang.IllegalAccessError: tried to access method freemarker.ext.servlet.AllHttpScopesHashModel.<init>(Lfreemarker/template/ObjectWrapper;Ljavax/servlet/ServletContext;Ljavax/servlet/http/HttpServletRequest;)V from class org.springframework.web.servlet.view.freemarker.FreeMarkerView
at org.springframework.web.servlet.view.freemarker.FreeMarkerView.buildTemplateModel(FreeMarkerView.java:295)
at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:276)
at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233)
at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:267)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1221)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1005)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:952)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
原因是因为fremarker的版本问题,将freemarker-2.3.8.jar改为com.springsource.freemarker-2.3.15.jar后,OK。
参考文章:http://czj4451.iteye.com/blog/1995489
http://www.yihaomen.com/article/java/318.htm
还没有评论,来说两句吧...