深入Jetty源码之Servlet框架及实现(Servlet、Filter、Registration)

时间:2022-09-25 14:34:29

概述

Servlet是Server Applet的缩写,即在服务器端运行的小程序,而Servlet框架则是对HTTP服务器(Servlet Container)和用户小程序中间层的标准化和抽象。这一层抽象隔离了HTTP服务器的实现细节,而Servlet规范定义了各个类的行为,从而保证了这些“服务器端运行的小程序”对服务器实现的无关性(即提升了其可移植性)。
在Servlet规范有以下几个核心类(接口):
ServletContext:定义了一些可以和Servlet Container交互的方法。
Registration:实现Filter和Servlet的动态注册。
ServletRequest(HttpServletRequest):对HTTP请求消息的封装。
ServletResponse(HttpServletResponse):对HTTP响应消息的封装。
RequestDispatcher:将当前请求分发给另一个URL,甚至ServletContext以实现进一步的处理。
Servlet(HttpServlet):所有“服务器小程序”要实现了接口,这些“服务器小程序”重写doGet、doPost、doPut、doHead、doDelete、doOption、doTrace等方法(HttpServlet)以实现响应请求的相关逻辑。
Filter(FilterChain):在进入Servlet前以及出Servlet以后添加一些用户自定义的逻辑,以实现一些横切面相关的功能,如用户验证、日志打印等功能。
AsyncContext:实现异步请求处理。

Jetty中的Holder

在Jetty中,每个Servlet和其相关信息都由ServletHolder封装,并且将Servlet相关操作代理给ServletHolder;同理,对Filter也有FilterHolder与其相对应;另外ServletHolder和FilterHolder都继承自Holder实例。在Servlet 3.0中引入动态向ServletContext注册Servlet和Filter,并返回相应的Registration实例,用于进一步配置与其关联的Servlet和Filter,因而Registration也是和ServletHolde和FilterHolder相关联的接口。在Jetty中,他们的类关系图如下:
深入Jetty源码之Servlet框架及实现(Servlet、Filter、Registration)

Servlet

Servlet和Filter是Servlet规范中用于定义用户逻辑实现的接口,Servlet是最初的版本,所有的“服务器端小程序”都要实现该接口,并交由Servlet Container管理其实例,负责其生命周期,以及当相应请求到来时调用相应方法。Servlet接口非常简单:

public interface Servlet {
    // Servlet Container在创建一个Servlet后调用该方法,并传入ServletConfig实例,从而用户可以在这个方法中做一些自定义的初始化工作,如初始化数据库连接等。
    // 并且Servlet Container可以保证一个Servlet实例init方法之后被调用一次,但是对一个Servlet类init方法可能会被多次调用,因而有些Servlet Container可能会在某些情况下将某些
    // Servlet移出Servlet Container,而后又重新加载这些Servlet,如为了在处理Servlet Container资源压力比较大的情况下。
    public void init(ServletConfig config) throws ServletException;

// 返回在init方法中传入的ServletConfig实例。ServletConfig包含了在web.xml配置文件中配置当前Servlet的初始化参数,并且可以使用该ServletConfig实例获取当前ServletContext实例。
    public ServletConfig getServletConfig();
    
    // 当该Servlet对应的请求到来时,Servlet Container会调用这个Servlet的service方法,用于处理请求,并将相应写入ServletResponse参数中,该方法只能在init方法完成后被调用。
    // 在service方法中,可以选择使用ServletResponse定义的方法返回响应给客户端,或只是向ServletResponse中写入响应,最终由Servlet Container根据ServletResponse的信息将响应返回给客户端。
    // 很多情况下,Servlet Container都不会使用多线程来处理客户请求,应该该方法会在多线程环境下被使用,Servlet实现者可以实现SingleThreadMode接口以强制该方法只在单线程的环境下被使用。
    // 但是SingleThreadMode接口已经在Servlet 2.3中被废弃,实现该接口也会影响Servlet的执行性能,而且有些Servlet Container会选择实例或多个Servlet实例,以保证对请求的响应性能,因而此时依然不能保证该方法的单线程特性,因而不建议使用这个SingleThreadMode接口。
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
    
