> 文章列表 > MyBatis(六)在WEB中应用MyBatis(使用MVC架构模式)

MyBatis(六)在WEB中应用MyBatis(使用MVC架构模式)

MyBatis(六)在WEB中应用MyBatis(使用MVC架构模式)

目标:

  • 掌握mybatis在web应用中怎么用
  • mybatis三大对象的作用域和生命周期
  • ThreadLocal原理及使用
  • 巩固MVC架构模式
  • 为学习MyBatis的接口代理机制做准备

实现功能:

使用技术:

  • HTML + Servlet + MyBatis

WEB应用的名称:

  • bank

一、需求描述

二、数据库表的设计和准备数据

三、实现步骤

第1步、环境搭建

①、IDEA中创建Maven WEB应用(mybatis-004-web

 

②换成下面的代码(换个版本高一点的tomcat)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true">
</web-app>

③、pom。xml文件添加依赖(mybatis依赖、mysql驱动依赖、logback依赖、servlet依赖)

<dependencies><!--mybatis依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><!--mysql驱动依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><!--logback依赖--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency><!--servlet依赖--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency></dependencies>

④、IDEA配置Tomcat

⑤、引入相关配置文件,放到resources目录下(全部放到类的根路径下)

  • mybatis-config.xml
  • AccountMapper.xml
  • logback.xml
  • jdbc.properties

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="jdbc.properties"/><environments default="dev"><environment id="dev"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><!--一定要注意这里的路径哦!!!--><mapper resource="AccountMapper.xml"/></mappers>
</configuration>

AccountMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="account"></mapper>

logback.xml

<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"><!-- 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!--mybatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR --><root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/powernode
jdbc.username=root
jdbc.password=root

第2步、前端页面index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>银行账户转账</title>
</head>
<body>
<!--/bank是应用的根,部署web应用到tomcat的时候一定要注意这个名字-->
<form action="/bank/transfer" method="post">转出账户:<input type="text" name="fromActno"/><br>转入账户:<input type="text" name="toActno"/><br>转账金额:<input type="text" name="money"/><br><input type="submit" value="转账"/>
</form>
</body>
</html>

第3步、创建pojo包、service包、dao包、web包、utils包

第4步、定义pojo类:Accoun

package com.powernode.bank.pojo;/*** @author wuw* @since 2023-04-03 13:42:16*/
public class Account {private Long id;private String actno;private Double balance;@Overridepublic String toString() {return "Account{" +"id=" + id +", actno='" + actno + '\\'' +", balance=" + balance +'}';}public Account() {}public Account(Long id, String actno, Double balance) {this.id = id;this.actno = actno;this.balance = balance;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getActno() {return actno;}public void setActno(String actno) {this.actno = actno;}public Double getBalance() {return balance;}public void setBalance(Double balance) {this.balance = balance;}
}

第5步、将之前的工具类复制到 utils包下

utils工具类代码:

package com.powernode.bank.utils;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;/*** @author wuw* @since 2023-04-03 13:55:57*/
public class SqlSessionUtil {private static SqlSessionFactory sqlSessionFactory;/*** 类加载时初始化sqlSessionFactory对象*/static {try {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));} catch (Exception e) {e.printStackTrace();}}/*** 每调用一次openSession()可获取一个新的会话,该会话支持自动提交。** @return 新的会话对象*/public static SqlSession openSession() {return sqlSessionFactory.openSession(true);}
}

第6步、:编写AccountDao接口,以及AccountDaoImpl实现类

分析dao中至少要提供几个方法,才能完成转账:

  • 转账前需要查询余额是否充足:selectByActno
  • 转账时要更新账户:update
