微信开发中 ACCESS TOKEN 过期失效的解决方案详解
630
2022-10-25
Tomcat 源码分析 (设计模式) (七)
工厂模式模板方法模式门面模式观察者模式责任链模式命令模式适配器模式
文章目录
1.工厂模式2.模版方法模式3.观察者模式4.责任链模式5.外观模式6.适配器模式7.命令模式
1.工厂模式
Tomcat 启动的时候, Connector 组件的 startInternal() 方法:
//Connector.java protocolHandler.start(); //AbstractProtocol.java endpoint.start(); //AbstractEndpoint.java bind(); //JIoEndpoint.java public void bind() throws Exception { // Initialize thread count defaults for acceptor if (acceptorThreadCount == 0) { acceptorThreadCount = 1; } // Initialize maxConnections if (getMaxConnections() == 0) { // User hasn't set a value - use the default setMaxConnections(getMaxThreadsExecutor(true)); } if (serverSocketFactory == null) { if (isSSLEnabled()) { //获取serverSocket的工厂类 serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this); } else { //获取serverSocket的工厂类 serverSocketFactory = new DefaultServerSocketFactory(this); } } if (serverSocket == null) { try { if (getAddress() == null) { //调用工厂类创建实例 serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog()); } else { //调用工厂类创建实例 serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress()); } } catch (BindException orig) { String msg; if (getAddress() == null) msg = orig.getMessage() + "
2.模版方法模式
LifecycleBase类中的start()方法:
@Override public final synchronized void start() throws LifecycleException { if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) || LifecycleState.STARTED.equals(state)) { if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString("lifecycleBase.alreadyStarted", toString())); } return; } if (state.equals(LifecycleState.NEW)) { init(); } else if (state.equals(LifecycleState.FAILED)) { stop(); } else if (!state.equals(LifecycleState.INITIALIZED) && !state.equals(LifecycleState.STOPPED)) { invalidTransition(Lifecycle.BEFORE_START_EVENT); } setStateInternal(LifecycleState.STARTING_PREP, null, false); try { //抽象方法,子类具体实现 startInternal(); } catch (Throwable t) { // This is an 'uncontrolled' failure so put the component into the // FAILED state and throw an exception. ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t); } if (state.equals(LifecycleState.FAILED)) { // This is a 'controlled' failure. The component put itself into the // FAILED state so call stop() to complete the clean-up. stop(); } else if (!state.equals(LifecycleState.STARTING)) { // Shouldn't be necessary but acts as a check that sub-classes are // doing what they are supposed to. invalidTransition(Lifecycle.AFTER_START_EVENT); } else { setStateInternal(LifecycleState.STARTED, null, false); } }
子类实现的方法:
protected abstract void startInternal() throws LifecycleException;
3.观察者模式
LifecycleListener代表的是抽象观察者,它定义了一个lifecycleEvent方法,这个方法就是当主题变化时要执行的方法。ServerLifecycleListener代表的是具体的观察者,它实现了 LifecycleListener接口的方法,就是这个具体的观察者具体的实现方式
Lifecycle接口代表的是抽象主题,它定义了管理观察者的方法和它要做的其他方法。而StandardServer代表的是具体主题,它实现了抽象 主题的所有方法。这里Tomcat对观察者做了扩展,增加了另外两个类:LifecycleSupport和LifecycleEvent,它们作为辅助 类扩展了观察者的功能。LifecycleEvent可以定义事件类別,对不同的半件可区别处理,更加灵活LifecycleSupport类代理了主 题对多观察者的管理,将这个管理抽出来统一实现,以后如果修改只要修改LifecycleSupport类就可以了,不需要去修改所有的具体主题,因为所有具体主题对观察者的操作都被代理给LifecycleSupport类了
LifecycleBase.java
setStateInternal(LifecycleState.STARTED, null, false); ... private synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException { if (log.isDebugEnabled()) { log.debug(sm.getString("lifecycleBase.setState", this, state)); } if (check) { // Must have been triggered by one of the abstract methods (assume // code in this class is correct) // null is never a valid state if (state == null) { invalidTransition("null"); // Unreachable code - here to stop eclipse complaining about // a possible NPE further down the method return; } // Any method can transition to failed // startInternal() permits STARTING_PREP to STARTING // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to // STOPPING if (!(state == LifecycleState.FAILED || (this.state == LifecycleState.STARTING_PREP && state == LifecycleState.STARTING) || (this.state == LifecycleState.STOPPING_PREP && state == LifecycleState.STOPPING) || (this.state == LifecycleState.FAILED && state == LifecycleState.STOPPING))) { // No other transition permitted invalidTransition(state.name()); } } this.state = state; String lifecycleEvent = state.getLifecycleEvent(); if (lifecycleEvent != null) { fireLifecycleEvent(lifecycleEvent, data); } } ... protected void fireLifecycleEvent(String type, Object data) { lifecycle.fireLifecycleEvent(type, data); } ...
LifecycleSupport.java
/** * Notify all lifecycle event listeners that a particular event has * occurred for this Container. The default implementation performs * this notification synchronously using the calling thread. * * @param type Event type * @param data Event data */ public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); for (LifecycleListener listener : listeners) { listener.lifecycleEvent(event); } }
Tomcat的组件生命周期状态只要一变化,Tomcat就会通知改组件的所有的观察者,把状态变化通知到所有的观察者,看是否有观察者对相关组件的状态变化感兴趣。
4.责任链模式
Valve为阀门
通过getNext()获取到下一个阀门
实现类:
StandardWrapperValveStandardContextValveStandardHostValveStandardEngineValve
Tomcat的容器设置就是责任链模式,从Engine到Host再到Context —直到Wrapper都通过一个链传递请求.
Container扮演抽象处理者角色具体处理者:StandardEnginePipeline和Valve扩展了这个链的功能, 使得在链向下传递的过秤中,能够接收外界的干预。Pipeline就是连接每个子容器的管子,里面传递的Request和Response对象好比管子里流的水,而Valve就是在这个管子上开的一个个小孔子,让你有机会接触到里面的水,做一些额外 的事情。为了防止水被引出来而不流到下一个容器中,在每一段管子最后总有一个节点保证它一定能流到下一个子容器,所以每个容器都有一个StandardXXXValve
5.外观模式
外观模式又叫门面模式, 外观模式主要功能是封装了子系统的具体实现,提供统一的外观类给外部系统,这样当子系统内部实现发生变化的时候,不会影响到外部系统。
request,response,session等常用类都使用了外观设计模式。
request.getSession()
//RequestFacade.java @Override public HttpSession getSession() { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } return getSession(true); } //Request.java @Override public HttpSession getSession(boolean create) { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } if (SecurityUtil.isPackageProtectionEnabled()){ return AccessController. doPrivileged(new GetSessionPrivilegedAction(create)); } else { //委托给了request,而request是Request的实例 return request.getSession(create); } } /** * Return the session associated with this Request, creating one * if necessary and requested. * * @param create Create a new session if one does not exist */ @Override public HttpSession getSession(boolean create) { Session session = doGetSession(create); if (session == null) { return null; } return session.getSession(); } //StandardSession.java /** * Return the HttpSession
for which this object * is the facade. */ @Override public HttpSession getSession() { if (facade == null){ if (SecurityUtil.isPackageProtectionEnabled()){ final StandardSession fsession = this; facade = AccessController.doPrivileged( new PrivilegedAction
HttpRequestFacade类封装了 HttpRequest接口,能够提供数据,通过HttpRequestFacade访问到的数据都被代理到HttpRequest中,通常被封装的对象都被设为Private或者Protected,以防止在Facade中被直接访问。
6.适配器模式
CoyoteAdapter
连接器调用 CoyoteAdapter 的 sevice 方法,传入的是 Tomcat Request 对象,CoyoteAdapter 负责将 Tomcat Request 转成 ServletRequest,再调用容器的 service 方法
Connector.java
@Override protected void initInternal() throws LifecycleException { super.initInternal(); if (protocolHandler == null) { throw new LifecycleException( sm.getString("coyoteConnector.protocolHandlerInstantiationFailed")); } // Initialize adapter 初始化适配器 adapter = new CoyoteAdapter(this); protocolHandler.setAdapter(adapter); if (service != null) { protocolHandler.setUtilityExecutor(service.getServer().getUtilityExecutor()); } // Make sure parseBodyMethodsSet has a default if (null == parseBodyMethodsSet) { setParseBodyMethods(getParseBodyMethods()); } if (protocolHandler.isAprRequired() && !AprStatus.isInstanceCreated()) { throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener", getProtocolHandlerClassName())); } if (protocolHandler.isAprRequired() && !AprStatus.isAprAvailable()) { throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary", getProtocolHandlerClassName())); } if (AprStatus.isAprAvailable() && AprStatus.getUseOpenSSL() && protocolHandler instanceof AbstractHttp11jsseProtocol) { AbstractHttp11JsseProtocol> jsseProtocolHandler = (AbstractHttp11JsseProtocol>) protocolHandler; if (jsseProtocolHandler.isSSLEnabled() && jsseProtocolHandler.getSslImplementationName() == null) { // OpenSSL is compatible with the JSSE configuration, so use it if APR is available jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName()); } } try { protocolHandler.init(); } catch (Exception e) { throw new LifecycleException( sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e); } }
CoyoteAdapter.service()
@Override public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception { Request request = (Request) req.getNote(ADAPTER_NOTES); Response response = (Response) res.getNote(ADAPTER_NOTES); if (request == null) { // Create objects request = connector.createRequest(); request.setCoyoteRequest(req); response = connector.createResponse(); response.setCoyoteResponse(res); // Link objects request.setResponse(response); response.setRequest(request); // Set as notes req.setNote(ADAPTER_NOTES, request); res.setNote(ADAPTER_NOTES, response); // Set query string encoding req.getParameters().setQueryStringCharset(connector.getURICharset()); }
7.命令模式
主要是AJP 和 HTTP 协议通过命令模式, 根据协议和IO实现的不同通过不同的Process子类去实现。
AjpProcessorAjpNioProcessorAjpAprProcessorHttp11ProcessorHttp11NioProcessorHttp11AprProcessor
每一种Processor 都有一种ProcessorHandler 而每一种协议处理类都有Handler 。
Connector 和 Container 的连接为命令模式:Connector 作为抽象请求者,HttpConnector 作为具体请求者。HttpProcessor 作为命令。Container 作为命令的抽象接受者,ContainerBase 作为具体的接受者。客户端就是应用服务器 Server 组件了。Server 首先创建命令请求者 HttpConnector 对象,然后创建命令 HttpProcessor 命令对象。再把命令对象交给命令接受者 ContainerBase 容器来处理命令。命令的最终是被 Tomcat 的 Container 执行的。命令可以以队列的方式进来,Container 也可以以不同的方式来处理请求,如 HTTP1.0 协议和 HTTP1.1 的处理方式就会不同。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~