银行转账案例

[1] 案例需求

用户访问登录页面,在页面中输入用户名和密码点击登录,登录成功后 进入到主页中。如果登录败,则在登录页面中提示用户用户名或密码错误。在主页面中,用户在填写银行转账信息,包括:转账账户,转账账 户密码,转账金额,收款账号,收款人姓名。点击开始转账,完成转账。但是有如下特殊需求:
① 需要用户的登录日志。
② 当转账账户的密码失去焦点时,检验转账账户信息是否存在。
③在转账金额失去焦点时,校验金额是否正确。
④ 收款人姓名失去焦点时,校验收款人信息是否正确
⑤ 当所有的信息验证无误后,才能转账。

[2] 案例页面效果图

① 登录页面效果图
在这里插入图片描述

② 转账主页面效果图
在这里插入图片描述

[3] 功能分析

① 创建登录页面
② 用户登录以及登录失败提示语
③ 登录日志
④ 创建银行转账页面
⑤ 转账账户信息校验
⑥ 金额校验
⑦ 入账账户信息校验
⑧ 转账功能

[4] 数据库设计

① 用户信息表: t_user

字段名 中文名 类型 大小 约束
uid 用户编号 int 10 主键、非空
uname 用户名 varchar 100 非空
pwd 密码 varchar 100 非空

② 银行账户信息表:t_account

字段名 中文名 类型 大小 约束
aid 账户编号 int 10 主键、非空
apwd 支付密码 varchar 100 非空
money 账户金额 double
uid 用户编号 int 10 非空

[5] 功能实现

1. 完成数据库的变现