    // 返回当前Servlet的描述信息,如作者、版本号、版权等。在GenericServlet默认实现中,返回空字符串。
    public String getServletInfo();

// 当Servlet Container销毁当前Servlet时会调用该方法,从而给Servlet提供拥有清理当前Servlet占用的资源的地方,如关闭和数据库的连接等。
    // Servlet Container会保证该方法在所有执行service方法的线程完成或超时后被调用。Servlet Container一般会在三种情况下会调用该方法:
    // 1. Servlet Container当前资源比较紧张,需要将一些不再用或不常用的Servlet移出;2. 实现某些Servlet的热部署;3. 当前Web Application被停止。
    public void destroy();
}

对每个Servlet都有一个ServletConfig实例和其对应,ServletConfig中包含了在web.xml文件中定义的Servlet的init-param参数,并且可以使用ServletConfig实例获取ServletContext实例:

public interface ServletConfig {
    // 返回该ServletConfig对应的Servlet的名称,在web.xml文件中定义的Servlet名称或对于没有注册的Servlet为其类名。
    public String getServletName();

// 返回和其关联的ServletContext。
    public ServletContext getServletContext();
    
    // 返回在web.xml配置文件中定义或者使用ServletRegistration动态定义添加的init-param参数。
    public String getInitParameter(String name);
    public Enumeration<String> getInitParameterNames();
}

在Jetty中,不管是在web.xml中配置的Servlet还是使用ServletContext动态注册并使用ServletRegistration.Dynamic动态配置的Servlet,在ServletHandler内部都使用ServletHolder来表示一个Servlet,并且由ServletHolder来处理所有和Servlet相关的逻辑。ServletHolder的实现逻辑在之后给出。
Servlet框架中默认实现了两个Servlet:GenericServlet和HttpServlet,GenericServlet只是对Servlet的简单实现,而HttpServlet会根据请求中的方法将请求分发给相应的:doGet/doPost/doPut/doHead/doOptions/doTrace等方法,它还提供了getLastModified()方法,重写该方法用于实现条件GET。以上这些方法(除doOptions和doTrace已经有具体的逻辑实现)默认实现直接方法405 Method Not Allowed响应(Http/1.1)或404 Bad Request响应(HTTP/1.0)。重写相应的方法以实现各个Method对应的逻辑。

Filter

在Servlet 2.3开始引入了Filter机制,以在Servlet的service方法的执行前后添加一些公共的Filter逻辑,为面向切面的编程提供了很大的便利,这些公共的逻辑如纪录一个Request从进入Servlet Container到出所花费的总时间、为每个Request添加一些额外的信息以帮助之后处理、对所有或特定Request添加用户验证功能等。Filter可以在web.xml文件中定义,由Servlet Container负责其实例化、初始化以及doFilter方法的调用。在Servlet 3.0以后,还支持动态的给ServletContext注册Filter,并由返回的FilterRegistration.Dynamic实例做进一步的配置。Filter的接口定义也是比较简单:

public interface Filter {
    // 由ServletContainer在初始化一个Filter时调用,Filter的实现者可以在该方法中添加一些用户自定义的初始化逻辑,同时可以保存FilterConfig实例,它可以获取定义的init-param初始化参数以及获取ServletContext实例。其他情况和Servlet类似,不赘述。
    public void init(FilterConfig filterConfig) throws ServletException;
    
    // 每一次请求到来都会穿越配置的FilterChain,执行配置的Servlet,然后从这个FilterChain中返回。在doFilter方法的实现中,要调用下一个Filter,使用FilterChain的doFilter方法。
    // 在调用FilterChain的doFilter之前为执行请求之前的处理,而之后为请求已经执行完成,在响应返回的路上的逻辑处理。也可以步调用FilterChain的doFilter方法,以阻止请求的进一步处理。
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException;

// 在Filter被移出Servlet Container时调用,它和Servlet类似,不赘述。**
    public void destroy();
}

Filter接口中包含对FilterConfig以及FilterChain的使用,FilterConfig和ServletConfig定义、实现以及逻辑都类似:

public interface FilterConfig {
    public String getFilterName();
    public ServletContext getServletContext();
    public String getInitParameter(String name);
    public Enumeration<String> getInitParameterNames();
}

FilterChain是Servlet中将Filter链以Channel的方式连接在一起的类,它实现了可以向执行Servlet前和后都添加一些切面逻辑,甚至阻止Servlet的执行,Filter的实现者使用FilterChain的doFilter方法调用在这个链中的下一个Filter的doFilter方法,如果当前Filter是链中最后一个Filter,则调用响应的Servlet。其接口定义如下:

