您的位置:首页 > 理论基础 > 计算机网络

Java网络编程的框架

2016-04-30 20:43 393 查看

三层架构与MVC的区别

三层架构是软件架构,是在整体上将整个软件系统从逻辑上划分为三层,即三个逻辑组件组成,目的是实现组件内的高内聚和组件间的底耦合,这三层分别是,表现层UI,业务逻辑层BLL,数据访问层DAL。

MVC是一种设计模式,三层架构的UI层存在显示逻辑,控制逻辑和业务逻辑的混淆,为了解决三层架构的UI层存在的问题,出现了MVC设计模式,MVC将UI层进一步划分成三层,显示层View,控制层Controller,模型层Model。

用entity文件夹存放实体类,其贯穿整个软件架构的三层,每一层都会用到entity中的实体,整个UI层通过MVC设计模式被分成了三部分,且仅Model部分与BLL有关,其余两部分解脱出来,理论上Model仅负责调用业务,而具体的业务由BLL实现,DAL仅完成对数据库最基本的操作,不涉及任何业务。

IOC分析

IOC,Inversion of Control,控制反转,类型之一是DI,Dependency Injection,依赖注入。面向抽象编程是指将程序中可变的部分抽象出来做成标准,即接口,面向标准编程,标准满足OCP原则,如下

类A面向某个标准,如IB编程,那么可以认为类A脱离了IB的具体实现,即与IB的实现成功解耦,类A是解放出来了,但是IB终究还是要注入实现的,如在类C中,给出IB的真正实现,然后再注入该具体实现给类A,如此实际是将类A对IB实现的依赖转移到了类C,实际类C对IB的实现产生了依赖,一个标准IB实际可以有很多的实现,若我们更换了实现,那就要重写类C。

IOC的出现实际就是为了解除类C与IB实现的依赖,将IB的实现类配置到XML中,那么类C要做的仅仅是通过工厂类获取一个具体的实现类的实例即可,而工厂类会加载并读取XML中实现类的完全限定名,而后通过反射机制生成IB的实现类的实例并返回给类C,这样我们若想更换实现,仅仅修改一下XML文件即可,类C不需要做任何修改。

public interface IB {
public void say();
}
public class B implements IB {
public void say() {
System.out.println(“hello”);
}
}
public class A {
IB ib;
public A() {}
构造注入
public A(IB ib) {
this.ib = ib;
}
设置注入
public void setIb(IB ib) {
this.ib = ib;
}
类A面向标准ib编程
public void sayHello() {
this.ib.say();
}
}
public Class C {
Factory factory = new Factory(XML路径);
IB ib = (IB)factory.getBean(“bean的id”);
A a = new A(ib);
a.sayHello();
}


Struts2中MVC的实现

View使用html与jsp实现,仅用于数据的提交与显示,完成显示逻辑,Controller使用Filter实现,仅用于请求的转发与响应的重定向,利用IOC完成控制逻辑,Model使用java调用BLL层的服务,完成业务逻辑,流程如下

用户通过View提交请求给Controller,Filter提取出用户请求的文件名,若文件名为一个页面,会进行请求的转发到该页面,不是重定向,要保证请求数据不会丢失,若文件名为XXAction,会从指定的路径加载并解析XML文件,找到XML文件中的name属性的值为文件名的节点对应的XXAction类的完全限定名,而后通过反射加载XXAction类并生成其实例,之后将具体的XXAction实例注入到Filter中的接口Action实例,然后调用抽象Action实例的execute方法,进入execute方法实际是从Controller转移到了Model,execute方法执行结束并返回后,从Model返回到Controller,由Controller根据XML的配置与返回的结果字符串来决定下一步的跳转,若下一步的跳转为页面,可以进行请求的转发,也可以进行响应的重定向,若下一步的跳转为XXAction,则必须进行响应的重定向,不能转发,要保证重新走Controller,由此View与Controller之间的转换是通过请求的提交与响应实现的,Controller与Model之间的转换是通过函数的调用与返回来实现的。

