MVC架构
之前使用的三层架构模式:
主要分为: 表示层(UI层)(servlet、jsp)、业务层(BLL)(service)、持久层(DAL数据访问层)(dao模式、主要包含增删改查)。
使用三层架构可以将开发的流程进行细分,表示层处理请求以及响应、数据的显示。业务层处理业务逻辑,持久层负责进行数据的持久化操作。
MVC架构:
主要分为控制器(Controller)、模型(Model)、视图(View)
使用mvc架构可以更好的组织对象, 比如请求就交给控制器来完成,业务处理或者数据传递交给模型,数据的显示交给视图来处理。
不管是三层架构还是MVC 都是架构上的概念,本身没有任何的引入的内容,没有任何输入输出。只是使用这些架构模式可以更好的组织我们的类 ,使用了三层架构,可以让我们的结构更加清晰,方便以后的维护;使用了MVC,可以更好的组织对象,让模块之间能够解耦(不会直接耦合在一起)。
MVC详解:
M:Model 用于做数据的传递,比如增删改查的业务。(相当于JavaWeb中的JavaBean)
C:controller 用于接受请求,委托模型进行义务处理,然后处理响应。(相当于JavaWeb中的Servlet)
V:view 用于展示模型数据(相当于JavaWeb中的Jsp)
JavaBean在不同的架构中的作用
三层架构中的JavaBean:域模型层,主要的作用是用于在三层之间进行数据传递,贯穿三层。
MVC中的JavaBean:称为模型/JavaBean组件。负责传递数据,负责业务处理。
MVC&三层架构分别适合开发什么程序:
JavaBean组件:处理数据传递,又要处理业务逻辑。以后难于维护,业务逻辑庞大的项目(比如游戏)不推荐直接用MVC
三层架构:适合业务比较复杂的项目,分层明确,每层都有自己的任务,每层尽量做到解耦(改变其中一层,不会影响到其他层)。
缺点:层数太多了。导致本来简单的业务反而很复杂。
MVC优化:
两个架构之间的联系:
将MVC架构拆分:
JavaBean组件—业务层+持久层+域模型层
Controller+JSP 正好就是表示层的内容:
在三层架构中,MVC使用表示层框架。但是单独使用MVC的时候是独立的架构
拆分前:
拆分后:
MVC:
1.参数的映射(自动映射) 内容自动匹配
以后要接受什么值,只需要写好数据类型,写好名字
2.响应内容自动转化、发送回客户端。
或者
不再需要response.getWriter等方法了,直接返回。
以后只需要写上一个userBean,就自动将user转化为json传回去。(以前是用写servlet当成controller。现在自己写一个controller)
自定义框架:架构设计
自定义MVC框架:
1.自己要设计一个控制器,控制器里面既可以自动获取数据,也可以自动将数据转化数据格式。
2.还可以自动将内容转化json,也可以将内容自动发送回客户端。
目前我们能用到的技术:Servlet技术、Filter技术(在servlet之前) 都能接受请求。
4-29 今天:以Servlet为核心去封装自定义框架。MyMVC。
写一个servlert,多个controller.Servlet如何链接(调用)Controller?通过路径链接,给servlet controller加上路径识别标志。如何路径匹配了 servlet就可以通过反射去调用controller。给Controller加上注解:
Servlet通过反射去找controller的时候 默认会遍历所有的类,所有优化的时候可以设定servlet只扫描某个指定的包。把所有mycontroller只放在同一个包中,servlet只扫描这一个包就行。其他的包不用管也不会去扫。
优化:
如何在映射之前就设定只扫描某一个包?如何告诉servlet你的包名是哪个?
1.mycontroller和servlet放在同一个包。但是让别人共享的时候不方便(不推荐)
2.servlet在加载的时候要配置文件(web.xml),把controller的包放在配置文件中
问题:这里把这个包名写死了,打包成jar包后,会影响别人用的时候的命名规范。必须要是这个名字,不推荐。
3.让用户使用的时候提供一个==config.properties(使用者提供。开发者预先提供好文件模板,使用者使用的时候来修改里面的参数配置。)==的file文件。目的是告诉servlet读取的类所在的包是哪一个。可以解决在所有文件中盲目去找controller的操作,提高系统效率。
选中src,点file-new -file
在文件里设置
步骤:
1.创建一个servlet(核心处理器、前端控制器),不要注解,通过xml文件配置。用于接收用户发送过来的请求,但是他并不处理请求,只负责请求分发。
(1)重写service,用service处理,不用doget dopost
(2)重写 init方法 初始化servlet,整个生命周期只执行一次,读配置文件就用init来读
2.配置web。xml
在写controller的要用什么方法就写上.do(这里先不用,用*选择所有的方法)
综合xml:
然后设置servlet读这个配置文件,就可以读到数据 找到包,加载controller了。
3.设置全局变量properties
定义集合,用来存放全限定类名,用于把内容放在集合当中
4.定义一个方法doLoadConfig( 传入一个string类),用于读取location文件下的数据,获取到要扫描的包名
通过类加载器,读取传进来的路径,用一个输入流接收。这个方法只负责读。
5.在init中 加载config.proerties配置文件
6:写一个方法doScaner,获取到服务器里面的全限定类名。
根据传递过来的包名,动态获取包下面所有的class文件。加载后端控制器的包名。
读取到所有文件的物理路径,加载文件。
方法:使用类加载器提供的方法getResource.
+packageName。 但是proprties里面用的是 点 而不是斜杠,需要替换(replace。\. 因为点是特殊字符 需要斜杠来转义)。先打印出来看看是否能得到路径。注意:url得到的是一个文件夹
替换成replaceAll 现在就可以得到了
得到这个文件对象
通过foreach循环输出,如果获取的不是文件而是文件夹(通过isDirectory判断),比如controller大包里面又有一个小包的情况,这时候会找到一个文件夹,而不是包内的另一个包,这时候就需要则加上dian ”. “ 继续获取文件。
如果获取的是文件,去掉后缀(把.class换成空)。这个时候就获得了这个全限定类名了
第三步:在inti中加载读取的包下面的所有==类(。class)==文件(不是java文件)
第四步:将获取到的类加载实例。
1.声明一个全局的Map,键和值分别为路径,对象
2.自定义一个注解,来找到这个controller
2.定义一个方法,将获取到的类路径加载创建实例(不需要传参)
cla。isAnnotationPresent(是否有注解)(Controller.class) 是否有controller注解
3.将方法写到init中。(不需要传参)
第五步:
先定义一个Map,用来存放路径和方法的关系:(调用哪个路径/add还是/del 和他们所对应的方法)
1.定义一个方法,initHandlerMapping()将请求的路径和ioc容器中的实例进行匹配,匹配了才知道调的是哪个控制器
2.把用户发送过来的路径在controller上面映射一个地址
先自定义注解:
如果想用一个controller解决增删改查所有功能,可以这样做,头上加一个新的地址 比如user
然后下面每一个方法写一个独立的路径(数据接口)
为了防止类在加载的时候什么类都读取一遍,可以通过注解的方式给controller类的头上 加上标记
然后,自定义注解。–建包–建class-设置生命周期–
先得到user 得到user里面的所有注解 然后再通过注解获取add里面的方法
3.继续定义这个方法 initHandlerMapping。判断map的ioc容器是否为空。
第六步:定义一个全局MAp,用来存路径和方法之间的关系
第七步:再设计一个map,键是url 值是object对象,用于存放地址和对象之间的关系(上一个map是存地址和方法的关系)
综合的init:
第八步:定义一个方法,用于处理用户请求和url映射,然后在service里面调用这个方法。
两个Name 一定要一致。
整体:
调用之后, addcontroller里面的add方法就执行了。
本次导入的所有包:
为什么不在servlet里面直接new controller?
若以后业务庞大的时候,controller太多的时候,创建一个controller 就要在servlet里面又New一个controller。修改了源码,不符合编码逻辑。所以通过注解反射的机制可以更好达到这种效果