Spring+SpringMVc+Mybatis实现数据库查询

 

大家好,本篇博客小 Y 将会给大家带来一篇 SSM 框架实现数据查询的 Demo, 使用的数据库是 Mysql,Server 是 TomCat. 现在的 SSM 整合非常流行,因为 springmvc 的高效和 mybatis 的灵活、高效,给企业开发带来了很大的好处,大大节省了开发成本。好了,啰嗦了这么多,其实就想告诉大家 ssm 框架的优秀之处,那么开门见山,让我们开始本次的博客吧。

本篇博客的目录

1:SSM 框架搭建环境

2:编写数据库 sql, 创建表

3:连接数据库

4:写 java 代码,分层

5:  写 jsp 页面

6:Spring 的配置文件

7:springmvc 的配置文件

8:web.xml 配置

9:部署,实施

10:总结

一:SSM 框架的环境搭建

1:所谓 SSM, 就是 Spring、SpringMVC、mybatis. 首先我们在 myeclipse 中创建一个 java Web 项目,然后在 webRoot 目录下的 lib 目录上添加上我们需要的 jar 包,其中很容易看出我们的 ssm,ps:小 Y 当初找 jar 包也是使出洪荒之力, 博客的尾部会奉上本次 jar 包的链接地址。

2:接下来我们就要创建数据库表了,打开我们的 mysql,创建一个数据库 works, 然后写两张表,一张就是我们的 user 表,另一个是我们的 book 表,也就是我们需要在页面上展示的数据内容。如图,大概是这样一个目录结构(ps: 我用的 Navicat 数据库工具),然后插入必要的数据

