本文为动力节点老杜web课程mvc部分笔记,以银行转账项目为例
CREATE TABLE `t_act` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自然主键,与业务无关,自增',
`actno` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '账号',
`balance` decimal(10,2) DEFAULT NULL COMMENT '余额',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

原因
上述jar包添加过程有误
措施
1.以为jdk17与tomcat9不适配,换成10仍不适配
2.在web WEB-INF中创建lib目录,将servlet-api.jar拷过去,仍不管用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<base href="${pageContext.request.scheme}://${pageContext.request.serverPort}${pageContext.request.contextPath}/">
<title>银行账户转账</title>
</head>
<body>
<form action="transfer" method="post">
转出账户:<input type="text" name="fromActno"><br>
转入账户:<input type="text" name="toActno"><br>
转账金额:<input type="text" name="money"><br>
<input type="submit" name="转账">
</form>
</body>
</html>

别忘了加注解 @WebServlet("/transfer")
从前端获取用户输入的转账信息
String fromActno = request.getParameter("fromActno");
String toActno = request.getParameter("toActno");
double money = Double.parseDouble(request.getParameter("money"));
编写转账业务逻辑代码,连接数据库,进行转账操作(JDBC那一套)
注意3:开启事务,事务手动提交与事务回滚-------------------------------------------------
jdbc会自动提交,开启事务,不让他自动提交
注意2:在web WEB-INF中添加mysql连接jar包

