`
cywhoyi
  • 浏览: 418686 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

TOM源码第一课

 
阅读更多

/*

  * Licensed to the Apache Software Foundation (ASF) under one or more

  * contributor license agreements.  See the NOTICE file distributed with

  * this work for additional information regarding copyright ownership.

  * The ASF licenses this file to You under the Apache License, Version 2.0

  * (the "License"); you may not use this file except in compliance with

  * the License.  You may obtain a copy of the License at

  * 

  *      http://www.apache.org/licenses/LICENSE-2.0

  * 

  * Unless required by applicable law or agreed to in writing, software

  * distributed under the License is distributed on an "AS IS" BASIS,

  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  * See the License for the specific language governing permissions and

  * limitations under the License.

  */ 

  

 package javax.servlet;

 

 import java.io.IOException;

 

 

 /**

  * Defines methods that all servlets must implement.

  *

  * <p>A servlet is a small Java program that runs within a Web server.

  * Servlets receive and respond to requests from Web clients,

  * usually across HTTP, the HyperText Transfer Protocol. 

  *

  * <p>To implement this interface, you can write a generic servlet

  * that extends

  * <code>javax.servlet.GenericServlet</code> or an HTTP servlet that

  * extends <code>javax.servlet.http.HttpServlet</code>.

  *

  * <p>This interface defines methods to initialize a servlet,

  * to service requests, and to remove a servlet from the server.

  * These are known as life-cycle methods and are called in the

  * following sequence:

  * <ol>

  * <li>The servlet is constructed, then initialized with the <code>init</code> method.

  * <li>Any calls from clients to the <code>service</code> method are handled.

  * <li>The servlet is taken out of service, then destroyed with the 

  * <code>destroy</code> method, then garbage collected and finalized.

  * </ol>

  *

  * <p>In addition to the life-cycle methods, this interface

  * provides the <code>getServletConfig</code> method, which the servlet 

  * can use to get any startup information, and the <code>getServletInfo</code>

  * method, which allows the servlet to return basic information about itself,

  * such as author, version, and copyright.

  *

  * @author     Various

  * @version     $Version$

  *

  * @see     GenericServlet

  * @see     javax.servlet.http.HttpServlet

  *

  */

 

 

 public interface Servlet {

 

     /**

      * Called by the servlet container to indicate to a servlet that the 

      * servlet is being placed into service.

      *

      * <p>The servlet container calls the <code>init</code>

      * method exactly once after instantiating the servlet.

      * The <code>init</code> method must complete successfully

      * before the servlet can receive any requests.

      *

      * <p>The servlet container cannot place the servlet into service

      * if the <code>init</code> method

      * <ol>

      * <li>Throws a <code>ServletException</code>

      * <li>Does not return within a time period defined by the Web server

      * </ol>

      *

      *

      * @param config            a <code>ServletConfig</code> object 

      *                    containing the servlet's

      *                     configuration and initialization parameters

      *

      * @exception ServletException     if an exception has occurred that

      *                    interferes with the servlet's normal

      *                    operation

      *

      * @see                 UnavailableException

      * @see                 #getServletConfig

      *

      */

 

     public void init(ServletConfig config) throws ServletException;

     

     

 

     /**

      *

      * Returns a {@link ServletConfig} object, which contains

      * initialization and startup parameters for this servlet.

      * The <code>ServletConfig</code> object returned is the one 

      * passed to the <code>init</code> method. 

      *

      * <p>Implementations of this interface are responsible for storing the 

      * <code>ServletConfig</code> object so that this 

      * method can return it. The {@link GenericServlet}

      * class, which implements this interface, already does this.

      *

      * @return        the <code>ServletConfig</code> object

      *            that initializes this servlet

      *

      * @see         #init

      *

      */

 

     public ServletConfig getServletConfig();

     

     

 

     /**

      * Called by the servlet container to allow the servlet to respond to 

      * a request.

      *

      * <p>This method is only called after the servlet's <code>init()</code>

      * method has completed successfully.

      * 

      * <p>  The status code of the response always should be set for a servlet 

      * that throws or sends an error.

      *

      * 

      * <p>Servlets typically run inside multithreaded servlet containers

      * that can handle multiple requests concurrently. Developers must 

      * be aware to synchronize access to any shared resources such as files,

      * network connections, and as well as the servlet's class and instance 

      * variables. 

      * More information on multithreaded programming in Java is available in 

      * <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">

      * the Java tutorial on multi-threaded programming</a>.

      *

      *

      * @param req     the <code>ServletRequest</code> object that contains

      *            the client's request

      *

      * @param res     the <code>ServletResponse</code> object that contains

      *            the servlet's response

      *

      * @exception ServletException     if an exception occurs that interferes

      *                    with the servlet's normal operation 

      *

      * @exception IOException         if an input or output exception occurs

      *

      */

 

     public void service(ServletRequest req, ServletResponse res)

     throws ServletException, IOException;

     

     

 

     /**

      * Returns information about the servlet, such

      * as author, version, and copyright.

      * 

      * <p>The string that this method returns should

      * be plain text and not markup of any kind (such as HTML, XML,

      * etc.).

      *

      * @return         a <code>String</code> containing servlet information

      *

      */

 

     public String getServletInfo();

     

     

 

     /**

      *

      * Called by the servlet container to indicate to a servlet that the

      * servlet is being taken out of service.  This method is

      * only called once all threads within the servlet's

      * <code>service</code> method have exited or after a timeout

      * period has passed. After the servlet container calls this 

      * method, it will not call the <code>service</code> method again

      * on this servlet.

      *

      * <p>This method gives the servlet an opportunity 

      * to clean up any resources that are being held (for example, memory,

      * file handles, threads) and make sure that any persistent state is

      * synchronized with the servlet's current state in memory.

      *

      */

 

     public void destroy();

 }

 在Servlet接口中声明了5个方法里,init(),service(),destory()方法是与servlet的生命周期相关的方法,当实例化某个servlet类后,Servlet容器会调用其init()方法进行初始化,至于Servlet容器是如何调用,后面会分析。后面会被类与类之间的衔接来做一定的分析。在servlet接收任何请求之前,必须是经过正确初始化的。一般情况下init()方法可以留空。

 当servlet的一个客户端请求到达后,servlet容器就调用相应的servlet的service()方法,并将javax.serlvet.servletRequest对象和javax.servlet.servletResponse对象作为参数传入,ServletResquest对象包含客户端的HTTP请求的信息,ServletResponse对象则封装servlet的请求信息。这两个类的设计十分有趣,在后面就具体分析这两个类。在servlet对象的整个生命周期内,service()方法会被多次调用。

 在将servlet实例从服务中移除前,servlet容器会调用servlet实例的destory()方法,一般当Servlet容器关闭或servlet容器要释放内存时,才会将servlet实例移除,而且只有当servlet实例的service()方法中的线程都退出或执行超时后,才会调用destory()方法,当servlet容器调用了某个servlet实例的destory()方法后,它就不再调用该servlet实例的service()方法了,调用destory()方法让servlet对象有机会去清理自身持有的资源,如内存,文件句柄和线程等,确保有所的持久化与内存中该servlet对象的当前状态同步。

 下面<how tomcat work>中的一个servlet类:

 import javax.servlet.*;

 import java.io.IOException;

 import java.io.PrintWriter;

 public class PrimitiveServlet implements Servlet {

 public void init(ServletConfig config) throws ServletException {

 System.out.println("init");

 }

 public void service(ServletRequest request, ServletResponse response)

 throws ServletException, IOException {

 System.out.println("from service");

 PrintWriter out = response.getWriter();

 out.println("Hello. Roses are red.");

 out.print("Violets are blue.");

 }

 public void destroy() {

 System.out.println("destroy");

 }

 public String getServletInfo() {

 return null;

 }

 public ServletConfig getServletConfig() {

 return null;

 }

 }

 一个功能齐全的servlet容器有以下几件事要做:

 1,当第一次调用某个servlet,要载入该servlet类,并调用其init()方法(仅此一次);

 2,针对每个request请求,创建一个javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例;

 3,调用该servlet的service()方法,将servletRequest对象和servletResponse对象作为参数传入;

 4,当关闭该servlet类时,调用其destory()方法,并卸载该servlet类。

 

 那么从客户连接到tomcat上来,最重要要做的事就是如何处理客户的请求并且把请求传递给Servlet容器,虽然看起来很简单,但是这整个过程确是如此的繁杂,包括字符串的解析,以及cookies,session,参数请求等等的工作。那么我们首先的工作就是分析客户连接到tomcat上来这一块,也就是tomcat的默认连接器。

 

 Tomcat的连接器必须实现org.apache.catalina.Connecor接口,在接口中声明了很多方法,其中最重要的是getContainer(),setContainer(),createRequest(),createResponse()方法。为什么这么说呢?看看以下分析:

 setContainer()方法用于将连接器和某个servlet容器相关联。如果不跟特定的servlet容器关联起来,我靠,你准备要把包装好的HttpRequest和HttpResponse对象传给谁阿??

 getContainer()方法返回与当前连接器相关联的servlet容器。createRequest()方法会引入的HTTP请求创建request对象,相应的,createResponse()方法会创建一个response对象。

 org.apache.catalina.connector.http.HttpConnector类实现了Connector接口,首先大概说以下HttpConnector类做的一些工作:

 1,首先它实现了org.apache.catalina.Connector接口(使其可以成为Catalina中的连接器),又实现了java.lang.Runnble接口(确保它的实例在自己的线程中运行)和实现了org.apache.catalina.Lifecycle接口,Lifecycle接口用于维护每个实现了该接口的每个Catalina组件的生命周期。但是这个接口目前不是重点,在后面会讲到。

 2,由于HttpConnector实现了Lifecycle接口,因此当创建一个HttpConnector实例后,就应该调用其initialize()方法和start()方法,这两个方法如何调用在后面会详细讲到,现在就记住一点:这两个方法只应该被调用一次。

 3,HttpConnector类还负责创建服务器套接字,这是最重要的一点,没有这个,啥事都不用做了。HttpConnector类的initialize()方法会调用一个私有方法open(),后者返回一个java.net.ServerSocket实例,赋值给成员变量serverSocket。但是,这里没有直接调用ServerSocket类的构造函数,而是通过open()方法从一个服务器套接字工厂得到一个实例。

 4,维护HttpProcessor实例:HttpProcessor实例是用来处理HTTP请求的,在Tomcat的默认连接器中,HttpConnector实例有一个HttpProcessor对象池,每个HttpProcessor实例都运行在其自己的线程中。这样HttpConnector实例就可以同时处理多个HTTP请求了。

 好了,接下来就是具体看看它们这几个步骤中tomcat源码的实现:

 首先我们从连接用户开始入手:

 org.apache.catalina.connector.http.HttpConnector

         /**

      * The shutdown signal to our background thread

      */

     private boolean stopped = false;

     

      /**

      * Use TCP no delay ?

      */

     private boolean tcpNoDelay = true;

     

       /**

      * Timeout value on the incoming connection.

      * Note : a value of 0 means no timeout.

      */

     private int connectionTimeout = Constants.DEFAULT_CONNECTION_TIMEOUT;

     

       /**

      * Has this component been started yet?

      */

     private boolean started = false;

     

     

      /**

      * The thread synchronization object.

      */

     private Object threadSync = new Object();

         

         //该方法运行在一个线程中

  // ---------------------------------------------- Background Thread Methods

 

 

     /**

      * The background thread that listens for incoming TCP/IP connections and

      * hands them off to an appropriate processor.

      */

     public void run() {

 

         // Loop until we receive a shutdown command

                //如果tomcat接收到shutdown的命令,那么将会关闭连接器

         while (!stopped) {

 

             // Accept the next incoming connection from the server socket

             Socket socket = null;

             try {

                 //                if (debug >= 3)

                 //                    log("run: Waiting on serverSocket.accept()");

                 socket = serverSocket.accept();//服务器等待用户的连接

                 //                if (debug >= 3)

                 //                    log("run: Returned from serverSocket.accept()");

                 if (connectionTimeout > 0)

                     socket.setSoTimeout(connectionTimeout);//设置超时时间

                 socket.setTcpNoDelay(tcpNoDelay);//启用/禁用 TCP_NODELAY

             } catch (AccessControlException ace) {

                 log("socket accept security exception", ace);

                 continue;

             } catch (IOException e) {

                 //                if (debug >= 3)

                 //                    log("run: Accept returned IOException", e);

                 try {

                     // If reopening fails, exit

                     synchronized (threadSync) {

                         if (started && !stopped)//如何其他组件还在运行或者socket还没关闭

                             log("accept error: ", e);

                         if (!stopped) {//如果socket还没关闭

                             //                    if (debug >= 3)

                             //                        log("run: Closing server socket");

                             serverSocket.close();//关闭服务器

                             //                        if (debug >= 3)

                             //                            log("run: Reopening server socket");

                             serverSocket = open();//创建新的serverSocket对象

                         }

                     }

                     //                    if (debug >= 3)

                     //                        log("run: IOException processing completed");

                 } catch (IOException ioe) {

                     log("socket reopen, io problem: ", ioe);

                     break;

                 } catch (KeyStoreException kse) {

                     log("socket reopen, keystore problem: ", kse);

                     break;

                 } catch (NoSuchAlgorithmException nsae) {

                     log("socket reopen, keystore algorithm problem: ", nsae);

                     break;

                 } catch (CertificateException ce) {

                     log("socket reopen, certificate problem: ", ce);

                     break;

                 } catch (UnrecoverableKeyException uke) {

                     log("socket reopen, unrecoverable key: ", uke);

                     break;

                 } catch (KeyManagementException kme) {

                     log("socket reopen, key management problem: ", kme);

                     break;

                 }

 

                 continue;

             }

 

             // Hand this socket off to an appropriate processor

             HttpProcessor processor = createProcessor();//从HttpProcessor获得一个HttpProcessor对象或者是当池中没有HttpProcessor对象。

             if (processor == null) {

                 try {

                     log(sm.getString("httpConnector.noProcessor"));

                     socket.close();//关闭socket

                 } catch (IOException e) {

                     ;

                 }

                 continue;

             }

             //            if (debug >= 3)

             //                log("run: Assigning socket to processor " + processor);

             processor.assign(socket);//处理HTTP请求

 

             // The processor will recycle itself when it finishes

 

         }

 

         // Notify the threadStop() method that we have shut ourselves down

         //        if (debug >= 3)

         //            log("run: Notifying threadStop() that we have shut down");

         synchronized (threadSync) {

             threadSync.notifyAll();//唤醒有所的线程

         }

 

     }

     这段代码衍生出来的需要注意的东西有很多,但是先说一点,上面的log()方法是日志记录,这里暂时不说它,后面会详细的说它。好了,现在要从这段代码开始来把握几点需要注意的地方。有些地方需要加上UML来进行解释会比较好!

     

     第一点需要关注的地方:serverSocket = open();我们来看看open()方法做了些什么事情先。首先它是一个私有的方法,也就是用户不能去重写它的方法。

    org.apache.catalina.connector.http.HttpConnector

    

     /**

      * The IP address on which to bind, if any.  If <code>null</code>, all

      * addresses on the server will be bound.

      */

     private String address = null;

     

     

      /**

      * The port number on which we listen for HTTP requests.

      */

     private int port = 8080;

     

     

      /**

      * The accept count for this Connector.

      */

     private int acceptCount = 10;

     

     

     

      private ServerSocket open()

     throws IOException, KeyStoreException, NoSuchAlgorithmException,

            CertificateException, UnrecoverableKeyException,

            KeyManagementException

     {

 

         // Acquire the server socket factory for this Connector

         ServerSocketFactory factory = getFactory();利用工厂方法来创建一个套接字

 

         // If no address is specified, open a connection on all addresses

         if (address == null) {

             log(sm.getString("httpConnector.allAddresses"));

             try {

                 return (factory.createSocket(port, acceptCount));//返回创建好了的套接字

             } catch (BindException be) {

                 throw new BindException(be.getMessage() + ":" + port);

             }

         }

 

         // Open a server socket on the specified address

         try {

             InetAddress is = InetAddress.getByName(address);//在给定主机名的情况下确定主机的IP地址

             log(sm.getString("httpConnector.anAddress", address));

             try {

                 return (factory.createSocket(port, acceptCount, is));

             } catch (BindException be) {

                 throw new BindException(be.getMessage() + ":" + address +

                                         ":" + port);

             }

         } catch (Exception e) {

             log(sm.getString("httpConnector.noAddress", address));

             try {

                 return (factory.createSocket(port, acceptCount));

             } catch (BindException be) {

                 throw new BindException(be.getMessage() + ":" + port);

             }

         }

 

     }

     看看open()方法:很简单,不多说。主要要加索,保证线程安全

       /**

      * Return the server socket factory used by this Container.

      */

     public ServerSocketFactory getFactory() {

 

         if (this.factory == null) {

             synchronized (this) {

                 this.factory = new DefaultServerSocketFactory();

             }

         }

         return (this.factory);

 

     }

     

     

     那么从上面的代码用到了工厂设计模式,具体继续跟踪源码的实现:

     apache.catalina.net.ServerSocketFactory,该类是一个接口,提供了三个方法:

     其实也就是java.net.ServerSocket的三个方法构造,只不过换了以下名字调用而已,它的子类DefaultServerSocketFactory实现了这个接口,并且这个类是fianl类,不可以被集成。具体看看这个类的实现:

     /*

  * Licensed to the Apache Software Foundation (ASF) under one or more

  * contributor license agreements.  See the NOTICE file distributed with

  * this work for additional information regarding copyright ownership.

  * The ASF licenses this file to You under the Apache License, Version 2.0

  * (the "License"); you may not use this file except in compliance with

  * the License.  You may obtain a copy of the License at

  * 

  *      http://www.apache.org/licenses/LICENSE-2.0

  * 

  * Unless required by applicable law or agreed to in writing, software

  * distributed under the License is distributed on an "AS IS" BASIS,

  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  * See the License for the specific language governing permissions and

  * limitations under the License.

  */

 

 

 package org.apache.catalina.net;

 

 

 import java.io.IOException;

 import java.net.InetAddress;

 import java.net.ServerSocket;

 import java.security.KeyStoreException;

 import java.security.NoSuchAlgorithmException;

 import java.security.UnrecoverableKeyException;

 import java.security.KeyManagementException;

 import java.security.cert.CertificateException;

 import org.apache.catalina.net.ServerSocketFactory;

 

 

 /**

  * Default server socket factory, which returns unadorned server sockts.

  *

  * @author db@eng.sun.com

  * @author Harish Prabandham

  * @author Craig R. McClanahan

  */

 

 public final class DefaultServerSocketFactory implements ServerSocketFactory {

 

 

     // --------------------------------------------------------- Public Methods

 

 

     /**

      * Returns a server socket which uses all network interfaces on

      * the host, and is bound to a the specified port.  The socket is

      * configured with the socket options (such as accept timeout)

      * given to this factory.

      *

      * @param port the port to listen to

      *

      * @exception IOException                input/output or network error

      * @exception KeyStoreException          error instantiating the

      *                                       KeyStore from file (SSL only)

      * @exception NoSuchAlgorithmException   KeyStore algorithm unsupported

      *                                       by current provider (SSL only)

      * @exception CertificateException       general certificate error (SSL only)

      * @exception UnrecoverableKeyException  internal KeyStore problem with

      *                                       the certificate (SSL only)

      * @exception KeyManagementException     problem in the key management

      *                                       layer (SSL only)

      */

     public ServerSocket createSocket (int port)

     throws IOException, KeyStoreException, NoSuchAlgorithmException,

            CertificateException, UnrecoverableKeyException,

            KeyManagementException {

 

         return (new ServerSocket(port));

 

     }

 

 

     /**

      * Returns a server socket which uses all network interfaces on

      * the host, is bound to a the specified port, and uses the

      * specified connection backlog.  The socket is configured with

      * the socket options (such as accept timeout) given to this factory.

      *

      * @param port the port to listen to

      * @param backlog how many connections are queued

      *

      * @exception IOException                input/output or network error

      * @exception KeyStoreException          error instantiating the

      *                                       KeyStore from file (SSL only)

      * @exception NoSuchAlgorithmException   KeyStore algorithm unsupported

      *                                       by current provider (SSL only)

      * @exception CertificateException       general certificate error (SSL only)

      * @exception UnrecoverableKeyException  internal KeyStore problem with

      *                                       the certificate (SSL only)

      * @exception KeyManagementException     problem in the key management

      *                                       layer (SSL only)

      */

     public ServerSocket createSocket (int port, int backlog)

     throws IOException, KeyStoreException, NoSuchAlgorithmException,

            CertificateException, UnrecoverableKeyException,

            KeyManagementException {

 

         return (new ServerSocket(port, backlog));

 

     }

 

 

     /**

      * Returns a server socket which uses only the specified network

      * interface on the local host, is bound to a the specified port,

      * and uses the specified connection backlog.  The socket is configured

      * with the socket options (such as accept timeout) given to this factory.

      *

      * @param port the port to listen to

      * @param backlog how many connections are queued

      * @param ifAddress the network interface address to use

      *

      * @exception IOException                input/output or network error

      * @exception KeyStoreException          error instantiating the

      *                                       KeyStore from file (SSL only)

      * @exception NoSuchAlgorithmException   KeyStore algorithm unsupported

      *                                       by current provider (SSL only)

      * @exception CertificateException       general certificate error (SSL only)

      * @exception UnrecoverableKeyException  internal KeyStore problem with

      *                                       the certificate (SSL only)

      * @exception KeyManagementException     problem in the key management

      *                                       layer (SSL only)

      */

     public ServerSocket createSocket (int port, int backlog,

                                       InetAddress ifAddress)

     throws IOException, KeyStoreException, NoSuchAlgorithmException,

            CertificateException, UnrecoverableKeyException,

            KeyManagementException {

 

         return (new ServerSocket(port, backlog, ifAddress));

 

     }

 是吧,是java.nio.ServerSocket类的三个构造方法吧。port端口号,backlog可接收的队列长度,ifAddress要将服务器绑定到的InetAddress

分享到:
评论

相关推荐

    Tom_深入分析Spring源码

    《Spring源码分析》这份资料深入探讨了Spring框架的核心机制,尤其聚焦于Spring5版本。...Tom老师的这份资料无疑是一份宝贵的资源,它将引导我们逐步揭开Spring的奥秘,让我们在编程旅程中更进一步。

    会说话的Tom猫 anroid源码

    总的来说,"会说话的Tom猫"的源码是一个很好的Android音频处理和游戏开发的实践案例。通过研究和分析,开发者可以深入理解Android音频API的使用、UI交互设计以及多媒体资源的管理,进一步提升自己的开发技能。

    易语言TOM猫动画易语言源码.rar

    易语言TOM猫动画易语言源码.rar 易语言TOM猫动画易语言源码.rar 易语言TOM猫动画易语言源码.rar 易语言TOM猫动画易语言源码.rar 易语言TOM猫动画易语言源码.rar 易语言TOM猫动画易语言源码.rar

    Spring5 源码分析(第 2 版)-某Tom老师

    《Spring5 源码分析(第 2 版)》是某Tom老师精心编写的深度解析文档,旨在帮助读者全面理解Spring5的核心机制和设计理念。Spring作为Java领域最为广泛应用的框架之一,其源码的深入理解对于开发者来说至关重要。这篇...

    4个Scratch趣味小游戏源码包含Scratch方块跑酷游戏源码Scratc飞机大战游戏源码管道Tom游戏源码等

    在这个压缩包中,包含了四个基于Scratch的小游戏源码,分别是“方块跑酷1.0.sb2”、“管道Tom.sb2”、“归家弹球.sb2”以及“飞机大战1.0.sb2”。这些源码是学习和理解Scratch编程逻辑的绝佳资源。 1. **Scratch...

    易语言POST注册Tom邮箱源码.rar

    易语言POST注册Tom邮箱源码.rar

    tom猫游戏源码 iOS

    //序列帧动画 播放一组图片 //指定动画图片的数组 NSMutableArray *arrayM = [NSMutableArray array]; //添加动画播放的素材 for (int i = 0; i; i++) { NSString *imageName = [NSString stringWithFormat:@...

    咕泡学院_Tom_JavaVIP课程_深入分析Spring源码(第一阶段)1

    4. **JDBC 支持**:Spring 提供了一个简单的 JDBC 抽象层,减少了直接使用 JDBC 的繁琐,同时支持与第三方持久层框架(如 Hibernate、JPA)的集成。 5. **Java EE 整合**:Spring 可以很好地与 Java EE 技术(如 ...

    易语言源码TOM猫动画易语言源码.rar

    "TOM猫动画"源码示例是用易语言编写的,可能是实现了一个类似经典手机应用"会说话的Tom猫"的动画效果。在这个项目中,开发者可能利用了易语言的基础语法、图形用户界面(GUI)设计、事件驱动编程等技术来创建TOM猫的...

    易语言POST注册Tom邮箱源码.zip易语言项目例子源码下载

    易语言POST注册Tom邮箱源码.zip易语言项目例子源码下载易语言POST注册Tom邮箱源码.zip易语言项目例子源码下载 1.合个人学习技术做项目参考 2.适合学生做毕业设计参考 3.适合小团队开发项目参考

    Tom Spring5源码分析

    ### Tom Spring5源码分析 #### 一、Spring框架中常用的设计模式 ##### 1. 设计模式概览 在软件工程领域,设计模式是指针对某一类问题的最优解决方案。通常所说的23种经典设计模式涵盖了面向对象设计的各个方面,...

    Tom_深入分析Spring源码doc

    本篇文章将针对“Tom_深入分析Spring源码doc”中的关键知识点进行详细的阐述。 1. **依赖注入(Dependency Injection,DI)** Spring的核心特性之一就是依赖注入,它使得组件间的依赖关系由Spring容器管理,而不是...

    TOM舞曲网(DIV+CSS) -ASP源码.zip

    【标题】"TOM舞曲网(DIV+CSS) -ASP源码.zip"指的是一个基于ASP编程语言构建的网站源代码,它采用了现代网页设计技术DIV+CSS进行布局。这个源码可能是为一个名为"TOM舞曲网"的在线音乐平台设计的,允许用户浏览、播放...

    scratch2源码管道Tom

    scratch2源码管道Tom提取方式是百度网盘分享地址

    H5游戏源码 Tom猫.zip

    【H5游戏源码 Tom猫.zip】是一款基于HTML5技术开发的游戏源代码,它提供了创建互动体验的基础,尤其是移动端的轻量级娱乐应用。H5游戏源码是使用HTML、CSS和JavaScript等Web技术编写的,可在现代浏览器上运行,无需...

    最新微信砍价源码 微砍价营销 tom砍价源码discuz插件4.1

    本模块是基于discuz程序开发的功能插件,UTF-8版本 新版特色功能: 1、增加了全部砍价活动列表; 2、增加了使用认证服务号自动获取用户信息的功能; 3、增加了允许开启关闭帮砍价必须关注授权认证服务号的功能,...

    TOM 微助力3.0源码

    5、用户在转发助力时,同一用户多次转发、助力,只有记录一次; 6、后台可以修改用户转发和助力数据,商家和站长可以控制中奖排名(允许作弊,内定中奖); 7、用户报名参加后 &gt;&gt; 分享转发 &gt;&gt; 好友点击和转发该用户...

    spring源码

    Spring框架是Java开发中的核心组件,它为应用程序提供了一个全面的基础设施,支持...通过分析源码,开发者还可以了解到如何设计和实现一个可扩展、可维护的框架,这对于提升自身的技术水平和解决问题的能力大有裨益。

    如何切割tomtom地图

    在TomTom HOME软件中,登录您的账户,然后在主菜单的第一页选择“新增地图”。这里会显示出您已购买的所有地图数据。找到需要分割的地图,点击其下方的“更多信息”链接。 此时,TomTom HOME会显示地图的详细信息,...

    how tom cat works中文PDF+源码

    《How Tomcat Works》中文版及源码的结合,为学习者提供了一条深入了解Tomcat的途径。通过阅读书籍,我们可以理解Tomcat的基本概念和工作流程;而源码分析则能帮助我们深入到细节,理解其设计思想和实现方式。对于...

Global site tag (gtag.js) - Google Analytics