public interface FilterChain {
    // 调用该方法会调用Filter链中的下一个Filter的doFilter方法,如果当前Filter是这条链中的最后一个Filter,则该方法会调用响应的Servlet的service方法。
    public void doFilter (ServletRequest request, ServletResponse response) throws IOException, ServletException;
}

在Jetty中,ServletHandler的内部类Chain实现了FilterChain接口,在构造Chain实例时,首先根据Request的URL以及对应Servlet Name查找所有相关的Filter列表,然后使用这个Filter列表、Request实例、当前请求对应的ServletHolder创建这个链,在其doFilter方法实现中,它会存储一个_filter索引,它指向下一个Filter实例,当每个Filter调用doFilter方法时,Chain会根据这个索引获取下一个Filter实例,并将该索引向后移动,从而调用下一个Filter的doFilter方法,如果这个索引值到达最后一个Filter链中的Filter,且有ServletHolder实例存在,则调用该ServletHolder的handle方法,否则调用notFound方法,即向客户端发送404 NOT FOUND响应。如果Filter不支持ASYNC模式,则在调用其doFilter之前,需要将Request的ASYNC支持设置为false。
在ServletHandler中还有CachedChain实现了FilterChain接口,它以链表的形式纪录找到的Filter列表,并将这个列表缓存在ServletHandler中,不同的dispatch类型有一个列表,并且可以根据请求的URL或请求的Servlet名来查找是否已经有缓存的Filter链表。
在ServletHandler中,可以使用setFilterChainsCached方法来配置是否使用CachedChain还是直接使用Chain,默认使用CachedChain。

Registration

Registration是Servlet 3.0规范中引入的接口,用于表示向ServletContext中动态注册的Servlet、Filter的实例,从而实现对这些动态注册的Servlet、Filter实例进行进一步的配置。 对于Servlet和Filter的配置,他们的共同点是他们有响应的Name、ClassName、Init Parameters以及asyncSupported属性,而这些方法正是Registration接口的定义。Registration接口将setAsyncSupport方法定义在其内部的Dynamic接口中,Dynamic用于表示这是用于动态的配置这个Servlet或Filter的含义,但是为什么要将这个方法放在Dynamic接口中呢?如何决定不同的方法应该是在Registration本身的接口中,而那些应该放到Dynamic接口中呢?

public interface Registration {
    // 返回这个Registration实例关联的Servlet或Filter的Name,这个Name在向ServletContext注册Servlet或Filter时给定。
    public String getName();

// 返回这个Registration实例关联的Servlet或Filter的类名。
    public String getClassName();

// 和这个Registration实例关联的初始化参数的操作。
    public boolean setInitParameter(String name, String value);
    public String getInitParameter(String name);
    public Set<String> setInitParameters(Map<String, String> initParameters);
    public Map<String, String> getInitParameters();

interface Dynamic extends Registration {
        // 配置Registration关联的Servlet或Filter是否支持异步操作。
        public void setAsyncSupported(boolean isAsyncSupported);
    }
}

Registration有两个子接口:ServletRegistration和FilterRegistration,分别用于表示Servlet相关的配置和Filter相关的配置。
对ServletRegistration,它可以设置Servlet的URL Mapping、RunAsRole属性、LoadOnStartup属性等:

public interface ServletRegistration extends Registration {
    // 添加URL patterns到这个ServletRegistration关联的Servlet的映射。如果有任意的URL patterns已经映射到其他的Servlet中,则该方法不会执行任何行为。
    public Set<String> addMapping(String... urlPatterns);

// 获取所有到当前ServletRegistration对应的Servlet的URL patterns。
    public Collection<String> getMappings();

// 获取当前ServletRegistration对应的Servlet的RunAsRole。
    public String getRunAsRole();

interface Dynamic extends ServletRegistration, Registration.Dynamic {
        // 设置当前ServletRegistration对应的Servlet的loadOnStartup等级。如果loadOnStartup大于或等于0,表示Servlet Container要优先初始化该Servlet,
        // 此时Servlet Container要在Container初始化时实例化并初始化该Servlet,即在所有注册的ContextListener的contextInitialized方法调用完成后。
        // 如果loadOnStartup小于0,则表示这个Servlet可以在用到的时候实例化并初始化。默认值为-1。
        public void setLoadOnStartup(int loadOnStartup);

// 设置ServletRegistration相关的ServletSecurityElement属性。
        public Set<String> setServletSecurity(ServletSecurityElement constraint);

// 设置ServletRegistration对应的Servlet的MultipartConfigElement属性。
        public void setMultipartConfig(MultipartConfigElement multipartConfig);

// 设置ServletRegistration对应的Servlet的RunAsRole属性。
        public void setRunAsRole(String roleName);
    }
}