public class Filter {
面向抽象编程
public Action action;
public ActionFactory factory;
利用IOC注入抽象的具体实现
private void initAction(String action_name, HttpRequest request) {
factory = new ActionFactory(struts.xml);
内部利用发射加载类并实例化,反射出setXX方法,调用request的getParameter(XX)方法获取值并注入
this.action = factory.getAction(action_name, request);
判断是否使用拦截器并初始化flag
}
public void doGet(HttpRequest request, HttpResponse response) {
this.initAction(action_name, request);
if(使用拦截器) {
Action proxyAction = (Action)AOPContainer
.getProxyInterface(this.action);
String result = proxyAction.execute();
} else {
String result = this.action.execute();
}
String resultVal = facroty.getResultVal(action_name, result);
if(resultVal…) {
request.getRequestDispatcher(resultVal…)
.forward(request, response);
} else if(resultVal…) {
response.sendRedirect(resultVal…);
}
}
}


AOP分析

AOP,Aspect Oriented Programming,面向某个具体方法。可以将一个方法的不同业务逻辑相隔离,两个业务是互不相交的,从而降低耦合度,分别单独开发,最后利用动态代理来实现各个业务逻辑的组合,Struts2的execute方法使用了AOP,称为拦截器,如下

public class ActionInvocation {
private Object proxy;
private Method method;
private Object[] params;
被代理接口的实现类,实际是XXAction
private Object obj;
public ActionInvocation(Object proxy, Method method,
Object[] params, Object obj) {
this.proxy = proxy;
this.method = method;
this.params = params;
this.obj = obj;
}
public Object invoke() {
Object result = method.invoke(obj, params);
return result;
}
}
组合抽象类
public abstract class AbstractInterceptor {
public abstract String intercept(ActionInvocation actionInvo);
}
组合抽象类的实现类,由用户添加自己的业务逻辑
public class MyInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation actionInvo) {
用户实现添加业务
String result  = (String)actionInvo.invoke();
用户实现添加业务
return result;
}
}
实现动态代理的核心类,动态代理只能代理接口,由此Action必须定义为接口
public class InvocationHandlerImpl implements InvocationHandler {
obj用于接收被代理接口的实现类的实例
Object obj = null;
public InvocationHandlerImpl(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method method, Object[] params)
throws Throwable {
ActionInvocation actionInvo = new ActionInvocation(proxy,
method, params, obj);
AbstractInterceptor abstractInter = factory.getBean(拦截器名);
Object result = abstractInter.intercept(actionInvo);
return result;
}
}


AOP容器,根据已经实例化的被代理接口的实例返回实例化的代理接口的实例

public class AOPContainer {
isProxyed为已经实例化的被代理接口变量或者是实现了被代理接口的类的实例,方法返回已经被实例化的代理接口
public static Object getProxyInterface(Object isProxyed) {
Object obj = Proxy.newProxyInstance(
isProxyed.getClass().getClassLoader(),
isProxyed.getClass().getInterfaces(),
new InvocationHandlerImpl(isProxyed));
return obj;
}
}


过滤器与拦截器的区别

过滤器的本质为Servlet,在请求到达服务端的目的地之前,请求会先到达过滤器并由过滤器进行一定的处理后,再决定决定请求的分发方向,过滤器可以将请求原样转发给原请求的目的地,也可以直接响应重定向到其它目的地。

拦截器的本质是AOP,请求已经到达服务端的目的地,但是可以在进行请求的业务处理之前或之后添加其它的必要业务操作。

请求转发与响应重定向的区别

请求转发forward,A发出请求给B,B收到A的请求后将其原样转发给C,C对A的请求处理后响应A,整个过程A的请求地址不变,始终是对B的请求,A的请求最终由C处理并响应,但是A并不知道C,在A看来是B完成的请求并响应,A并未直接请求C,请求由B转发给C,但是C仍然知道请求是由A发出的,并对A做出响应而不是B,因为http请求报文中存储着请求的发送者A和接受者B,整个过程只发生了一次请求,一次响应,请求的数据在A、B、C三者之间共享,请求转发只能转发到本Web应用内的组件,如下

request.getRequestDispatcher(“/XX”).forward(request, response)


响应重定向redirect,A发出请求给B,B对A的请求进行处理后响应A并告知A去请求C,A收到B的响应后,A发出请求给C,C对A的请求进行处理后响应A,A的请求地址开始为B,重定向后A的请求地址变为C,地址的改变表明A重新发出了一个新的请求,整个过程发生了两次请求和响应,第一次请求B且B响应,第二次请求C且C响应,每次请求响应结束后request与response对象的生命周期结束,下次请求重新建立request与response对象,数据在两次请求响应之间不共享,可以重定向到网络上的任一资源,如下

response.sendRedirect(“/XX”);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: