技术标签: spring 架构 java javaweb mvc
Mvc概念:M:model(模型),V:view(视图),C:Controller(控制器)
视图层:用于做数据的展示以及与用户进行交互的一个界面
控制层:能够接收客户端的请求,具体的业务功能还是需要模型组件来完成。
模型层:负责处理业务逻辑以及数据库的交互,承载数据。模型分为多种,有简单的pojo/vo(value object),有业务模型组件,以及数据访问层组件。
模型层类别:
1)pojo/vo:值对象:一个fruit类就是值对象,可以获取相应的属性数据。
2)DAO:数据访问对象:连接数据库并操作相应数据库表单的DAO类
3)BO: 业务对象:业务对象调用相应的数据对象进行一系列操作。
区分业务对象以及数据访问对象:
1)DAO中的方法都是单精度方法或细粒度的方法,一个方法只考虑一个操作,比如添加到数据库就是insert,无需考虑其他操作的影响。
2)BO中的方法属于业务方法,实际的业务是比较复杂的,因此业务方法粒度是比较粗的。service层的业务实现,具体要调用已经定义的dao层接口,封装service层业务逻辑有利于通用的业务逻辑的独立性和重复利用性。程序显得非常简洁。
例如账户注册这个功能属于业务功能,因此注册这个方法属于业务方法。
那么这个业务方法就包含了许多DAO方法,也就是说注册这个业务功能需要通过多个DAO方法的组合进行调用,从而完成注册功能的实现。
注册:
1、检查用户名是否被注册-DAO中的select操作
2、向用户表新增一条新用户记录-DAO中的insert操作
3、向用户表新增一条新用户记录-DAO中的insert操作
4、向系统消息表新增一条新用户记录-DAO中的insert操作
5、向系统日志表新增一条新用户记录-DAO中的insert操作
6、。。。
简单的说DAO层是跟数据库打交道的,service层是处理一些业务流程(不仅仅包括DAO调用操作)。
能够将各个层次强制性分开,这样分开之后就会减少层与层之间的依赖,这样就能最大化的重用代码了。例如MVC层的话多个视图就能共享一个模型,控制器也可以连接不同的模型和视图来完成用户的需求,三个部件相互独立这种设计思想能构造好的松耦合构建。
在原来优化后的水果系统中用户发送请求的处理流程如下图所示:
用户中央控制器接收请求后直接向控制层发出命令,由控制层访问model进行一系列的DAO方法调用获取数据,最后view渲染页面。
当日积月累的使用MVC模式开发之后,会逐渐感受到层与层之间的粘连以及模棱两可的地方存在,这就是service层出现的重要原因。业务逻辑粘连了C层以及M层,因此需要将业务逻辑解耦出来,成为独立的Service层。
假设现在你做这个功能会用到user表和权限表,那么你前台的页面访问action,action再去调用用户模块service,用户模块service判断你是操作user表还是权限表,如果你操作的是user表则service的实现类就去调用userDAO。如果是操作的是权限表则调用权限的DAO。也就是说DAO一定是和数据库的每张表一一对应,而service则不是。
没有service层会产生的问题:
只能在控制层直接实现业务逻辑导致多个控制器无法共享通用的业务逻辑,如果业务逻辑需要升级,则需要直接在源代码上修改兼容,会导致控制器代码不断膨胀复杂。
service层的作用:
service是业务层,是使用一个或者多个模型执行操作的方法。
1:封装一些通用的业务逻辑。
2:与数据层交互。
3:其他请求:如获取远程服务数据。
因此需构建一个业务模型来进行模型的调用,这样控制器能够更专注于模型构建的调用以及视图的处理。
package com.ck.fruit.biz.impl;
import com.ck.dao.FruitDAO;
import com.ck.fruit.biz.FruitService;
import com.ck.fruit.pojo.Fruit;
import java.util.List;
public class FruitServiceImpl implements FruitService {
FruitDAO fruitDAO=null;
@Override
public List<Fruit> getFruitList(String keyword, Integer pageNo) {
return fruitDAO.getFruitList(keyword,pageNo);
}
@Override
public void addFruit(Fruit fruit) {
fruitDAO.addFruit(fruit);
}
@Override
public Fruit getFruitById(Integer fid) {
return fruitDAO.getFruitByFid(fid);
}
@Override
public void delFruit(Integer fid) {
fruitDAO.deleteFruit(fid);
}
@Override
public Integer getPageCount(String keyword) {
Integer fruitCount=fruitDAO.countNum(keyword);
Integer pageCount=(fruitCount+5-1)/5;
return pageCount;
}
@Override
public void updateFruit(Fruit fruit) {
fruitDAO.updateFruit(fruit);
}
}
构建上述模型之后在控制器上进行业务调用即可,无需再直接再调用fruitDAO中的方法。
Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的业务处理方法。
采用MVC综合设计模式,MVC本身不属于设计模式的一种,它描述的是一种结构,最终目的达到解耦,解耦说的意思是你更改某一层代码,不会影响我其他层代码,如果你会像spring这样的框架,你会了解面向接口编程,表示层调用控制层,控制层调用业务层,业务层调用数据访问层。初期也许都是new对象去调用下一层,比如你在业务层new一个DAO类的对象,调用DAO类方法访问数据库,这样写是不对的,因为在业务层中是不应该含有具体对象,最多只能有引用,如果有具体对象存在,就耦合了。因此在层与层之间实现解耦很有必要,IOC就能实现此需求。
<bean id="fruit" class="com.ck.fruit.controllers.FruitController">
<property name="fruitService" ref="fruitService"/>
</bean>
这样就可以通过配置中的属性找到类所需要的依赖并进行实例化,这就是注入依赖。
1.在原先的项目中在控制器以及service层中均存在实例化其它层的类再进行调用,这样层与层之间就存在耦合依赖的情况,因此需要对当前结构进行改进。
2.将需要的类先赋值为null
3.建立一个Beanfactory接口并创建其实现类用来构建一个MAP集合存放xml配置文件中存放的类
xml配置文件,各个bean节点对应各个类,bean中的property节点表示该bean代表的类需要依赖的类,用于后续注入依赖使用。
ClassPathXmlApplicationContext类实现beanFactory接口,将xml配置文件中的类全部通过反射映射入相应集合中:
将xml中所有的类注入集合后就要开始组装bean之间的依赖关系,通过获取bean下的property子节点,来从集合中获取相应的类实例,然后通过反射技术将相应的类中的属性赋值,注入依赖。
最终实现水果系统:
文章浏览阅读1.3k次。# -*- coding: utf-8 -*-"""@File : 200113_等比例调整图像分辨率大小.py@Time : 2020/1/13 13:38@Author : Dontla@Email : [email protected]@Software: PyCharm"""import cv2def img_resize(image):height, width = image...._opencv小图等比例缩放
文章浏览阅读42次。对于这些调制技术的误码率(BER)研究是非常重要的,因为它们可以帮助我们了解在不同信道条件下系统的性能表现。通过以上步骤,您可以进行OFDM、OOK、PPM和QAM的误码率仿真研究,并绘制它们的误码率曲线,以便更好地了解它们在不同信道条件下的性能特点。针对这些调制技术的BER研究是非常重要的,可以帮助我们更好地了解这些技术在不同信道条件下的性能表现,从而指导系统设计和优化。6. 分析结果:根据误码率曲线的比较,分析每种调制方案在不同信噪比条件下的性能,包括其容忍的信道条件和适用的应用场景。_ber仿真
文章浏览阅读2.5w次,点赞3次,收藏3次。1、场景照抄官方的实例,绑定了 myData.Age 这个值。实际选择某个日期后,从 vuetool(开发工具)看,值已经更新了,但视图未更新。2、尝试绑定另一个值: myData,可以正常的触发 @change 方法。可能是:值绑定到子对象时,组件没有侦测到。3、解决使用 @blur 代替 @change 方法。再判断下 “值有没有更新” 即可。如有更好的方法,欢迎评论!..._el-date-picker @change不触发
文章浏览阅读1.5k次,点赞2次,收藏8次。Projectlnliersclass pcl: : Projectlnliers< PointT >类 Projectlnliers 使用一个模型和一组的内点的索引,将内点投影到模型形成新的一个独立点云。关键成员函数 void setModelType(int model) 通过用户给定的参数设置使用的模型类型 ,参数 Model 为模型类型(见 mo..._projectinliers
文章浏览阅读2.4k次。“System.BadImageFormatException”类型的未经处理的异常在 xxxx.exe 中发生其他信息: 未能加载文件或程序集“xxxxxxx, Version=xxxxxx,xxxxxxx”或它的某一个依赖项。试图加载格式不正确的程序。此原因是由于 ” 目标程序的目标平台与 依赖项的目标编译平台不一致导致,把所有的项目都修改到同一目标平台下(X86、X64或AnyCPU)进行编译,一般即可解决问题“。若果以上方式不能解决,可采用如下方式:右键选择配置管理器,在这里修改平台。_“system.badimageformatexception”类型的未经处理的异常在 未知模块。 中发生
文章浏览阅读2.4k次。记录一下碰到的问题:1.Assetbundle加载问题: 原PC打包后的AssetBundle导入安卓工程后,加载会出问题。同时工程打包APK时,StreamingAssets中不能有中文。解决方案: (1).加入PinYinConvert类,用于将中文转换为拼音(多音字可能会出错,例如空调转换为KongDiao||阿拉伯数字不支持,如Ⅰ、Ⅱ、Ⅲ、Ⅳ(IIII)、Ⅴ、Ⅵ、Ⅶ、Ⅷ、Ⅸ、Ⅹ..._电脑软件移植安卓
文章浏览阅读2.4k次。话不多说参考书籍 汪文君补充知识:start是异步,run是同步,start的执行会经过JNI方法然后被任务执行调度器告知给系统内核分配时间片进行创建线程并执行,而直接调用run不经过本地方法就是普通对象执行实例方法。什么是线程?1.现在几乎百分之百的操作系统都支持多任务的执行,对计算机来说每一个人物就是一个进程(Process),在每一个进程内部至少要有一个线程实在运行中,有时线..._start 是同步还是异步
文章浏览阅读5.3k次,点赞9次,收藏34次。我主要用了层次选择器和属性选择器可以随意选择,方便简单为主大体CSS格式 大家自行构造网页主体<body> <div class='main' > <div class='left'> <img src="images/pic.gif" /> <br/><br/> <img src="images/col.gif" alt="收藏本片"/&_单击标题“非缘勿扰”,元素中有id属性的的文本(主演、导演、标签、剧情
文章浏览阅读2.2k次。完整的解决思路_no module named 'win32com
文章浏览阅读901次,点赞20次,收藏23次。浏览器是每台电脑的必装软件,去浏览器搜索资源和信息已经成为我们的日常,我媳妇儿原本也以为浏览器就是上网冲浪而已,哪有那么强大,但经过我的演示之后她惊呆了,直接给我竖起大拇指道:“原来浏览器还能这么用?大开眼界!今天来给大家介绍几款实用的浏览器插件,学会之后让你的浏览器“活过来”!_浏览器插件助手
文章浏览阅读101次。NumPy是Python中最常用的科学数学计算库之一,它提供了高效的多维数组对象以及对这些数组进行操作的函数NumPy的核心是ndarray(N-dimensional array)对象,它是一个用于存储同类型数据的多维数组Numpy通常与SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用,用于替代MatLabSciPy是一个开源的Python算法库和数学工具包;Matplotlib是Python语言及其Numpy的可视化操作界面'''_数学中常用的环境有numpy
文章浏览阅读1.1w次。docker in docker说白了,就是在docker容器内启动一个docker daemon,对外提供服务。优点在于:镜像和容器都在一个隔离的环境,保持操作者的干净环境。想到了再补充 :)一:低版本启动及访问启动1.12.6-dinddocker run --privileged -d --name mydocker docker:1.12.6-dind在其他容器访问d..._dind