注意1: 转账之前判断余额是否充足,不足则异常,(创建一个异常类)
//余额不足异常类
public class MoneyNotEnoughException extends Exception {
//构造方法
public MoneyNotEnoughException() {
}
public MoneyNotEnoughException(String msg) {
super(msg);
}
}
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
PreparedStatement ps2 = null; //有了新的sql语句
PreparedStatement ps3 = null;
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
String url = "jdbc:mysql://localhost:3306/mvc";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url,user,password);
//注意3
//开启事务
//获取预编译的sql对象
String sql = "select id,balance from t_act where actno = ? ";
ps = conn.prepareStatement(sql);
ps.setString(1,fromActno);
//执行sql语句,返回结果集
rs = ps.executeQuery();
//拿到结果集后处理结果集
//因为只有一条结果,if即可
if (rs.next()){
//取出余额
double balance = rs.getDouble("balance");
if (balance < 0){
//余额不足
throw new MoneyNotEnoughException("余额不足");
}
//程序走到这里已经说明余额充足,不必加else,因为if中如不足则exception
//下面转账,实现功能
//act01 - 10000
//act02 + 10000
String sql2 = "update t_act set balance = balance - ? where actno = ? ";
ps2 = conn.prepareStatement("sql2");
ps2.setDouble(1,money);
ps2.setString(2,fromActno);
int count = ps2.executeUpdate(); //执行更新,并返回更新的条数
//---------------------模拟异常--------------------------------
//此处模拟一个异常,此时钱转出,未转入
String s = null;//空指针异常
//试验证明,出问题。引入事务
s.toString();
//---------------------模拟异常--------------------------------
String sql3 = "update t_act set balance = balance + ? where actno = ? ";
ps3 = conn.prepareStatement("sql3");
ps3.setDouble(1,money);
ps3.setString(2,fromActno);
count += ps3.executeUpdate();
if (count != 2){
//转账失败,再来异常
throw new AppException("App异常,请联系管理员");
}
//提交事务(转账成功肯定能提交了-----------------------------
conn.commit();
//转账成功
out.print("转账成功");
}
} catch (Exception e) {
//-------------------------------事务回滚--------------------
try {
if (conn != null) { //保险起见,不等于null才回滚
conn.rollback();//只要遇到异常就回滚
}
} catch (SQLException ex) {
ex.printStackTrace();
}
//-----------------------------------------------------
//异常处理,发生上述异常后怎么做
//e.printStackTrace(); 不打印异常信息了,搞到前端去
out.print(e.getMessage()); //getMessage可以获取到上面写的"余额不足"
// 因为构造方法中有参那个,调用父类的massage,父类中还有super继续上调,
//直到一个private的成员变量,那么值就给他了,而getMassage恰好获得他的值
}finally {
//释放资源
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps2 != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps3 != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
下面分析mvc存在的问题
这个servlet负责所有的事情
代码复用性太差,实现一个功能就要搞一个servlet,比如R,查一个数据就得写一个servlet,可以搞一个专门查数据的方法,查询数据时调用即可。
原因:没有进行"职能分工",没有独立组件的概念,没有办法进行代码复用,代码之间耦合度太高,扩展力太差
耦合度高导致代码很难扩展。
操作数据库的代码和业务逻辑混杂在一起,编写代码时很容易出错。无法专注业务逻辑。所以才需要分层。

C调用M和V
M:数据处理、业务处理
V:页面展示
jdbc.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mvc
user=root
password=123456
DBUtil
package bank.utils;
import java.sql.*;
import java.util.ResourceBundle;
/**
* JDBC工具类
* @author d
* @version 1.0
* @since 1.0
*/
public class DBUtil {
private static ResourceBundle bundle = ResourceBundle.getBundle("resources/jdbc");
private static String driver = bundle.getString("com.mysql.cj.jdbc.Driver");
private static String url = bundle.getString("jdbc:mysql://localhost:3306/mvc");
private static String user = bundle.getString("root");
private static String password = bundle.getString("123456");
//工具类一般搞个私有的构造方法,因为不让创建对象。工具类中的方法都是静态的,不需要创建对象
// 为了防止创建对象,故私有化
private DBUtil(){}
//DBUtil在类加载时注册驱动
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 这里没有使用数据库连接池,直接创建的连接对象
* 每一次调用这个方法,都是一个新的对象
* @return 连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
}
/**
* 关闭资源
* @param conn 连接对象
* @param stmt 数据库操作对象
* @param rs 结果集对象
*/
public static void close(Connection conn , Statement stmt, ResultSet rs){
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
AccountDao是负责Account数据增删改查的
时间
2022.08.30
我是一名决定学习Ruby和RubyonRails的ASP.NETMVC开发人员。我已经有所了解并在RoR上创建了一个网站。在ASP.NETMVC上开发,我一直使用三层架构:数据层、业务层和UI(或表示)层。尝试在RubyonRails应用程序中使用这种方法,我发现没有关于它的信息(或者也许我只是找不到它?)。也许有人可以建议我如何在RubyonRails上创建或使用三层架构?附言我使用ruby1.9.3和RubyonRails3.2.3。 最佳答案 我建议在制作RoR应用程序时遵循RubyonRails(RoR)风格。Rails
我想开始使用“Sinatra”框架进行编码,但我找不到该框架的“MVC”模式。是“MVC-Sinatra”模式或框架吗? 最佳答案 您可能想查看Padrino这是一个围绕Sinatra构建的框架,可为您的项目提供更“类似Rails”的感觉,但没有那么多隐藏的魔法。这是使用Sinatra可以做什么的一个很好的例子。虽然如果您需要开始使用这很好,但我个人建议您将它用作学习工具,以对您来说最有意义的方式使用Sinatra构建您自己的应用程序。写一些测试/期望,写一些代码,通过测试-重复:)至于ORM,你还应该结帐Sequel其中(imho
我尝试用Ruby设计一个基于Web的应用程序。我开发了一个简单的核心应用程序,在没有框架和数据库的情况下在六边形架构中实现DCI范例。核心六边形中有小六边形和网络,数据库,日志等适配器。每个六边形都在没有数据库和框架的情况下自行运行。在这种方法中,我如何提供与数据库模型和实体类的关系作为独立于数据库的关系。我想在将来将框架从Rails更改为Sinatra或数据库。事实上,我如何在这个核心Hexagon中实现完全隔离的rails和mongodb的数据库适配器或框架适配器。有什么想法吗? 最佳答案 ROM呢?(Ruby对象映射器)。还有
“架设一个亿级高并发系统,是多数程序员、架构师的工作目标。许多的技术从业人员甚至有时会降薪去寻找这样的机会。但并不是所有人都有机会主导,甚至参与这样一个系统。今天我们用12306火车票购票这样一个业务场景来做DDD领域建模。”开篇要实现软件设计、软件开发在一个统一的思想、统一的节奏下进行,就应该有一个轻量级的框架对开发过程与代码编写做一定的约束。虽然DDD是一个软件开发的方法,而不是具体的技术或框架,但拥有一个轻量级的框架仍然是必要的,为了开发一个支持DDD的框架,首先需要理解DDD的基本概念和核心的组件。一.什么是领域驱动设计(DDD)首先要知道DDD是一种开发理念,核心是维护一个反应领域概
我在当前项目中使用由Oracle数据库和memcached支持的RubyonRails。有一个非常常用的功能,它依赖于单个数据库View作为数据源,并且该数据源内部有其他数据库View和表。这是一个虚拟数据库View,能够从一个地方访问所有内容,而不是物化数据库View。大多数情况下,如果用户正在使用他们希望更新的功能,那么让数据保持最新很重要。从这个View获取数据时,我将安全表内部连接到View(安全表不是View本身的一部分),其中包含一些我们用来在更细粒度级别上控制数据访问的字段。例如,安全表有user_id,prop_1,prop_2列,其中prop_1,prop_2是数据库
我正在开发一个包含大约10个不同功能组件的Sinatra应用程序。我们希望能够将这些组件混合并匹配到应用程序的单独实例中,完全从config.yaml文件配置,如下所示:components:-route:'/chunky'component_type:FoodListercomponent_settings:food_type:baconmax_items:400-route:'places/paris'component_type:Mappercomponent_settings:latitude:48.85387273165654longitude:2.340087890625-
文章目录⭐️赠书活动-《从程序员到架构师》⭐️编辑推荐⭐️作者简介⭐️赠书活动→获奖名单⭐️赠书活动-《从程序员到架构师》内容简介:《从程序员到架构师:大数据量、缓存、高并发、微服务、多团队协同等核心场景实战》分为数据持久化层场景实战、缓存层场景实战、基于常见组件的微服务场景实战、微服务进阶场景实战和开发运维场景实战5个部分。基于对十余个架构搭建与改造项目的经验总结,介绍了大数据量、缓存、高并发、微服务、多团队协同等核心场景下的架构设计常见问题及其通用技术方案,包含冷热分离、查询分离、分表分库、秒杀架构、注册发现、熔断、限流、微服务等具体需求下的技术选型、技术原理、技术应用、技术要点等内容,将
我想要一个非常基本的小型基础程序示例,它读入两个插件并注册它们。这两个插件以相同的方式以不冲突的方式挂接到基础程序。就此而言,我对任何编程语言的元编程都很陌生,我不确定从哪里开始。 最佳答案 我已经研究这个问题一段时间了。我尝试了很多不同的方法来做这件事,并征求了很多人的建议。我仍然不确定我所拥有的是否是“正确的方法”,但它运作良好并且很容易做到。在我的例子中,我专门查看配置并引入配置插件,但原理是相同的,即使我的术语特定于cnfiguration。在非常基础的层面上,我有一个配置类,里面什么都没有——它是空的。我还有一个Confi
我正在学习Sinatra,我想知道是否有人知道使用Sinatra为项目制作MVC结构的好方法。我有一些想法,但对我来说它们似乎太麻烦了。 最佳答案 Sinatra已经是“VC”——您的View与您的路由(Controller)分离。如果愿意,您可以选择将其分成多个文件;有关更多信息,请参阅此答案(我的):UsingSinatraforlargerprojectsviamultiplefiles要添加“M”(模型),请选择一个数据库框架。有些人喜欢ActiveRecord.有些人喜欢DataMapper.还有更多可供您选择。我个人非常
数组理论基础数组是存放在连续内存空间上的相同类型数据的集合。数组下标从0开始数组内存空间的地址是连续的c++中vector和array的区别1、vector是顺序容器,其利用连续的内存空间来存储元素,但是其内存空间大小是能够改变的。2、array是顺序容器,其也是利用连续的内存空间来存储元素,但它的内存空间是固定大小的,申请之后就无法改变。3、vector的底层是array实现的二维数组二维数组在内存的空间地址是连续的704|二分查找思路1、把整个数组一分为二;2、判断目标值在左区间还是右区间,若在左区间,则修改右区间指针的位置;若在右区间,则修改新区间的左区间位置3、重复上述过程,直到lef