JavaWeb三层架构

        我们先来看一个请求响应类的代码,实现了从resource中读取user.txt文件获取用户信息封装,然后响应前端展示的功能。

package com.wzb.Controller;import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pojo.User;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;/*** 用户信息Controller*/
@RestController
public class UserController {@RequestMapping("/list")public String list() {// 1.加载user.txt文件获取用户信息,并将每一行的信息封装到ArrayList集合中,一行信息就是一个字符串元素// 因为类和resource在编译之后是在一起的,所以说通过获得本类的类加载器,调用getResourceAsStream方法(参数就是需要的文件名)// 返回该文件的输入流,可以避免使用绝对路径获得文件的输入流InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");// 使用hutool中的IoUtil,便捷的读文件输入流的内容,需要指定编码,并返回一个集合,集合中的每一个元素就是文件的一行内容ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());// 2.解析集合,获取用户属性,将属性封装成用户再用集合收集List<User> userList = lines.stream().map(line -> {String[] parts = line.split(","); // 用","分割字符串,得到每一个属性Integer id = Integer.parseInt(parts[0]);String username = parts[1];String password = parts[2];String name = parts[3];Integer age = Integer.parseInt(parts[4]);// 使用DateTimeFormatter类限定时间的格式,并按照该格式将String类型的时间字符串解析为LocalDateTime对象LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));return new User(id, username, password, name, age, updateTime);}).collect(Collectors.toList());//3.响应数据// 使用hutool中的JSONUtil类,将集合解析为json字符串返回,还可以使用setDateFormat方法设置json的时间格式return JSONUtil.toJsonStr(userList, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"));}
}

        

        此时,这个代码已经可以实现业务功能了,但是其实还是可以进行优化的:因为进行响应、获取数据、逻辑处理都在一个类中完成,假如说业务逻辑稍微变化,那么需要修改的地方就太多了,维护起来十分困难,用专业的术语来讲就是高耦合。这并不符合软件设计的原则——“高类聚、低耦合”。所以说一般在企业开发中使用三层架构的方式来实现分层解耦,从而达到软件设计的原则,增强程序的复用性、可维护性。

        三层架构

        Controller直接接收浏览器发送的请求,并调用Service进行处理;Service调用Dao获取数据;Dao从数据库中获取数据返回给Service,Service对Dao返回的数据进行逻辑处理返回给Controller;最后Controller将处理好的数据响应给前端。项目中一般会有多个Controller、Service、Dao,所以说需要先定义好对应的接口,再按照对应的业务逻辑编写其实现类(面向接口编程)。

        第一层:Controller(接收请求、响应数据)

        Controller是控制层,主要职责是接收前端发送的请求,对请求进行处理,并给前端响应数据,这一层需要和Service关联。 通过三层架构修改代码,使得Controller中的代码只有接收请求和响应数据的功能:

package com.wzb.controller;import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.wzb.pojo.User;
import com.wzb.service.UserService;
import com.wzb.service.impl.UserServiceImpl;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
public class UserController {private final UserService userService = new UserServiceImpl();private final List<User> userList = userService.findUser();@RequestMapping("/list")public String list() {return JSONUtil.toJsonStr(userList, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"));}}

        

        第二层:Service(逻辑处理)

        Service是业务逻辑层,主要的职责是处理具体的业务逻辑,这一层需要和Dao层关联;先在Dao层中获取了数据,再根据业务逻辑进行数据处理,将处理好的数据返回给Controller层。Service层的功能只有按照逻辑处理数据:

package com.wzb.service.impl;import com.wzb.dao.UserDao;
import com.wzb.dao.impl.UserDaoImpl;
import com.wzb.pojo.User;
import com.wzb.service.UserService;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;/*** Service层实现类**/
public class UserServiceImpl implements UserService {private final UserDao userDao = new UserDaoImpl();private final List<String> lines = userDao.findUser();public List<User> findUser() {List<User> userList = lines.stream().map(line -> {String[] parts = line.split(",");Integer id = Integer.parseInt(parts[0]);String username = parts[1];String password = parts[2];String name = parts[3];Integer age = Integer.parseInt(parts[4]);LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));return new User(id, username, password, name, age, updateTime);}).collect(Collectors.toList());return userList;}
}

        第三层:Dao(数据访问)

        Dao(Data Access Object 持久层),主要的职责是负责数据访问操作,包括数据的CRUD,这一层需要和数据库关联。Dao层在数据库中(或者其他数据源)获取数据之后,封装到集合中(或者不封装),直接返回到Service层,Service层进行处理。Dao层只负责和数据库交互获取数据。

package com.wzb.dao.impl;import cn.hutool.core.io.IoUtil;
import com.wzb.dao.UserDao;import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;/*** Dao层的实现类**/
public class UserDaoImpl implements UserDao {@Overridepublic List<String> findUser() {InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");return IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());}
}

        这样通过三层架构,就将原来一个类中的代码、一个类实现的功能,分工给了三个类,这样每一层各司其职,代码的维护性、可复用性大大提高,也便于分层解耦。 

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

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

相关文章

【数据结构与算法】排序算法总结:冒泡 / 快排 / 直接插入 / 希尔 / 简单选择 / 堆排序 / 归并排序

1 排序 1.1 冒泡 内排序的交换排序类别 1.1.1 普通实现 public class BubbleSort {/*** 基本的 冒泡排序*/public static void bubbleSort(int[] srcArray) {int i,j; // 用于存放数组下标int temp 0; // 用于交换数值时临时存放值for(i0;i<srcArray.length-1;i){// j …

如何构建SAAS项目

在后台使用JDBC方式动态创建用户输入的数据库信息&#xff08;库名、地址、用户名、密码&#xff09; 执行预先写好的sql文件&#xff08;如mybatis的scriptRunner)执行建表语句及插入基础数据&#xff08;管理员用户、普通用户&#xff09;

MQ高级2:MQ的可靠性

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

transformer学习笔记-神经网络原理

在深度学习领域&#xff0c;transformer可以说是在传统的神经网络的基础上发展而来&#xff0c;着重解决传统神经网络长距离关联、顺序处理、模型表达能力等问题。 在学习transformer之前&#xff0c;我想&#xff0c;有必要先对传统的神经网络做简要的了解。 一、神经网络基本…

【前端】JavaScript中的字面量概念与应用详解

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;字面量1. 数字字面量2. 字符串字面量3. 布尔字面量4. 空值字面量&#xff08;null&#xff09;5. 对象字面量6. 数组字面量7. 正则表达式字面量8. 特殊值字面量9. 函数字…

字节跳动青训营刷题笔记19

问题描述 小R正在组织一个比赛&#xff0c;比赛中有 n 支队伍参赛。比赛遵循以下独特的赛制&#xff1a; 如果当前队伍数为 偶数&#xff0c;那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛&#xff0c;且产生 n / 2 支队伍进入下一轮。如果当前队伍数为 奇数&…

Python中的简单爬虫

文章目录 一. 基于FastAPI之Web站点开发1. 基于FastAPI搭建Web服务器2. Web服务器和浏览器的通讯流程3. 浏览器访问Web服务器的通讯流程4. 加载图片资源代码 二. 基于Web请求的FastAPI通用配置1. 目前Web服务器存在问题2. 基于Web请求的FastAPI通用配置 三. Python爬虫介绍1. 什…

【ArcGISPro】使用AI提取要素-土地分类(sentinel2)

Sentinel2数据处理 【ArcGISPro】Sentinel-2数据处理-CSDN博客 土地覆盖类型分类 处理结果

WinForm 的Combox下拉框 在FlatStyle.Flat的边框设置

现象&#xff1a;Combox在设置FlatStyle.Flat时边框不见了 效果&#xff1a; 解决问题思路封装新控件&#xff1a; public class DBorderComboBox : ComboBox {private const int WM_PAINT 0xF;[Browsable(true)][Category("Appearance")][Description("边框…

Python 爬虫入门教程:从零构建你的第一个网络爬虫

网络爬虫是一种自动化程序&#xff0c;用于从网站抓取数据。Python 凭借其丰富的库和简单的语法&#xff0c;是构建网络爬虫的理想语言。本文将带你从零开始学习 Python 爬虫的基本知识&#xff0c;并实现一个简单的爬虫项目。 1. 什么是网络爬虫&#xff1f; 网络爬虫&#x…

使用UE5.5的Animator Kit变形器

UE5.5版本更新了AnimatorKit内置插件&#xff0c;其中包含了一些内置变形器&#xff0c;可以辅助我们的动画制作。 操作步骤 首先打开UE5.5&#xff0c;新建第三人称模板场景以便测试&#xff0c;并开启AnimatorKit组件。 新建Sequence&#xff0c;放入测试角色 点击角色右…

Uniapp 安装安卓、IOS模拟器并调试

一、安装Android模拟器并调试 1. 下载并安装 Android Studio 首先下载 Mac 环境下的 Android Studio 的安装包&#xff0c;为dmg 格式。 下载完将Android Studio 向右拖拽到Applications中&#xff0c;接下来等待安装完成就OK啦&#xff01; 打开过程界面如下图所示&#xf…

shell(5)字符串运算符和逻辑运算符

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

【金蝶双线指标】以看资金进出操作为主,兼顾波段跟踪和短线低吸

如上图&#xff0c;个股副图指标&#xff0c;大佬资金监控短线低吸攻击线操盘线趋势红蝴蝶&#xff0c;五大功能于一体。下面慢慢给大家仔细分享。 大佬资金监控指标&#xff0c;红绿进出&#xff0c;绿色缩小到极致&#xff0c;接近零轴&#xff0c;红绿柱分界线&#xff0c;为…

多输入多输出 | Matlab实现TCN-GRU时间卷积神经网络结合门控循环单元多输入多输出预测

多输入多输出 | Matlab实现TCN-GRU时间卷积神经网络结合门控循环单元多输入多输出预测 目录 多输入多输出 | Matlab实现TCN-GRU时间卷积神经网络结合门控循环单元多输入多输出预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现TCN-GRU时间卷积…

HCIA笔记4--VLAN划分

1. vlan是什么 vlan: virtual lan; 虚拟局域网的简称。 主要目的是隔离广播域。 2. vlan报文格式 在普通的以太网数据帧开关的12字节后添加4字节的vlan tag。而来区分vlan的是其中的vid部分12个比特位&#xff0c;范围自然就是0~2^12-1(0~4095); 0 4095保留使用。实际使用的是…

蓝牙定位的MATLAB仿真程序|基于信号强度的定位,平面、四个蓝牙基站(附源代码)

这段代码通过RSSI信号强度实现了蓝牙定位&#xff0c;展示了如何使用锚点位置和测量的信号强度来估计未知点的位置。它涵盖了信号衰减模型、距离计算和最小二乘法估计等基本概念。通过图形化输出&#xff0c;用户可以直观地看到真实位置与估计位置的关系。 文章目录 蓝牙定位原…

基于Springboot企业级工位管理系统【附源码】

基于Springboot企业级工位管理系统 效果如下&#xff1a; 系统登录页面 员工主页面 部门信息页面 员工管理页面 部门信息管理页面 工位信息管理页面 工位分配管理页面 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所。…

Spring Boot教程之十: 使用 Spring Boot 实现从数据库动态下拉列表

使用 Spring Boot 实现从数据库动态下拉列表 动态下拉列表&#xff08;或依赖下拉列表&#xff09;的概念令人兴奋&#xff0c;但编写起来却颇具挑战性。动态下拉列表意味着一个下拉列表中的值依赖于前一个下拉列表中选择的值。一个简单的例子是三个下拉框&#xff0c;分别显示…

SpringBoot源码-spring boot启动入口ruan方法主线分析(一)

一、SpringBoot启动的入口 1.当我们启动一个SpringBoot项目的时候&#xff0c;入口程序就是main方法&#xff0c;而在main方法中就执行了一个run方法。 SpringBootApplication public class StartApp {public static void main(String[] args) {// testSpringApplication.ru…