import com.powernode.bank.pojo.Account;/*** @author wuw* @since 2023-04-03 14:10:30*/
public interface AccountDao {/*** 根据账号获取账户信息* @param actno 账号* @return 账户信息*/Account selectByActno(String actno);/*** 更新账户信息* @param act 账户信息* @return 1表示更新成功,其他值表示失败*/int update(Account act);
}
import com.powernode.bank.pojo.Account;
import com.powernode.bank.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;/*** @author wuw* @since 2023-04-03 14:12:22*/
public class AccountDaoImpl implements AccountDao {@Overridepublic Account selectByActno(String actno) {SqlSession sqlSession = SqlSessionUtil.openSession();Account act = (Account)sqlSession.selectOne("selectByActno", actno);sqlSession.close();return act;}@Overridepublic int update(Account act) {SqlSession sqlSession = SqlSessionUtil.openSession();int count = sqlSession.update("update", act);sqlSession.commit();sqlSession.close();return count;}
}

第7步、AccountDaoImpl中编写了mybatis代码,需要编写SQL映射文件了

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="account"><select id="selectByActno" resultType="com.powernode.bank.pojo.Account">select * from t_act where actno = #{actno}</select><update id="update">update t_act set balance = #{balance} where actno = #{actno}</update>
</mapper>

第8步、编写AccountService接口以及AccountServiceImpl

package com.powernode.bank.exception;/*** @author wuw* @since 2023-04-03 14:48:25* 余额不足异常*/
public class MoneyNotEnoughException extends Exception{public MoneyNotEnoughException(){}public MoneyNotEnoughException(String msg){ super(msg); }
}
package com.powernode.bank.exception;/*** @author wuw* @since 2023-04-03 14:49:44*/
public class AppException extends Exception{public AppException(){}public AppException(String msg){ super(msg); }
}
package com.powernode.bank.service;import com.powernode.bank.exception.AppException;
import com.powernode.bank.exception.MoneyNotEnoughException;/*** @author wuw* @since 2023-04-03 14:50:54*/
public interface AccountService {/*** 银行账户转正* @param fromActno 转出账户* @param toActno 转入账户* @param money 转账金额* @throws MoneyNotEnoughException 余额不足异常* @throws AppException App发生异常*/void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException;
}
package com.powernode.bank.service.imp;import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.dao.imp.AccountDaoImpl;
import com.powernode.bank.exception.AppException;
import com.powernode.bank.exception.MoneyNotEnoughException;
import com.powernode.bank.pojo.Account;
import com.powernode.bank.service.AccountService;/*** @author wuw* @since 2023-04-03 14:51:55*/
public class AccountServiceImpl implements AccountService {private AccountDao accountDao = new AccountDaoImpl();@Overridepublic void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException {// 查询转出账户的余额Account fromAct = accountDao.selectByActno(fromActno);if (fromAct.getBalance() < money) {throw new MoneyNotEnoughException("对不起,您的余额不足。");}try {// 程序如果执行到这里说明余额充足// 修改账户余额Account toAct = accountDao.selectByActno(toActno);fromAct.setBalance(fromAct.getBalance() - money);toAct.setBalance(toAct.getBalance() + money);// 更新数据库accountDao.update(fromAct);accountDao.update(toAct);} catch (Exception e) {throw new AppException("转账失败,未知原因!");}}
}

第9步、编写AccountController

package com.powernode.bank.web;import com.powernode.bank.exception.AppException;
import com.powernode.bank.exception.MoneyNotEnoughException;
import com.powernode.bank.service.AccountService;
import com.powernode.bank.service.imp.AccountServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @author wuw* @since 2023-04-03 14:04:15*/
@WebServlet("/transfer")
public class AccountController extends HttpServlet {private AccountService accountService = new AccountServiceImpl();@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获取响应流response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();// 获取账户信息String fromActno = request.getParameter("fromActno");String toActno = request.getParameter("toActno");double money = Integer.parseInt(request.getParameter("money"));// 调用业务方法完成转账try {accountService.transfer(fromActno, toActno, money);out.print("<h1>转账成功!!!</h1>");} catch (MoneyNotEnoughException e) {out.print(e.getMessage());} catch (AppException e) {out.print(e.getMessage());}}
}

运行、