对FilterRegistration,它可以配置Filter的URL Mapping和Servlet Mapping等:

public interface FilterRegistration extends Registration {
    // 添加FilterRegistration关联的Filter到Servlet的映射,使用Servlet Name、DispatcherType作为映射。isMatchAfter表示新添加的Mapping是在已有的Mapping之前还是之后。
    public void addMappingForServletNames(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames);

// 获取当前FilterRegistration关联的Filter已存在的到Servlet Name的映射。
    public Collection<String> getServletNameMappings();

// 添加FilterRegistration关联的Filter到Servlet的映射,使用URL patterns、DispatcherType作为映射。isMatchAfter表示新添加的Mapping是在已有的Mapping之前还是之后。
    public void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns);

// 获取当前FilterRegistration关联的Filter已存在的到URL patterns的映射。
    public Collection<String> getUrlPatternMappings();

interface Dynamic extends FilterRegistration, Registration.Dynamic {
    }
}

在Jetty中对Registration的实现在Holder中定义,而相应的ServletRegistration和FilterRegistration实现作为ServletHolder和FilterHolder中的内部类实现,具体参考这两个类的实现。

Holder实现

在之前有提到,在Jetty中Servlet和Filter由相应的ServletHolder和FilterHolder封装,以将Servlet/Filter相关的信息和配置放在一起,并处理各自相关的逻辑,即面向对象设计中的将数据靠近操作。由于Servlet和Filter有一些相同的配置和逻辑,因而在ServletHolder和FilterHolder中提取出了Holder父类。在Holder的实现中,它主要定义了一些Servlet和Filter都要使用的字段,比高实现了所有和InitParameter相关的操作:

    public enum Source { EMBEDDED, JAVAX_API, DESCRIPTOR, ANNOTATION };
    final private Source _source;
    protected transient Class<? extends T> _class;
    protected final Map<String,String> _initParams=new HashMap<String,String>(3);
    protected String _className;
    protected String _displayName;
    protected boolean _extInstance;
    protected boolean _asyncSupported=true;
    protected String _name;
    protected ServletHandler _servletHandler;

Holder继承自AbstractLifeCycle,它在start时,如果_class字段没有被设置,则会使用ClassLoader加载_className中指定的类实例并赋值给_class字段;Source只是目前只是一种元数据的形式存在,用于表示Servlet或Filter的来源;而extInstance用于表示Servlet和Filter实例是直接通过ServletContext注册而来,而不是在当前Holder内部创建。
在Holder类中还定了两个内部类:HolderConfig和HolderRegistration,其中HoldConfig实现了ServletConfig/FilterConfig相关的所有InitParameter相关的操作(代理给Holder);HolderRegistration实现了Registration.Dynamic接口,其实现也都代理给Holder类中的方法。

FilterHolder实现

FilterHolder实现比较简单,它直接继承自Holder类,它额外的包含了一下几个字段:

    private transient Filter _filter;
    private transient Config _config;
    private transient FilterRegistration.Dynamic _registration;

其中_filter字段在start时如果没有初始化,则使用ServletContext创建该Filter实例,而_config字段则在启动时直接创建Config实例(Config是FilterHolder的内部类,且它继承自HolderConfig,并实现了FilterConfig接口),最后调用_filter.init()方法并传入_config实例。在stop时,调用_filter.destroy()方法从而该Filter有机会做一些清理工作,并且调用ServletHandler中的destroyFilter()方法,以通知ContextHandler中定义的Decorators。在注册外部实例化的Filter时,设置_extInstance为true,同时更新_class字段,以及_name字段(如果_name字段未被设置的话)。
最后,FilterHolder中还定义了Registration内部类,它继承自HolderRegistration,并实现了FilterRegistration.Dynamic接口。该Registration内部类实现了Mapping相关方法,Jetty中使用FilterMapping来表达一个Filter的映射关系。在FilterMapping中定义了一下映射关系:

    private int _dispatches=DEFAULT;
    private String _filterName;
    private transient FilterHolder _holder;
    private String[] _pathSpecs;
    private String[] _servletNames;