CREATE TABLE `tb_book` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(54) default NULL,
  `author` varchar(54) default NULL,
  `publicationdate` varchar(150) default NULL,
  `publication` varchar(54) default NULL,
  `price` double default NULL,
  `image` varchar(54) default NULL,
  `remark` varchar(600) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL auto_increment,
  `loginname` varchar(50) default NULL,
  `PASSWORD` varchar(18) default NULL,
  `username` varchar(18) default NULL,
  `phone` varchar(18) default NULL,
  `address` varchar(255) default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tb_book` VALUES ('1', 'Java 编程思想', 'Bruce Eckel', '2008-10-01', '机械工业出版社', '89.8', 'Thinkinjava.jpg', 'java 经典著作');
INSERT INTO `tb_book` VALUES ('2', '锋利的 jquery', '单东林', '2012-12-08', '人民邮电出版社', '49', 'Fastjquery.jpg', 'juqery 的权威书籍');
INSERT INTO `tb_book` VALUES ('3', '深入 Jvm 虚拟机', '周志明', '2014-12-08', '机械工业出版社', '66', 'inTheJvm.jpg', 'Jvm 方面的专业书籍');
INSERT INTO `tb_book` VALUES ('4', '黑客与画家', 'Paul Graham', '2008-12-08', '人民邮电出版社', '49', 'BlackGuestAndPainter.jpg', '有趣并且很好看的一本书');
INSERT INTO `tb_user` VALUES ('1', 'Yrion', '1234567', '王小贵', '17191182548', '北京市朝阳区');

 

 

 

3:创建好了数据库,接下来我们就需要写数据库配置文件了,proerties 文件,写上我们连接数据库的属性,然后就可以把它托管给 Spring 去帮我们连接 DB 了,其中一定要注意大小写,如果大小写不对 Spring 就无法创建数据源,所以一定要注意大小写 x3 遍!

dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://127.0.0.1:3306/works
dataSource.user=root
dataSource.password=195631
dataSource.maxPoolSize=20
dataSource.maxIdleTime=1000
dataSource.minPoolSize=6
dataSource.initialPoolSize=5

4:写 java 文件,这里我们采用的是 Springmvc 的规范,就是控制层、业务层、数据库层、数据层,这样做的好处就是逻辑清楚,类之间分离,我们写代码也按照这样的逻辑出来的条理很清楚,万一出了错误也很容易排错,包的命名方式也按照这种方式。注意一点,我们为了程序之间的解耦,采用的是面向接口编程,从不以继承的方式去实现代码的复用,因为这样的耦合性太高,不利于扩展。大概的结构图如下:(ps:com.wyq 是我本人的一个命名习惯,千万不要纠结这个),下面我们就来分析一下,各个层的代码:

4.1:首先我们来讲 com.wyq.Bean 层,这个是 Bean 层,也就是数据传输层,是具体的 java 对象,用来映射数据库的字段的,所以其也是很简单的 Pojo

package com.wyq.Bean;

import java.util.Date;

public class Book {

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> id;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String name;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String author;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Date publicationDate;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String publication;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Double price;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String image;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String remark;
  //  省略getter和setter方法

}


package com.wyq.Bean;

public class User{

  private int id;
  private String loginname;
  private String password;
  private String username;
  private String phone;
  private String address;

//省略 getter 和 setter 方法
}

4.2: 接下来看我们的控制层,所谓控制层就是用来控制作用的,就相当于 Servlet,或者 Struts2 中的 Action. 控制层我们起名为 Controller 层,我们来一探 Controller 的代码:

首先使用 @Controller 注解表明这个类用来处理请求,然后 @RequestMapping 中的 value 属性映射具体的请求,forName 在这里就代表着具体的请求,比如待会我们会有一个请求:BookApp/LoginForm, 然后 formName 在这里就代表着 LoginForm,再经过视图解析器解析,就会渲染成 LoginForm.jsp 文件。@PathVariable 代表拿到路径中的变量,就是举的栗子中的 LoginForm

@Controller
public class FormController{
@RequestMapping(value</span>="/{formName}"<span style="color: rgba(0, 0, 0, 1)">)
 </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String loginForm(@PathVariable String formName){
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 动态跳转页面</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> formName;
}

}

Controller
public class BookController {
@Autowired
@Qualifier(</span>"bookService"<span style="color: rgba(0, 0, 0, 1)">)   //这里使用@ualifier注解注入bookService业务层
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> BookService bookService;

@RequestMapping(</span>"/main"<span style="color: rgba(0, 0, 0, 1)">)  //处理main请求
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String main(Model model){
    
    List</span>&lt;Book&gt; books =<span style="color: rgba(0, 0, 0, 1)"> bookService.getAll(); //调用业务层方法
    
    model.addAttribute(</span>"books"<span style="color: rgba(0, 0, 0, 1)">,books);//把从数据库取到的数据放入到model中
    
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "main"<span style="color: rgba(0, 0, 0, 1)">;        
}

}

@Controller
public class UserController {    // 用户控制器
@Autowired
@Qualifier(</span>"userService"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> UserService userService; //注意业务层


@RequestMapping(</span>"/login"<span style="color: rgba(0, 0, 0, 1)">)  //处理login请求
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)">  ModelAndView login(String loginname,String password,ModelAndView mv,HttpSession session){
    
    User user </span>=<span style="color: rgba(0, 0, 0, 1)"> userService.login(loginname, password); //调用业务层方法返回一个实例对象
    
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (user!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {  //判断查到的数据是否为空
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果用户不为空,设在Session域中</span>
        session.setAttribute("user"<span style="color: rgba(0, 0, 0, 1)">, user);
        
        mv.setView(</span><span style="color: rgba(0, 0, 255, 1)">new</span> RedirectView("/BookApp/main"<span style="color: rgba(0, 0, 0, 1)">)); //重定向到main页面中
       
    }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
        
        mv.addObject(</span>"message","登录名或者密码错误,请重新输入"<span style="color: rgba(0, 0, 0, 1)">);
        
        mv.setViewName(</span>"loginForm"<span style="color: rgba(0, 0, 0, 1)">); //重新设置view视图页面
        
        
    }
    
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> mv; //返回视图
}

}

4.3: 接下里就是我们的 Dao 层了,也就是面向数据库的那一层,我们使用的持久层框架是 mybatis, 那么我们完全可以采用注解的方式,把 sql 以注解的方式写在代码上

public interface BookMapper {
@Select(</span>"select * from tb_book"<span style="color: rgba(0, 0, 0, 1)">) //用@Select注解sql语句
List</span>&lt;Book&gt;<span style="color: rgba(0, 0, 0, 1)"> findAll();

}

public interface UserMapper {
@Select(</span>"select * from tb_user where loginname=#{loginname} and password=#{password}"<span style="color: rgba(0, 0, 0, 1)">) //以#{}的方式表示sql中的参数
User finwithLoginnameAndPassword(@Param(</span>"loginname")String loginname,@Param("password"<span style="color: rgba(0, 0, 0, 1)">)String password);//@param表示上面sql中的参数

}

4.4:接下来讲解我们的 service 层,也就是业务层,主要包含一个 Dao 层对象,定义一个业务方法,然后通过 DB 层去数据库查询,这里我们先定义一个接口

public interface BookService {
List</span>&lt;Book&gt;<span style="color: rgba(0, 0, 0, 1)"> getAll();

}

public interface UserService {
User login(String Loginname,String password);

}

4.4.1:定义实现业务层的接口实现类

@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)  // 表示数据库隔离级别为如果当前有就使用当前,如果没有就创建新的事务,
隔离级别为:读已提交,也就是数据在写入的时候是无法被读的,只有提交后才能让其他事务读取,防止数据库发生脏读
@Service(
"bookService") // 表示 service 层 public class BookServiceImpl implements BookService{
@Autowired
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> BookMapper bookMapper; //用AutoWired注入DB层

@Transactional(readOnly</span>=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">) //数据库的读取方式为:只读
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> List&lt;Book&gt;<span style="color: rgba(0, 0, 0, 1)"> getAll() {
    
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> bookMapper.findAll();
}

}

@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)
@Service("userService")
public class UserServiceImpl implements UserService{    // 表示 service 层
@Autowired
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> UserMapper usermapper;

@Transactional(readOnly</span>=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> User login(String loginname, String password) {
    
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> usermapper.finwithLoginnameAndPassword(loginname, password);//调用DB层方法
    
}

}

5:写 jsp 页面,也就是我们需要展示的数据:

 5.1:loginForm.jsp 页面,很简单的一个 form 表单,注意 Action 设置为 login

<body>
    <form action="login" method="post">
        <table>
            <tr>
                <td><label> 登录名 </label></td>
                <td><input type="text" id="loginname" name="loginname"></td>
            </tr>
            <tr>
                <td><label> 密码 </label></td>
                <td><input type="password" id="password" name="password"></td>
            </tr>
            <tr>
                <td><input type="submit" value="登录" /></td>
            </tr>
        </table>
        <font color="red">${requestScope.message}</font>
    </form>
</body>

5.2:main.jsp 页面,主要用了一 c:foreach 进行数据库数据的遍历,注意这里是从 requestScope 中取得数据的

欢迎 ${sessionScope.user.username} 访问:
    <br>
    <table border="1">
        <tr>
            <th> 封面 </th>
            <th> 书名 </th>
            <th> 作者 </th>
            <th> 价格 </th>
        </tr>
        <c:forEach items="${requestScope.books}" var="book">
            <tr>
                <td><img src=images/${book.image} height="60"></td>
                <td>${book.name}</td>
                <td>${book.author}</td>
                <td>${book.price}</td>
            </tr>
        </c:forEach>
    </table>

6:spring 配置文件,之所以要写 Spring 配置文件,是因为我们要把组件交给 Spring 去管理,这其中组件包括数据库次 c3po 连接池、事务管理器等等

 <!-- mybatis:scan 会将 org.fkit.mapper 包里的所有接口当作 mapper 配置,之后可以自动引入 mapper 类-->  
    <mybatis:scan base-package="com.wyq.Mapper" />   
 <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 扫描com.wyq包下面的java文件,有Spring的相关注解的类,则把这些类注册为Spring的bean </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">context:component-scan </span><span style="color: rgba(255, 0, 0, 1)">base-package</span><span style="color: rgba(0, 0, 255, 1)">="com.wyq"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 使用PropertyOverrideConfigurer后处理器加载数据源参数 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">context:property-override </span><span style="color: rgba(255, 0, 0, 1)">location</span><span style="color: rgba(0, 0, 255, 1)">="classpath:db.properties"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 配置c3p0数据源 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">bean </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="dataSource"</span><span style="color: rgba(255, 0, 0, 1)"> class</span><span style="color: rgba(0, 0, 255, 1)">="com.mchange.v2.c3p0.ComboPooledDataSource"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 配置SqlSessionFactory,org.mybatis.spring.SqlSessionFactoryBean是Mybatis社区开发用于整合Spring的bean </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">bean </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="sqlSessionFactory"</span><span style="color: rgba(255, 0, 0, 1)"> class</span><span style="color: rgba(0, 0, 255, 1)">="org.mybatis.spring.SqlSessionFactoryBean"</span><span style="color: rgba(255, 0, 0, 1)">
    p:dataSource-ref</span><span style="color: rgba(0, 0, 255, 1)">="dataSource"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> JDBC事务管理器 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">bean </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="transactionManager"</span><span style="color: rgba(255, 0, 0, 1)"> 
class</span><span style="color: rgba(0, 0, 255, 1)">="org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span style="color: rgba(255, 0, 0, 1)">
     p:dataSource-ref</span><span style="color: rgba(0, 0, 255, 1)">="dataSource"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 启用支持annotation注解方式事务管理 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">tx:annotation-driven </span><span style="color: rgba(255, 0, 0, 1)">transaction-manager</span><span style="color: rgba(0, 0, 255, 1)">="transactionManager"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

</beans>

7:Springmvc 配置文件,这里主要配置的是视图解析器,主要的含义是我们刚才写的代码中的 Controller 返回的字符串渲染成对应的页面,其中包含路径和后缀,指的是具体的格式

<!-- 自动扫描该包,SpringMVC 会将包下用了 @controller 注解的类注册为 Spring 的 controller -->
    <context:component-scan base-package="com.wyq.Controller" />
    <!-- 设置默认配置方案 -->
    <mvc:annotation-driven />
    <!-- 使用默认的 Servlet 来响应静态文件比如 css、html、js 等文件 -->
    <mvc:default-servlet-handler />
    <!-- 视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <!-- 后缀 -->
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

8:配置 web.xml 文件,这其中包含监听器、servlet、过滤器等

<!-- 配置 spring 核心监听器,默认会以 /WEB-INF/applicationContext.xml 作为配置文件 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- contextConfigLocation 参数用来指定 Spring 的配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext*.xml</param-value>
    </context-param>
<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 定义Spring MVC的前端控制器 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>

<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<!-- 让 Spring MVC 的前端控制器拦截所有请求 -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 编码过滤器 -->
<filter>
<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>

 

 9:部署在 Tomcat 服务器上,启动 Tomcat,我们在浏览器上输入:http://localhost:8080/loginForm

我们再来试一下输入错误的登录名和密码,看看会出现什么情况:

10:总结,小 Y 把本篇博文就讲述到这里,为了清晰表达程序的运行步骤,索性我画了个图,这样展示会更加方便。

附本 demo 的下载地址:http://pan.baidu.com/s/1slPloML 密码:px8i