-- ----------------------------
-- Table structure for `t_account`
-- ----------------------------
DROP TABLE IF EXISTS `t_account`;
CREATE TABLE `t_account` (`aid` int(10) NOT NULL AUTO_INCREMENT,`apwd` varchar(100) NOT NULL,`money` double DEFAULT NULL,`uid` int(10) NOT NULL,PRIMARY KEY (`aid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of t_account
-- ----------------------------
INSERT INTO `t_account` VALUES ('1', '123', '10000', '1');
INSERT INTO `t_account` VALUES ('2', '456', '10000', '2');-- ----------------------------
-- Table structure for `t_user`
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (`uid` int(10) NOT NULL AUTO_INCREMENT,`uname` varchar(100) NOT NULL,`pwd` varchar(100) NOT NULL,PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES ('1', '张三', '123');
INSERT INTO `t_user` VALUES ('2', '李四', '456');

2. 搭建Spring+Mybatis项目开发的环境

(1) 创建web项目
(2) 在web-inf下创建lib文件夹,并导入整合的jar包
(3) 在src创建MVC的包结构
注意:将表的实体类文件创建
(4) 在src下创建spring的配置文件
(5) 在web.xml文件中配置Spring文件路径和监听器

3. 创建登录页面

效果图:
在这里插入图片描述

代码示例:

<%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><base href="<%=basePath %>"/><title>Title</title>
</head>
<body><h3 align="center">欢迎登录502班级银行转账系统</h3><hr><div style="width: 400px;margin: auto"><form action="userLogin" method="post"><table style="margin: auto;margin-top: 30px;" cellpadding="10px"><tr><td>用户名:</td><td><input type="text" name="uname" value=""></td></tr><tr><td>密码:</td><td><input type="password" name="pwd" value=""></td></tr><tr><td colspan="2"><input type="submit" value="点击登录"></td></tr></table></form></div>
</body>
</html>

4. 完成登录功能

(1) 创建UserServlet,处理登录请求
package com.java.controller;
import com.java.pojo.User;
import com.java.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
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 javax.servlet.http.HttpSession;
import java.io.IOException;@WebServlet(value = "/userLogin",loadOnStartup = 1)
public class UserServlet extends HttpServlet {//声明init方法,完成Spring资源的初始化加载private UserService us;@Overridepublic void init() throws ServletException {//获取Spring容器对象ApplicationContext ac= WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());//获取业务层对象us= (UserService) ac.getBean("us");}//声明service方法,完成请求的处理@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置请求编码格式req.setCharacterEncoding("utf-8");//设置响应编码格式resp.setContentType("text/html;charset=utf-8");resp.setCharacterEncoding("utf-8");//获取请求信息String uname=req.getParameter("uname");String pwd=req.getParameter("pwd");//处理请求//调用业务层方法根据用户名和密码获取用户信息User user = us.userLoginService(uname, pwd);//响应处理结果//获取Session对象HttpSession session=req.getSession();//响应if(user!=null){//将用户信息存储到session中session.setAttribute("user",user);//重定向到主页面resp.sendRedirect(req.getContextPath()+"/main.jsp");}else{//增加失败标记session.setAttribute("flag","userFail");//重定向到登录页面resp.sendRedirect(req.getContextPath()+"/login.jsp");}}
}
(2) 创建UserService,处理登录请求
package com.java.service.impl;
import com.java.mapper.UserMapper;
import com.java.pojo.User;
import com.java.service.UserService;
public class UserServiceImpl implements UserService {//声明mapper层属性private UserMapper userMapper;public UserMapper getUserMapper() {return userMapper;}public void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;}//用户登录@Overridepublic User userLoginService(String uname, String pwd) {return userMapper.userLoginMapper(uname,pwd);}
}
(3) 创建UserMapper,根据用户名和密码获取用户信息
package com.java.mapper;
import com.java.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {//根据用户名和密码获取用户信息@Select("select * from t_user where uname=#{uname} and pwd=#{pwd}")User userLoginMapper(@Param("uname") String uname, @Param("pwd") String pwd);
}
(4) 在applicationcontext.xml文件中配置业务层bean
<!--配置业务层bean--><bean id="us" class="com.bjsxt.service.impl.UserServiceImpl"><property name="userMapper" ref="userMapper"></property></bean>
5. 创建main.jsp主页面

① 页面示例图:
在这里插入图片描述

② 代码示例:

<%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><base href="<%=basePath %>"/><title>Title</title><%--引入jquery文件--%><script type="text/javascript" src="js/j.js"></script><%--声明js代码域--%><script type="text/javascript">//声明页面加载事件$(function () {//创建颜色数组var colors=["red","yellow","black","green","gray","blue","brown","darhorchid"];//使用间隔执行window.setInterval(function () {//获取0-8的随机整数,含0不含8var index=Math.floor(Math.random()*colors.length);//设置标题颜色$("#title").css("color",colors[index]);},100)})</script>
</head>
<body><%--网页的主题--%><h3 align="center"><%--跑马灯效果--%><marquee width=400 behavior=alternate direction=left align=middle><font color="r" id="title">欢迎${sessionScope.user.uname}登录502班级银行转账系统</font></marquee></h3><%--水平线--%><hr><%--银行转账表单--%><div style="width: 400px;margin: auto;"><form action=""><table style="margin: auto;margin-top: 30px;" cellpadding="10px"><tr><td>转账账户:</td><td><input type="text" name="outId" value=""></td></tr><tr><td>转账账户密码:</td><td><input type="password" name="outPwd" value=""></td></tr><tr><td>金额:</td><td><input type="text" name="money" value=""></td></tr><tr><td>收款账号:</td><td><input type="text" name="inId" value=""></td></tr><tr><td>收款人姓名:</td><td><input type="text" name="inName" value=""></td></tr><tr><td colspan="2"><input type="submit" value="开始转账"></td></tr></table></form></div>
</body>
</html>
6. 完成转账账户信息的校验

(1) 功能点需求:

用户在输入账户以及密码后,在密码失去焦点后,触发校验。如果正确则在密码框 后显示√,错误则显示X.

(2) 功能点分析:

通过需求我们发现,校验的结果是在当前页面中继续显示的。相当于我们在当前 页面中显示新的响应结果 ,确定该功能使用ajax技术来实现。

(3) 前台分析:

① ajax请求的触发时机:在密码框失去焦点时触发
② ajax请求的请求地址: Servlet的别名,checkAccount
③ ajax请求的请求数据:账户和密码
④ ajax请求的响应数据:true或者false的字符串

(4) 前台代码实现:

//给密码框添加焦点事件,完成校验
$(function () {$("#outdPwd").blur(function () {//发起ajax请求$.post("checkAccount",{outId:$("#outId").val(),outPwd:$("#outdPwd").val(),methodName=”checkOutInfo”},function (data) {if(eval(data)){$("#outSpan").html("√").css("color","green");}else{$("#outSpan").html("X").css("color","red");}})})
})

(5) 后台分析:

① 创建Servlet,处理转账账户信息校验。checkAccount 注意:有,响应”true”,没有,响应”false”
② 创建Service,处理账户信息校验。
③ 创建mapper,根据账户ID和密码获取账户信息。

(6) 后台代码实现:

CheckAccountServlet

    //声明方法:校验转账账户信息private void checkOutInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//获取请求信息String outId=req.getParameter("outId");String outPwd=req.getParameter("outPwd");//处理请求//调用业务层方法Account account = checkAccountService.checkOutAccountInfoService(outId, outPwd);//响应结果resp.getWriter().write(account!=null?"true":"false");}

CheckAccountService

    //校验转账账户信息Account checkOutAccountInfoService(String outId,String outPwd);

CheckAccountServiceImpl

    //校验转账账户信息@Overridepublic Account checkOutAccountInfoService(String outId, String outPwd) {return checkAccountMapper.checkAccountOutInfoMapper(outId,outPwd);}

CheckAccountMapper

    //校验转账账户信息:根据账户ID和密码获取账户信息@Select("select * from t_account where aid=#{outId} and apwd=#{outPwd}")Account checkAccountOutInfoMapper(@Param("outId") String outId, @Param("outPwd") String outPwd);
7. Servlet的优化

(1) 问题:

目前我们每实现一个功能点,就需要在后台声明一个对应的Servlet进行 请求的处理。这样造成Servlet声明过多,代码繁琐。

(2) 解决:

Servlet只声明一个,让所有的相关请求,都请求该Servlet。 在该Servlet中的service方法中,不做具体的请求处理。在Service中,根据请求,调用对应的逻辑代码来处理请求即可。 类似:main方法的机制。

(3) 实现:

在Servlet中将不同请求的处理逻辑代码封装成对应的逻辑功能方法 然后在service方法中,根据请求调用对应的逻辑方法处理请求。每次请求都需要在请求数据中携带要请求的方法的方法名。后台service中 根据请求数据中的方法名调用对应的逻辑方法即可。

package com.java.controller;
import com.java.pojo.Account;
import com.java.service.CheckAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
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;
@WebServlet(value = "/checkAccount",loadOnStartup = 2)
public class CheckAccountServlet extends HttpServlet {//声明业务层属性private CheckAccountService checkAccountService;//重写init方法@Overridepublic void init() throws ServletException {//获取Spring容器对象ApplicationContext ac=new ClassPathXmlApplicationContext("applicationcontext.xml");//获取业务层对象checkAccountService= (CheckAccountService) ac.getBean("checkAccountService");}//重写service方法@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置请求编码格式req.setCharacterEncoding("utf-8");//设置响应编码格式resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");//获取请求数据中的方法名String methodName=req.getParameter("methodName");//根据请求调用对应的逻辑代码if("checkOutInfo".equals(methodName)){checkOutInfo(req,resp);}else if("checkMoneyInfo".equals(methodName)){checkMoneyInfo(req,resp);}else if("checInInfo".equals(methodName)){checInInfo(req,resp);}else if("transferInfo".equals(methodName)){transferInfo(req,resp);}else{System.out.println("没有对应的逻辑方法:"+methodName);}}//转账private void transferInfo(HttpServletRequest req, HttpServletResponse resp) {}//校验收款人信息private void checInInfo(HttpServletRequest req, HttpServletResponse resp) {}//校验金额private void checkMoneyInfo(HttpServletRequest req, HttpServletResponse resp) {}//声明方法:校验转账账户信息private void checkOutInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//获取请求信息String outId=req.getParameter("outId");String outPwd=req.getParameter("outPwd");//处理请求//调用业务层方法Account account = checkAccountService.checkOutAccountInfoService(outId, outPwd);//响应结果resp.getWriter().write(account!=null?"true":"false");}}
8. 校验金额

(1) 功能点需求:

用户在金额框中输入要转账的金额信息后,失去焦点时,完成金额信息的校验。 余额足够则在金额框后显示√,否则显示X

(2) 功能分析:

使用ajax技术。

① 前台分析

i. 给金额框增加焦点事件
ii. 发起ajax请求
iii. 请求数据为金额,转账账户Id,后台逻辑方法名
iv. 响应数据为true或者false的字符串

示例代码:

/*********************转账金额校验**************************************/    $(function () {$("#money").blur(function () {//发起ajax请求$.post("checkAccount",{outId:$("#outId").val(),money:$("#money").val(),methodName:"checkMoneyInfo"},function (data) {if(eval(data)){$("#moneySpan").html("√").css("color","green");}else{$("#moneySpan").html("X").css("color","red");}})})})

② 后台分析:
i. 在CheckAccountServlet中声明金额校验逻辑方法,并在service方法完成调用

    //校验金额private void checkMoneyInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//获取请求数据String outId=req.getParameter("outId");String money =req.getParameter("money");//处理请求Account account=checkAccountService.checkMoneyInfoService(outId,money);//响应结果resp.getWriter().write(account!=null?"true":"false");}

ii. 在CheckAccountService中新增金额校验的业务方法

    //校验金额Account checkMoneyInfoService(String outId, String money);
    //校验金额@Overridepublic Account checkMoneyInfoService(String outId, String money) {return checkAccountMapper.checkMoneyInfoMapper(outId,money);}

iii. 在CheckAccountMapper中新增金额校验的数据库操作

//校验金额
@Select("select * from t_account where aid=#{outId} and money>=#{money}")
Account checkMoneyInfoMapper(@Param("outId") String outId, @Param("money") String money);
9. 收款人信息校验

(1) 功能点需求:

用户在收款人姓名失去焦点时,校验收款人信息。存在,则在收款人姓名框后显示 √,不存在则显示X

(2) 功能分析

  1. 前台分析

i. 给收款人姓名框增加焦点事件
ii. 发起ajax请求完成校验
iii. 请求数据为收款人账户ID,收款人姓名,后台逻辑方法名
iv. 响应数据 true或者false的字符串

代码示例:

/*********************收款人信息校验**************************************/$(function () {$("#inName").blur(function () {//发起ajax请求$.post("checkAccount",{inId:$("#inId").val(),inName:$("#inName").val(),methodName:"checInInfo"},function (data) {if(eval(data)){$("#inNameSpan").html("√").css("color","green");}else{$("#inNameSpan").html("X").css("color","red");}})})})
  1. 后台分析
    i. 在CheckAccountServlet中声明对应的逻辑方法完成校验
    //校验收款人信息private void checInInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//获取请求数据String inId=req.getParameter("inId");String inName=req.getParameter("inName");//处理请求Account account=checkAccountService.checkInInfoService(inId,inName);//响应结果resp.getWriter().write(account!=null?"true":"false");}

ii. 在CheckAccountService中声明业务方法

    //校验收款人信息Account checkInInfoService(String inId, String inName);
    //校验收款人信息@Overridepublic Account checkInInfoService(String inId, String inName) {return checkAccountMapper.checkInInfoMapper(inId,inName);}

iii. 在CheckAccountMapper中声明数据库操作

    //校验收款人信息@Select("select a.* from t_account a join t_user u on a.uid=u.uid where a.aid=#{inId} and u.uname=#{inName}")Account checkInInfoMapper(@Param("inId") String inId, @Param("inName") String inName);
10. 开始转账

(1) 功能点需求:

点击开始转账时,保证所有的转账信息是正确的,如果有错误的转账信息 提示用户,请填写正确的信息。如果全部都是正确的,则直接发起转账请求,完成转账。

(2) 功能分析:

① 前台分析

i. 给转账按钮增加单击事件
ii. 校验转账信息是否全部正确
iii. 提交转账请求

代码示例:

/*********************转账账户信息校验**************************************///给密码框添加焦点事件,完成校验$(function () {$("#outdPwd").blur(function () {//发起ajax请求$.post("checkAccount",{outId:$("#outId").val(),outPwd:$("#outdPwd").val(),methodName:"checkOutInfo"},function (data) {if(eval(data)){$("#outSpan").html("√").css("color","green").addClass("success").removeClass("error");}else{$("#outSpan").html("X").css("color","red").addClass("error").removeClass("success");}})})})
/*********************转账金额校验**************************************/$(function () {$("#money").blur(function () {//发起ajax请求$.post("checkAccount",{outId:$("#outId").val(),money:$("#money").val(),methodName:"checkMoneyInfo"},function (data) {if(eval(data)){$("#moneySpan").html("√").css("color","green").addClass("success").removeClass("error");}else{$("#moneySpan").html("X").css("color","red").addClass("error").removeClass("success");}})})})
/*********************收款人信息校验**************************************/$(function () {$("#inName").blur(function () {//发起ajax请求$.post("checkAccount",{inId:$("#inId").val(),inName:$("#inName").val(),methodName:"checInInfo"},function (data) {if(eval(data)){$("#inNameSpan").html("√").css("color","green").addClass("success").removeClass("error");}else{$("#inNameSpan").html("X").css("color","red").addClass("error").removeClass("success");}})})})
/*********************转账功能**************************************/$(function () {$("#btn").click(function () {//校验转账信息是否正确if($(".success").length==3){//提及表单$("#fm").submit();}else{alert("请填写正确的账户信息")}})})

② 后台分析

i. 在CheckAccountServlet中声明转账的逻辑方法

    //转账private void transferInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//获取请求数据String outId=req.getParameter("outId");String inId=req.getParameter("inId");String money=req.getParameter("money");//处理请求int i=checkAccountService.transferInfoService(outId,inId,money);//响应结果if(i>0){resp.sendRedirect(req.getContextPath()+"/success.jsp");}else{resp.sendRedirect(req.getContextPath()+"/error.jsp");}}

ii. 在CheckAccountService中声明转账的业务方法

    //转账功能int transferInfoService(String outId, String inId, String money);
    //转账功能@Overridepublic int transferInfoService(String outId, String inId, String money) {//1.出账int i = checkAccountMapper.transferOut(outId, money);//2.入账i+=checkAccountMapper.transferIn(inId,money);//返回return i;}

iii. 在CheckAccountMapper中完成转账的数据库操作

    @Update("update t_account set money=money-#{money} where aid=#{outId}")int transferOut(@Param("outId") String outId,@Param("money") String money);//转入@Update("update t_account set money=money+#{money} where aid=#{inId}")int transferIn(@Param("inId") String inId,@Param("money") String money);
11. 登录日志

(1) 功能点需求:

我们的银行转账功能,在刚开始运营的时候,并没有用户登录的日志信息的记录。后来,某天某个客户他的账号被登录了,但是给该客户又不知道是什么时间进行的登录,造成调查有困扰,怎么办?在当前登录功能的基础上,增加登录日志,来记 录用户的登录信息。便于我们后期的排查。

(2) 功能分析:

在保留当前登录功能的基础上,完成对登录功能的扩展。但是又不希望改变原有的功能代码逻辑。考虑使用SpringAOP。
前置通知:在日志文件中输出XXX在XXX时间发起了登录请求
切点:登录的业务方法
后置通知:在日志文件中输出XXX在XXX时间登录成功
建议使用SchemaBased方式实现。

(3) 功能实现:

i. 在lib下导入AOP的jar包
ii. 在src下创建com.bjsxt.advice的包
iii. 在advice包中创建前置通知和后置通知

后置通知

package com.java.advice;import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class MyAfter implements AfterReturningAdvice {@Overridepublic void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {//获取Log4j的对象Logger logger = Logger.getLogger(MyAfter.class);//日志输出if(o!=null){logger.debug(objects[0]+"登录成功");}}
}

前置通知

package com.java.advice;import org.apache.log4j.Logger;
import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class MyBefore implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {//获取Log4j的对象Logger logger = Logger.getLogger(MyBefore.class);//日志输出logger.debug(objects[0]+"发起了登录请求");}
}

iv. 在src下声明log4j.properties配置文件


log4j.rootCategory=infolog4j.logger.com.bjsxt.mapper=debug, CONSOLE,LOGFILE
log4j.logger.com.bjsxt.advice=debug, CONSOLE,LOGFILE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=- %c-%d-%m%nlog4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=- %c-%d-%m%n

v. 在applicationcontext.xml文件中配置通知bean以及组装规则

<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--配置数据源bean--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/502"></property><property name="username" value="root"></property><property name="password" value="1234"></property></bean><!--配置工厂bean--><bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property></bean><!--配置mapper扫描bean--><bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="sqlSessionFactory" ref="factory"></property><property name="basePackage" value="com.bjsxt.mapper"></property></bean><!--配置业务层bean--><!--用户登录--><bean id="us" class="com.bjsxt.service.impl.UserServiceImpl"><property name="userMapper" ref="userMapper"></property></bean><!--配置信息校验--><bean id="checkAccountService" class="com.bjsxt.service.impl.CheckAccountServiceImpl"><property name="checkAccountMapper" ref="checkAccountMapper"></property></bean><!--配置通知bean--><bean id="before" class="com.bjsxt.advice.MyBefore"></bean><bean id="after" class="com.bjsxt.advice.MyAfter"></bean><!--配置AOP组装规则--><aop:config><aop:pointcut id="mp" expression="execution(* com.bjsxt.service.impl.UserServiceImpl.userLoginService(String,String))"/><aop:advisor advice-ref="before" pointcut-ref="mp"></aop:advisor><aop:advisor advice-ref="after" pointcut-ref="mp"></aop:advisor></aop:config><!--开启cglib代理模式--><aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324758.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20级、19级 | 一天一瞬间!【日更】

点击上方蓝色关注我们&#xff01;欢迎来到今天的一天一瞬间专栏今天是2020年09月08日&#xff0c;天气状况&#xff1a;炎热。19级目前还是上午上课下午补课&#xff0c;补课私下里和我说&#xff0c;班内学生表现都不错&#xff0c;听罢&#xff0c;甚是开心&#xff0c;不管…

一张图看懂小程序全生态

6月9日小程序发布整半年&#xff0c;这半年里&#xff0c;小程序接连经历了&#xff1a;受追捧——遇冷——质疑——趋于理性的过程。我们对小程序这半年来的产业发展做了全面的梳理&#xff0c;从中可以发现&#xff0c;小程序已俨然形成了自己的生态体系&#xff0c;这一生态…

自然语言处理中的Attention Model:是什么以及为什么[一]

转载自 自然语言处理中的Attention Model&#xff1a;是什么以及为什么[一] 自然语言处理中的Attention Model&#xff1a;是什么以及为什么[一] 1、前言 要是关注深度学习在自然语言处理方面的研究进展&#xff0c;我相信你一定听说过Attention Model&#xff08;后文有时…

204787 ,194787 |0001 1131 0001 4226 7035 ![2480 ]

点击上方蓝色关注我们&#xff01;0006 6143 0037 7139 ,2598 4192 0007 7240 0681 1331 0226 ?6849 ?0784 4104 6943 4149 2418 2345 5116 ,7119 0354 0055 3089 1835 ,5261 1783 0250 2601 0110 0171 ,6290 0138 4972 1421 0055 7820 0087 8010 0138 4104 ?1927 1927 ,076…

DDD理论学习系列(9)-- 领域事件

1. 引言 A domain event is a full-fledged part of the domain model, a representation of something that happened in the domain. Ignore irrelevant domain activity while making explicit the events that the domain experts want to track or be notified of, or whi…

ssl1127-方程的解数【HASH,dfs】

前言 我只是凑数的。 正题 输入输出&#xff08;建议无视&#xff09; Input 第1行包含一个整数n。第2行包含一个整数M。第3行到第n2行&#xff0c;每行包含两个整数&#xff0c;分别表示ki和pi。两个整数之间用一个空格隔开。第3行的数据对应i1&#xff0c;第n2行的数据对应…

自然语言处理中的Attention Model:是什么以及为什么[二]

转载自 自然语言处理中的Attention Model&#xff1a;是什么以及为什么[二] 自然语言处理中的Attention Model&#xff1a;是什么以及为什么[二] 1、Attention Model 图一见下&#xff1a; 图1中展示的Encoder-Decoder模型是没有体现出“注意力模型”的&#xff0c;所以可以…

SpringAOP之代理设计模式

[1]设计模式: 概念: 设计模式其实就是代码的一种结构的设计思路。 好处: 增加代码健壮性 易修改性 可扩展性 设计模式的种类: 三大种类: 建造类设计模式 结构类设计模式 行为类设计模式 参考网址: http://baijiahao.baidu.com/s?id1639156298714178350&wfrspider&forp…

教师节快乐!

点击上方蓝色关注我们&#xff01;今天是个特殊的节日&#xff0c;教师节&#xff0c;从昨天开始就有学生给我发教师节祝福了……诺&#xff0c;发就发了吧&#xff0c;还害羞&#xff01;早上一醒来&#xff0c;就看到同学们在群里发祝福&#xff0c;心理美滋滋的。还有直接改…

如何利用.NET Core搭建跨平台的控制台应用程序

尽管传统意义上来说&#xff0c;.NET是只面向Windows的、闭源的专有平台&#xff0c;然而&#xff0c;传统观念即将被颠覆。新的开源跨平台的.NET Core已经开启&#xff0c;意味着你可以在任意平台写C#或.NET&#xff0c;然后在Windows、Linus和macOS运行。 这个新的.NET平台正…

自然语言处理中CNN模型几种常见的Max Pooling操作

转载自 自然语言处理中CNN模型几种常见的Max Pooling操作 自然语言处理中CNN模型几种常见的Max Pooling操作 CNN是目前自然语言处理中和RNN并驾齐驱的两种最常见的深度学习模型。 图1展示了在NLP任务中使用CNN模型的典型网络结构。 一般而言&#xff0c;输入的字或者词用…

SpringTX

文章目录SpringTX的介绍SpringTX的使用代码示例声明式事务中属性解释SpringBoot中AOP事务配置SpringTX的介绍 问题&#xff1a; 在学习了Spring整合mybatis后&#xff0c;我们可以直接从Spring容器中获取mapper层的实例化对象完成数据库操作。而在业务层方法中很多时候因为业务…

详细整理分层开发步骤!

不点蓝字&#xff0c;我们哪来故事&#xff1f;一、创建数据库&#xff0c;在数据库中创建表二、创建java项目&#xff08;起名要有意义&#xff0c;eg&#xff1a;petSys&#xff09;三、在项目中新建包&#xff0c;包名为&#xff1a;cn.bdqn.petSys.entity四、在cn.bdqn.pet…

.NET 跨平台界面框架和为什么你首先要考虑再三

现在用 C# 来开发跨平台应用已经有很成熟的方案&#xff0c;即共用非界面代码&#xff0c;而每个操作系统搭配特定的用户界面代码。这个方案的好处是可以直接使用操作系统原生的控件和第三方控件&#xff0c;还能够和操作系统深度集成。 这里的深度集成主要是指一些 Windows 专…

seq2seq中的beam search算法过程

转载自 seq2seq中的beam search算法过程 首先说明在sequence2sequence模型中&#xff0c;beam search的方法只用在测试的情况&#xff0c;因为在训练过程中&#xff0c;每一个decoder的输出是有正确答案的&#xff0c;也就不需要beam search去加大输出的准确率。 假设现在我…

Spring的properties属性配置文件和Spring常用注解

Spring的properties属性配置文件 问题: 在学习了Spring的知识后&#xff0c;需要被Spring管理的资源都是通过配置文件的形式来告诉Spring容器对象管理谁以及如何管理。但是随着使用次数的增多&#xff0c;我们发现配置文件中配置的标签越来越多&#xff0c;每次我们创建一个新…

即日起,正式进入编程世界!

点击上方蓝色关注我们&#xff01;从今天开始&#xff0c;正式进入编程世界。首先我们先从堪称“少儿编程”的Scratch开始&#xff0c;简洁的编辑窗口加上可读性较高的Chinese&#xff08;大部分的编程编辑器均为英文版&#xff09;&#xff0c;使得该软件特容易上手。班内总有…

使用领域事件

1.引言 最近刚学习了下DDD中领域事件的理论知识&#xff0c;总的来说领域事件主要有两个作用&#xff0c;一是解耦&#xff0c;二是使用领域事件进行事务的拆分&#xff0c;通过引入事件存储&#xff0c;来实现数据的最终一致性。若想了解DDD中领域事件的概念&#xff0c;可参…

深入浅出讲解语言模型

转载自 深入浅出讲解语言模型 深入浅出讲解语言模型 1、什么是语言模型呢&#xff1f; 简单地说&#xff0c;语言模型就是用来计算一个句子的概率的模型&#xff0c;也就是判断一句话是否是人话的概率&#xff1f; 那么如何计算一个句子的概率呢&#xff1f;给定句子&…

基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)

一、前言 至今为止编程开发已经11个年头&#xff0c;从 VB6.0,ASP时代到ASP.NET再到MVC, 从中见证了.NET技术发展&#xff0c;从无畏无知的懵懂少年&#xff0c;到现在的中年大叔&#xff0c;从中的酸甜苦辣也只有本人自知。随着岁月的成长&#xff0c;技术也从原来的三层设计到…