它包含了两个appliesTo()方法,这两个方法在Chain用于根据dispatcherType或dispatcherType以及path计算当前FilterMapping是否匹配给定的dispatcherType或dispatcherType和path。在对dispatcherType做匹配计算时,使用FilterMapping实例的没有设置dispatcherType集合,它依然匹配REQUEST或ASYNC(如果Filter支持ASYNC模式的话)。

    boolean appliesTo(int type) {
        if (_dispatches==0)
            return type==REQUEST || type==ASYNC && _holder.isAsyncSupported();
        return (_dispatches&type)!=0;
    }

ServletHolder实现

ServletHolder实现相对复杂,它继承自Holder类,并实现了UserIdentity.Scope接口以及Comparable接口,其中Comparable接口用于当ServletHandler在start时,对注册的所有ServletHolder的数组排序以决定他们的start顺序。它包含了一下额外的字段:

    private int _initOrder;
    private boolean _initOnStartup=false;
    private Map<String, String> _roleMap;
    private String _forcedPath;
    private String _runAsRole;
    private RunAsToken _runAsToken;
    private IdentityService _identityService;
    private ServletRegistration.Dynamic _registration;
    private transient Servlet _servlet;
    private transient Config _config;
    private transient long _unavailable;
    private transient UnavailableException _unavailableEx;
    public static final Map<String,String> NO_MAPPED_ROLES = Collections.emptyMap();

其中_initOrder为ServletRegistration.Dynamic接口的实现,它定义ServletHolder在ServletHandler中的start顺序,即compareTo()方法的实现的主要参考信息。在Jetty中,只要设置了loadOnStart字段,则它就会在start时被初始化(即使设置的值为负数)。在设置外部Servlet实例直接到ServletHolder中时,_extInstance字段为被设置为true。如果在web.xml中的Servlet定义中有jsp-file定义,则设置该ServletHolder的forcePath值为该jsp-file中定义的值,而其className的值为servlet-class的定义,此时在ServletHolder的handle方法中会将forcePath的值设置到Request的org.apache.catalina.jsp_file属性中(这个设置用来干嘛呢?还不了解。。。);在ServletHolder启动时,如果Servlet实例实现了SingleThreadModel接口,则Servlet实例使用SingleThreadedWrapper类来表示(它包含一个Servlet栈 ,对每次请求,它会复用以前已经创建的Servlet实例或者创建一个新的实例以处理当前的请求,即该Servlet会有多个实例),如果_extInstance为true或者配置了loadOnStart属性,则在ServletHolder启动是就会初始化这个Servlet(实例化Servlet,并调用Servlet的init方法)。当一个请求到来时,ServletHolder调用其handle方法以处理该请求,在该方法中调用Servlet的service方法,如果在处理过程中出错了,则在Request中设置javax.servlet.error.servlet_name属性为ServletHolder的Name属性。

类似FilterMapping,Jetty也使用ServletMapping表达Servlet和URL pattern的映射关系:

    private String[] _pathSpecs;
    private String _servletName;

其他Security相关的字段和逻辑暂不做介绍。。。。。

