JavaWeb06-MVC和三层架构
目录
一、MVC模式
1.概述
2.好处
二、三层架构
1.概述
三、MVC与三层架构
四、练习
一、MVC模式
1.概述
MVC是一种分层开发的模式,其中
M:Model,业务模型,处理业务 V: View,视图,界面展示 C:Controller,控制器,处理请求,调用型和视图

2.好处
-
职责单一,互不影响
-
有利于分工协作
-
有利于组件重用
二、三层架构
1.概述

View视图不只是JSP!
数据访问层(持久层):对数据库的CRUD基本操作
一般命名为反转公司网址/controller
业务逻辑层(业务层):对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。
一般命名为反转公司网址/service
表现层:接收请求,封装数据,调用业务逻辑层,响应数据
一般命名为反转公司网址/dao或者mapper
三、MVC与三层架构

四、练习
给上次的数据添加一个状态字段,0禁用,1启用,2预售,设个默认值1即可
使用三层架构思想开发
参考下图:

java目录结构

代码,只写主要的了
service包下
public class ProductService {final SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();public List<Product> selectAll(){final SqlSession sqlSession = sqlSessionFactory.openSession();final ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);final List<Product> products = mapper.selectAll();sqlSession.close();return products;};
}
web包下
@WebServlet("/selectAll")
public class selectAll extends HttpServlet {private final ProductService productService = new ProductService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final List<Product> products = productService.selectAll();request.setAttribute("product",products);request.getRequestDispatcher("/jsp/product.jsp").forward(request,response);}
@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
之后回到视图层

jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--Created by IntelliJ IDEA.User: LEGIONDate: 2024/3/13Time: 13:36To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%--<% final Object product = request.getAttribute("product");%>--%>
<html>
<head><title>Title</title>
</head>
<body><h1>product列表</h1><table border="1px solid black"><tr><th>商品序号</th><th>商品id</th><th>商品名</th><th>商品图片</th><th>商品价格</th><th>商品评论数</th><th>商品分类</th><th>商品状态</th><th>商品发布时间</th><th>商品更新时间</th></tr><c:forEach items="${product}" var="product" varStatus="status"><tr><%-- index从0开始,count从1开始--%><td>${status.count}</td><%-- ${user.id} => Id => getId()--%><td>${product.id}</td><td>${product.title}</td><td><img src="${product.imgUrl}" alt="" width="75px" height="75px"></td><td>${product.price}</td><td>${product.comment}</td><td>${product.category}</td><td>${product.status}</td><td>${product.gmtCreate}</td><td>${product.gmtModified}</td></tr></c:forEach>
</table>
</body>
</html>
预览图:

添加:
html
<form action="/product_demo_war/add" method="post"><input type="text" name="title" placeholder="商品名称"><br><input type="text" name="price" placeholder="商品价格"><br>
<!-- 图片上传在这里就先不写了--><input type="number" name="category" placeholder="商品类型(数字就好)"><br><input type="radio" name="status">启用<input type="radio" name="status">禁用<br><input type="submit" value="添加"></form>
service:
/*** 添加商品* @param product 商品对象*/
public void add(Product product){final SqlSession sqlSession = sqlSessionFactory.openSession();final ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);mapper.add(product);sqlSession.commit();sqlSession.close();
}
web:
@WebServlet("/add")
public class Add extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ProductService productService = new ProductService();final String title = request.getParameter("title");final String price = request.getParameter("price");final Integer status = Integer.parseInt(request.getParameter("status"));final Integer category = Integer.parseInt(request.getParameter("category"));Product product = new Product(title,price,category,status);productService.add(product);request.getRequestDispatcher("/selectAll").forward(request,response);}
@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
预览:

修改:
有两步:
-
显示原先的数据:回显
-
修改现有的数据:修改
第一部分回显:根据id显示值
service:
public Product selectById(Long id){final SqlSession sqlSession = sqlSessionFactory.openSession();final ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);final Product product = mapper.selectById(id);sqlSession.close();return product;
}
web:
@WebServlet("/selectById")
public class SelectById extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {final String id = request.getParameter("id");ProductService productService = new ProductService();final Product product = productService.selectById(Long.parseLong(id));request.setAttribute("product",product);System.out.println(id);request.getRequestDispatcher("/jsp/productUpdate.jsp").forward(request,response);}
@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
显示层:productUpdate.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head><title>修改</title><style>.text {width: 100%;}</style>
</head>
<body>
<form action="/product_demo_war/updateById" method="post"><input type="hidden" name="id" value="${product.id}"><input class="text" type="text" name="title" placeholder="商品名称" value="${product.title}"><br><input class="text" type="text" name="price" placeholder="商品价格" value="${product.price}"><br><!-- 图片上传在这里就先不写了--><input class="text" type="number" name="category" placeholder="商品类型(数字就好)" value="${product.category}"><br><c:if test="${product.status == 1}"><input type="radio" name="status" value="1" checked>启用<input type="radio" name="status" value="0">禁用</c:if><c:if test="${product.status == 0}"><input type="radio" name="status" value="1">启用<input type="radio" name="status" value="0" checked>禁用</c:if>
<br><input type="submit" value="修改">
</form>
</body>
</html>
第二部分修改:
service:
public void UpdateById(Product product){final SqlSession sqlSession = sqlSessionFactory.openSession();final ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);mapper.updateById(product);sqlSession.commit();
}
servlet:
@WebServlet("/updateById")
public class Update extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final Long id = Long.parseLong(request.getParameter("id"));final String title = request.getParameter("title");final String price = request.getParameter("price");final Integer category = Integer.parseInt(request.getParameter("category"));final Integer status = Integer.parseInt(request.getParameter("status"));Date gmtModified = new Date();
Product product = new Product(id,title,price,category,status,gmtModified);ProductService productService = new ProductService();productService.UpdateById(product);
request.getRequestDispatcher("/selectAll").forward(request,response);
}
@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
测试:




删除:不写了,jsp知道怎么写就行了
相关文章:
JavaWeb06-MVC和三层架构
目录 一、MVC模式 1.概述 2.好处 二、三层架构 1.概述 三、MVC与三层架构 四、练习 一、MVC模式 1.概述 MVC是一种分层开发的模式,其中 M:Model,业务模型,处理业务 V: View,视图,界面展…...
MySQL数据库实现增删改查基础操作
准备工作 安装mysql8.0 (安装时一定要记住用户名和密码)安装数据库可视化视图工具Navicat 请注意⚠️⚠️⚠️⚠️ a. 编程类所有软件不要安装在中文目录下 b. Navicat破解版下载安装教程:(由于文章审核提示版权问题,链接不方便给出ÿ…...
PCM和I2S区别
I2S和PCM接口都是数字音频接口,而所见的蓝牙到cpu以及codec的音频接口都是用PCM接口,是不是两个接口有各自不同的应用呢?先来看下概念。 PCM(PCM-clock、PCM-sync、PCM-in、PCM-out)脉冲编码调制,模拟语音信…...
大模型笔记:吴恩达 ChatGPT Prompt Engineering for Developers(1) prompt的基本原则和策略
1 intro 基础大模型 VS 用指令tune 过的大模型 基础大模型 只会对prompt的文本进行续写 所以当你向模型发问的时候,它往往会像复读机一样续写几个问题这是因为在它见过的语料库文本(通常大多来自互联网)中,通常会连续列举出N个问…...
设计模式 — — 单例模式
一、是什么 单例模式只会在全局作用域下创建一次实例对象,让所有需要调用的地方都共享这一单例对象 二、实现 // 单例构造函数 function CreateSingleton (name) {this.name name;this.getName(); };// 获取实例的名字 CreateSingleton.prototype.getName func…...
C++:菱形继承与虚继承
看下面这个示例代码 class A{ public: int num10; A(){cout<<"A构造"<<endl;} virtual void fun(){cout<<"A虚函数"<<endl;} };class B:public A{ public: B(){cout<<"B构造"<<endl;} void fun(){cout<…...
贡献法:USACO 2021 December Contest Bronze:孤独的照片
Farmer John 最近购入了 N 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。 奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。 然而,他…...
Java实现简单的通讯录
每日一言 泪眼问花花不语,乱红飞过秋千去。 —欧阳修- 简单的通讯录实现,跟写Java实现图书管理系统差不多,用到的知识也差不多,就当个小练习,练习一下写Java程序的手感。 Java实现图书管理系统 关于通讯录的代码都写…...
服务器数据恢复—raid5热备盘上线同步数据失败的如何恢复数据
服务器数据恢复环境&故障&分析: 一台存储上有一组由多块硬盘组建的raid5阵列,该raid5阵列中的一块硬盘掉线,热备盘自动上线同步数据的过程中,raid阵列中又有一块硬盘掉线,热备盘的数据同步被中断,r…...
探索C语言中的循环结构
循环结构是程序设计中一种重要的控制结构,它允许程序重复执行特定的代码块,直到满足某个条件为止。在C语言中,循环结构有多种形式,如for循环、while循环和do-while循环。本文将介绍C语言中的循环结构,并讨论它们的用法…...
数学建模-估计出租车的总数
文章目录 1、随机抽取的号码在总体的排序 1、随机抽取的号码在总体的排序 10个号码从小到大重新排列 [ x 0 , x ] [x_0, x] [x0,x] 区间内全部整数值 ~ 总体 x 1 , x 2 , … , x 10 总体的一个样本 x_1, x_2, … , x_{10} ~ 总体的一个样本 x1,x2,…,x10 总体的一个样…...
设计模式在芯片验证中的应用——装饰器
一、装饰器模式 装饰器模式(Decorator)是一种结构化软件设计模式,它提供了一种通过向类对象添加行为来修改类对象的方法,而不会影响同一类的其它对象行为。该模式允许在不修改抽象类的情况下添加类功能。它从本质上允许基类代码对不可预见的修改具有前瞻…...
Python 查找并高亮PDF中的指定文本
在处理大量PDF文档时,有时我们需要快速找到特定的文本信息。本文将提供以下三个Python示例来帮助你在PDF文件中快速查找并高亮指定的文本。 查找并高亮PDF中所有的指定文本查找并高亮PDF某个区域内的指定文本使用正则表达式搜索指定文本并高亮 本文将用到国产第三方…...
LEETCODE LCS 03. 主题空间
题目描述如上,这个题主要运用了DFS的思想,同时走过的路径标记为6,即可在后续的遍历中过滤掉重复的元素,其他则类似边界条件的判断和题目条件的判断,求最大值,只需要一次遍历中累加对比每一次得即可。 模板&…...
【Spring Boot 源码学习】深入应用上下文初始化器实现
《Spring Boot 源码学习系列》 深入应用上下文初始化器实现 一、引言二、往期内容三、主要内容3.1 spring-boot 子模块中内置的实现类3.1.1 ConfigurationWarningsApplicationContextInitializer3.1.2 ContextIdApplicationContextInitializer3.1.3 DelegatingApplicationConte…...
【Docker】一文趣谈Docker
🏡浩泽学编程:个人主页 🔥 推荐专栏:《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 🛸学无止境,不骄不躁,知行合一 文章目录 …...
代码随想录day19(2)二叉树:二叉树的最大深度(leetcode104)
题目要求:求出二叉树的最大深度 思路:首先要区分二叉树的高度与深度。二叉树的高度是任一结点到叶子结点的距离,而二叉树的深度指的是任一节点到根节点的距离(从1开始)。所以求高度使用后序遍历(从下往上&…...
Lua中文语言编程源码-第五节,更改lcorolib.c协程库函数, 使Lua加载中文库关键词(与所有的基础库相关)
源码已经更新在CSDN的码库里: git clone https://gitcode.com/funsion/CLua.git 在src文件夹下的lcorolib.c协程库函数,Coroutine Library:表明这个C源文件实现了Lua的协程库(Coroutine Library),即提供了…...
Docker学习之数据管理(超详解析)
Docker存储资源类型: 用户在使用 Docker 的过程中,势必需要查看容器内应用产生的数据,或者需要将容器内数据进行备份,甚至多个容器之间进行数据共享,这必然会涉及到容器的数据管理: (1ÿ…...
FDTD液晶折射率各项异性表示方法
由于FDTD的数据都是沿坐标轴的,各向异性材料的参数也需要根据坐标轴来输入。 首先要了解坐标变换。 坐标变换 这里以二维坐标变化为例。 矢量下我们可以发现OP可在两个坐标系下分别表示 接下来将两个坐标相互关联,这里以Xb举例,Yb同理 注…...
Z-Image-GGUF惊艳效果:运动模糊、景深虚化、镜头畸变等摄影级效果模拟
Z-Image-GGUF惊艳效果:运动模糊、景深虚化、镜头畸变等摄影级效果模拟 1. 项目简介:当AI学会“拍照” 想象一下,你告诉AI:“给我一张黄昏时分,一个女孩在樱花树下奔跑的照片,要有那种风吹过发丝的动感&am…...
基于Wan 3D Causal VAE(Show-o2)的模型,重新完整地分析 10分钟的视频 对应多少 vison token
可以。这次我按 Show-o2 官方 432432 配置 和 Wan 3D Causal VAE 的公开时间压缩规则,把 10B token 且全部都是 vision token 的情况重新完整算一遍。下面的“大小”我统一按 未压缩 RGB 原始数据量 来算;如果你问的是实际 JPG / PNG / MP4 落盘大小,那会随压缩格式、码率和…...
线性结构之链表[基于郝斌课程]
每个结点只有一个前续结点每个结点只有一个后续结点首结点没有前续结点尾结点没有后续结点专业术语:首结点:第一个有效结点,存放第一个有效数据尾结点:最后一个有效结点,存放最后一个有效数据头结点:在首结…...
【无标题】vLLM:推理吞吐与尾延迟的资源真相
Chunked Prefil 大小影响哪些? 影响TPOT 和TTFT。 吞吐吗。 吞吐是怎么定义的? 以及QPS怎么定义的,以及并发树的关系? https://support.huaweicloud.com/intl/en-us/bestpractice-modelarts/modelarts_llm_infer_5906026.html Red…...
C++ 地址空间随机化(ASLR):探讨 C++ 动态链接库在内存布局上的安全特性
尊敬的各位同仁,各位对系统安全和C编程充满热情的开发者们,大家下午好!今天,我们齐聚一堂,共同探讨一个在现代软件安全领域至关重要的主题——地址空间布局随机化(ASLR),特别是它如何…...
Infinity Pro书签迁移终极指南:从JSON文件到本地缓存的完整操作流程
Infinity Pro书签迁移终极指南:从JSON文件到本地缓存的完整操作流程 作为一名长期使用Infinity Pro的开发者,我深知书签迁移的痛点。每次换设备或重装系统,那些精心整理的技术资源库都要重新配置。本文将分享一套经过实战验证的迁移方案&…...
教师评估软件市场迎增长机遇:未来六年CAGR锁定6.7%,教育数字化转型添动能
据恒州诚思调研统计,2025年全球教师评估软件市场规模约30.58亿元,预计未来将持续平稳增长,到2032年市场规模将接近47.92亿元,未来六年复合年增长率(CAGR)为6.7%。在教育行业数字化转型加速的背景下…...
3步搭建高效NTQQ机器人:LuckyLilliaBot全功能配置指南
3步搭建高效NTQQ机器人:LuckyLilliaBot全功能配置指南 【免费下载链接】LuckyLilliaBot NTQQ的OneBot API插件 项目地址: https://gitcode.com/gh_mirrors/li/LuckyLilliaBot LuckyLilliaBot是一款基于OneBot11协议的NTQQ机器人框架,它能帮助开发…...
Hunyuan-MT-7B多语种能力:Pixel Language Portal在联合国六种官方语言互译中的表现
Hunyuan-MT-7B多语种能力:Pixel Language Portal在联合国六种官方语言互译中的表现 1. 引言:当像素冒险遇见多语言翻译 在全球化交流日益频繁的今天,语言障碍仍然是横亘在不同文化之间的无形壁垒。传统翻译工具往往给人冰冷、机械的使用体验…...
基于S7-300与组态王的智能药片装瓶机控制系统优化设计
1. 智能药片装瓶机控制系统的核心价值 在制药生产线上,药片装瓶环节看似简单却暗藏玄机。传统的人工装瓶方式不仅效率低下,还容易出现计数错误、交叉污染等问题。我曾在某药企亲眼见过工人因疲劳导致装瓶数量出错,最终整批药品不得不报废的案…...