深入Jetty源码之Servlet框架及实现(Servlet、Filter、Registration)的更多相关文章

  1. Jetty源码学习-编译Jetty源码二三事

    工作小几个月了,JDK基础和web应用框架学的的差不多了,开始学习Jetty源码,费了小半天才编译成功,把自己拆过的坑记录下来. 编译前的环境: MAVEN 3.3.Eclips eLuna Serv ...

  2. JDK源码及其他框架源码解析随笔地址导航

    置顶一篇文章,主要是整理一下写过的JDK中各个类的源码及其他框架源码解析的文章,方便自己随时阅读也方便网友朋友们阅读与指正 基础篇 从为什么String=String谈到StringBuilder和S ...

  3. Spring5源码解析-Spring框架中的单例和原型bean

    Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...

  4. TOMCAT源码分析&lpar;启动框架&rpar;

    建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, 是不那么容易掌握TOMCAT的框架的. 所以得实践.实践.再实践. 建议下载一份TOMCAT的源码, 调试通过, 然后单步跟踪其启动 ...

  5. Jetty 源码分析

    一. 总括      你了解Jetty 吗,就像我们所熟知的Tomcat一样, Jetty是一个免费的开放源码的100%纯Java的Http服务器和Servlet容器. Jetty具备以下特点:   ...

  6. flume jetty 进程关系 flume jetty 跨域问题 jetty 源码分析

    flume  jetty  跨域问题 13481 httpSource的端口进程号 = flume 启动后的进程号 [root@c log]# netstat -atp Active Internet ...

  7. 程序员的出路在哪里&quest;挣钱的机会来了续-福利来了&comma;仿QQ界面&comma;放出全部源码&comma;打造创业框架及实现思路

    上一篇:程序员的出路在哪里?挣钱的机会来了!, 原来搞技术,挣钱,不一定非得要多高精尖,有时候抓住小白用户,解决他们一个很小但是很常用的功能,也是一条很好的出路. 其实很多软件产品,要实现出来没有你想 ...

  8. Solr4&period;8&period;0源码分析&lpar;1&rpar;之Solr的Servlet

    Solr是作为一个Servlet运行在Tomcat里面的,可以查看Solr的web.xml. 1.web.xml配置 由web.xml可以看出,基本上所有Solr的操作都是在SolrDispatchF ...

  9. &lbrack;Abp vNext 源码分析&rsqb; - 1&period; 框架启动流程分析

    一.简要说明 本篇文章主要剖析与讲解 Abp vNext 在 Web API 项目下的启动流程,让大家了解整个 Abp vNext 框架是如何运作的.总的来说 ,Abp vNext 比起 ABP 框架 ...

随机推荐

  1. SQL Server 阻止了对组件 &&num;39&semi;Ad Hoc Distributed Queries&&num;39&semi; 的 STATEMENT&&num;39&semi;OpenRowset&sol;OpenDatasource&&num;39&semi; 的访问

    delphi ado 跨数据库访问 语句如下 ' and db = '帐套1' 报错内容是:SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATE ...

  2. 动作手游实时PVP技术揭密(服务器篇)

    前言 我们的游戏是一款以忍者格斗为题材的ACT游戏,其主打的玩法是PVE推图及PVP 竞技.在剧情模式中,高度还原剧情再次使不少玩家泪目.而竞技场的乐趣,伴随着赛季和各种赛事相继而来,也深受玩家喜爱, ...

  3. 一个LINUX狂人的语录&lpar;个人认为很精辟&rpar;

    http://blog.chinaunix.net/uid-57160-id-2734431.html?page=2 我已经半年没有使用 Windows 的方式工作了.Linux 高效的完成了我所有的 ...

  4. mount loop最大数的调整

    mount: could not find any free loop device vi /etc/modules.conf Add "options loop max_loop=64&q ...

  5. Jython的应用

    今天本文围绕主要内容是jython是什么.安装.简单实用. 另外说说我为什么研究jython,研究它是有一个目的的,目的是将python代码转化为jar包以供安卓方面那边人脸识别,虽说目前人脸识别像阿 ...

  6. MongoDB 及 Mysql 背后的 B&sol;B&plus;树

    索引是数据库常见的数据结构,每个后台开发人员都应该对索引背后的数据结构有所了解. 本文通过分析B-Tree及B-/+Tree数据结构及索引性能分析及磁盘存取原理尝试着回答一下问题: 为什么B-Tree ...

  7. C&num;实例 Unity依赖注入使用

    Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入.Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问 题.构建一个成功应用程序的关键是实现非常松散的耦合设计 ...

  8. sudo环境变量问题;程序库函数寻找

    1. sudo 和 root不完全等效,继承的环境变量不一样,最主要的区别还是输入的密码不同. 2. 使用sudo去执行一个程序时,出于安全的考虑,这个程序将在一个新的.最小化的环境中执行,也就是说, ...

  9. ubuntu中rc&period;local无效

    在ubuntu中写了一点iptables规则,但是,竟然iptables竟然无效,经过多方查找问题...眼泪... 终于发现是rc.local竟然没有运行,我晕.仔细检查iptables脚本n遍,没有 ...

  10. 基于 IEEE 754 标准的 单精度浮点数计算方式 (未完成)

    def dec2bin(dec): if dec < 0: s = ' dec = dec * (-1) else: s = ' e = 127 dec = float(dec) r = int ...