tomcat(5)servlet容器
version),本文明天也会删除[1604112328]。
t1)Engine:表示整个Catalina servlet 引擎。t2)Host:表示包括有一个或多个 Context容器的虚拟主机。t3)Context:表示一个web 应用程序,一个Context 能够有多个 Wrapper。t4)Wrapper:表示一个独立的servlet。
这4个接口的标准实现是 StandardEngine类。StandardHost类,StandardContext类,StandardWrapper类,他们都在 org.apache.catalina.core 包内;
A1)全部的实现类都继承自抽象类 ContainerBase ;A2)Container接口的设计满足以下条件:在部署应用时,Tomcat管理员能够通过编辑配置文件(server.xml)来决定使用哪种容器。这是通过引入容器中的管道(pipeline)和阀(valve)的集合实现的;(干货——引入了容器中的管道和阀)
有意思的是, 能够通过编辑tomcat 的 配置文件(server.xml)来动态地加入阀;
A1)管道就想过滤器链条一样。而阀则好似过滤器。A2)当一个阀运行完毕后。会调用下一个阀继续运行。基础阀总是最后一个运行。(干货——当一个阀运行完毕后,会调用下一个阀继续运行。基础阀总是最后一个运行)
以下是invoke方法的伪代码:
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;
// invoke each valve added to the pipeline,先是非基础阀调用 invoke方法
for(;;){
valve[i].invoke();
}
// then, invoke the basic valve, 后是基础阀调用 invoke方法(基础阀最后一个调用invoke方法)
basicValve.invoke(...);
public void invoke(Request request, Response response) // SimplePipeline.invoke()
throws IOException, ServletException {
// Invoke the first Valve in this pipeline for this request
(new SimplePipelineValveContext()).invokeNext(request, response);
}
public void invokeNext(Request request, Response response) // SimplePipeline.invokeNext()
throws IOException, ServletException {
int subscript = stage;
stage = stage + 1;
// Invoke the requested Valve for the current request thread
if (subscript < valves.length) {
valves[subscript].invoke(request, response, this);
}
else if ((subscript == valves.length) && (basic != null)) {
basic.invoke(request, response, this);
}
else {
throw new ServletException("No valve");
}
}
} // end of inner class
ValveContext实例会将自身传给每一个阀,因此,每一个阀都能够调用 ValveContext实例的 invokeNext方法;
public interface Pipeline {
public Valve getBasic();
public void setBasic(Valve valve);
public void addValve(Valve valve);
public Valve[] getValves();
public void invoke(Request request, Response response)
throws IOException, ServletException;
public void removeValve(Valve valve);
}
public interface Valve {
public String getInfo();
public void invoke(Request request, Response response,ValveContext context) throws IOException, ServletException;
public interface Contained {
public Container getContainer();
public void setContainer(Container container);
}
public interface Wrapper extends Container {
public long getAvailable();
public void setAvailable(long available);
public String getJspFile();
public void setJspFile(String jspFile);
public int getLoadOnStartup();
public void setLoadOnStartup(int value);
public String getRunAs();
public void setRunAs(String runAs);
public String getServletClass();
public void setServletClass(String servletClass);
public boolean isUnavailable();
public void addInitParameter(String name, String value);
public void addInstanceListener(InstanceListener listener);
public void addSecurityReference(String name, String link);
public Servlet allocate() throws ServletException;
public void deallocate(Servlet servlet) throws ServletException;
public String findInitParameter(String name);
public String[] findInitParameters();
public String findSecurityReference(String name);
public String[] findSecurityReferences();
public void load() throws ServletException;
public void removeInitParameter(String name);
public void removeInstanceListener(InstanceListener listener);
public void removeSecurityReference(String name);
public void unavailable(UnavailableException unavailable);
public void unload() throws ServletException;
}
public class SimpleLoader implements Loader {
public static final String WEB_ROOT =
System.getProperty("user.dir") + File.separator + "webroot";
ClassLoader classLoader = null;
Container container = null;
public SimpleLoader() {
try {
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(WEB_ROOT);
String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;
urls[0] = new URL(null, repository, streamHandler);
classLoader = new URLClassLoader(urls);
}
catch (IOException e) {
System.out.println(e.toString() );
}
}
public class SimplePipeline implements Pipeline {
public SimplePipeline(Container container) {
setContainer(container);
}
// The basic Valve (if any) associated with this Pipeline.
protected Valve basic = null;
// The Container with which this Pipeline is associated.
protected Container container = null;
// the array of Valves
protected Valve valves[] = new Valve[0];
public void setContainer(Container container) {
this.container = container;
}
public Valve getBasic() {
return basic;
}
public void setBasic(Valve valve) {
this.basic = valve;
((Contained) valve).setContainer(container);
}
public void addValve(Valve valve) {
if (valve instanceof Contained)
((Contained) valve).setContainer(this.container);
synchronized (valves) {
Valve results[] = new Valve[valves.length +1];
System.arraycopy(valves, 0, results, 0, valves.length);
results[valves.length] = valve;
valves = results;
}
}
public Valve[] getValves() {
return valves;
}
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Invoke the first Valve in this pipeline for this request
(new SimplePipelineValveContext()).invokeNext(request, response);
}
public void removeValve(Valve valve) {
}
// this class is copied from org.apache.catalina.core.StandardPipeline class's
// StandardPipelineValveContext inner class.
protected class SimplePipelineValveContext implements ValveContext {
protected int stage = 0;
public String getInfo() {
return null;
}
public void invokeNext(Request request, Response response)
throws IOException, ServletException {
int subscript = stage;
stage = stage + 1;
// Invoke the requested Valve for the current request thread
if (subscript < valves.length) {
valves[subscript].invoke(request, response, this);
}
else if ((subscript == valves.length) && (basic != null)) {
basic.invoke(request, response, this);
}
else {
throw new ServletException("No valve");
}
}
} // end of inner class
}
public class SimpleWrapper implements Wrapper, Pipeline {
// the servlet instance
private Servlet instance = null;
private String servletClass;
private Loader loader;
private String name;
private SimplePipeline pipeline = new SimplePipeline(this);
protected Container parent = null;
public SimpleWrapper() {
pipeline.setBasic(new SimpleWrapperValve());
}
public synchronized void addValve(Valve valve) {
pipeline.addValve(valve);
}
public Servlet allocate() throws ServletException {
// Load and initialize our instance if necessary
if (instance==null) {
try {
instance = loadServlet();
}
catch (ServletException e) {
throw e;
}
catch (Throwable e) {
throw new ServletException("Cannot allocate a servlet instance", e);
}
}
return instance;
}
private Servlet loadServlet() throws ServletException {
if (instance!=null)
return instance;
Servlet servlet = null;
String actualClass = servletClass;
if (actualClass == null) {
throw new ServletException("servlet class has not been specified");
}
Loader loader = getLoader();
// Acquire an instance of the class loader to be used
if (loader==null) {
throw new ServletException("No loader.");
}
ClassLoader classLoader = loader.getClassLoader();
// Load the specified servlet class from the appropriate class loader
Class classClass = null;
try {
if (classLoader!=null) {
classClass = classLoader.loadClass(actualClass);
}
}
catch (ClassNotFoundException e) {
throw new ServletException("Servlet class not found");
}
// Instantiate and initialize an instance of the servlet class itself
try {
servlet = (Servlet) classClass.newInstance();
}
catch (Throwable e) {
throw new ServletException("Failed to instantiate servlet");
}
// Call the initialization method of this servlet
try {
servlet.init(null);
}
catch (Throwable f) {
throw new ServletException("Failed initialize servlet.");
}
return servlet;
}
public String getInfo() {
return null;
}
public Loader getLoader() {
if (loader != null)
return (loader);
if (parent != null)
return (parent.getLoader());
return (null);
}
public class SimpleWrapperValve implements Valve, Contained {
protected Container container;
public void invoke(Request request, Response response, ValveContext valveContext)
throws IOException, ServletException {
SimpleWrapper wrapper = (SimpleWrapper) getContainer();
ServletRequest sreq = request.getRequest();
ServletResponse sres = response.getResponse();
Servlet servlet = null;
HttpServletRequest hreq = null;
if (sreq instanceof HttpServletRequest)
hreq = (HttpServletRequest) sreq;
HttpServletResponse hres = null;
if (sres instanceof HttpServletResponse)
hres = (HttpServletResponse) sres;
// Allocate a servlet instance to process this request
try {
servlet = wrapper.allocate();
if (hres!=null && hreq!=null) {
servlet.service(hreq, hres);
}
else {
servlet.service(sreq, sres);
}
}
catch (ServletException e) {
}
}
public String getInfo() {
return null;
}
public Container getContainer() {
return container;
}
public void setContainer(Container container) {
this.container = container;
}
}
然后,它会把几行字符串output到 console。
public class ClientIPLoggerValve implements Valve, Contained {
protected Container container;
public void invoke(Request request, Response response, ValveContext valveContext)
throws IOException, ServletException {
// Pass this request on to the next valve in our pipeline
valveContext.invokeNext(request, response);
System.out.println("Client IP Logger Valve");
ServletRequest sreq = request.getRequest();
System.out.println(sreq.getRemoteAddr());
System.out.println("------------------------------------");
}
public String getInfo() {
return null;
}
public Container getContainer() {
return container;
}
public void setContainer(Container container) {
this.container = container;
}
}
public class HeaderLoggerValve implements Valve, Contained {
protected Container container;
public void invoke(Request request, Response response, ValveContext valveContext)
throws IOException, ServletException {
// Pass this request on to the next valve in our pipeline
valveContext.invokeNext(request, response);
System.out.println("Header Logger Valve");
ServletRequest sreq = request.getRequest();
if (sreq instanceof HttpServletRequest) {
HttpServletRequest hreq = (HttpServletRequest) sreq;
Enumeration headerNames = hreq.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement().toString();
String headerValue = hreq.getHeader(headerName);
System.out.println(headerName + ":" + headerValue);
}
}
else
System.out.println("Not an HTTP Request");
System.out.println("------------------------------------");
}
public String getInfo() {
return null;
}
public Container getContainer() {
return container;
}
public void setContainer(Container container) {
this.container = container;
}
}
step1)创建 HttpConnector 和 SimpleWrapper实例,并将须要加载的 servlet name 赋值给 Wrapper实例。step2)创建一个加载器和两个阀,将加载器设置到Wrapper实例中 ;step3)将上述创建的两个阀加入到 Wrapper的管道中;step4)将Wrapper 实例设置为 连接器的servlet容器。并初始化并启动连接器;
public final class Bootstrap1 {
public static void main(String[] args) { /* call by using http://localhost:8080/ModernServlet,
but could be invoked by any name */ HttpConnector connector = new HttpConnector();
Wrapper wrapper = new SimpleWrapper();
wrapper.setServletClass("servlet.ModernServlet"); // 设置servlet的相对路径 Loader loader = new SimpleLoader(); // 类加载器
Valve valve1 = new HeaderLoggerValve(); // 把请求头信息output到 console
Valve valve2 = new ClientIPLoggerValve();// 用来将client的IP 地址输出到控制台上 wrapper.setLoader(loader);
((Pipeline) wrapper).addValve(valve1);
((Pipeline) wrapper).addValve(valve2); connector.setContainer(wrapper); try {
connector.initialize(); // 创建服务器套接字
connector.start(); // // make the application wait until we press a key.
System.in.read();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\webroot com.tomcat.chapter5.startup/Bootstrap1
HttpConnector Opening server socket on all host IP addresses
HttpConnector[8080] Starting background thread
ModernServlet -- init
Client IP Logger Valve
127.0.0.1
------------------------------------
Header Logger Valve
host:localhost:8080
connection:keep-alive
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
accept-encoding:gzip, deflate, sdch
accept-language:zh-CN,zh;q=0.8,en;q=0.6
------------------------------------
Client IP Logger Valve
127.0.0.1
------------------------------------
Header Logger Valve
host:localhost:8080
connection:keep-alive
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
accept-encoding:gzip, deflate, sdch
accept-language:zh-CN,zh;q=0.8,en;q=0.6
------------------------------------
映射器是组件,帮助servlet容器(Context实例)选择一个子容器来处理某个指定的请求;
public interface Mapper {
public Container getContainer(); // 返回与该映射器相关联的servlet容器的实例。
public void setContainer(Container container); // 设置与该映射器相关联的servlet容器。
public String getProtocol(); // 返回该映射器负责处理的协议
public void setProtocol(String protocol); //指定该映射器负责处理哪种协议
public Container map(Request request, boolean update); // 返回要处理某个特定请求的子容器的实例;
}
step1)容器包括一个管道,容器的invoke方法会调用管道的invoke方法;step2)管道的invoke方法会调用全部加入到其容器中的阀,然后再调用其基础阀的invoke方法。step3)在Wrapper实例中。 基础阀负责加载相关联的servlet类,并对请求进行响应;step4)在包括子容器的 Context实例中。 基础阀使用映射器来查找一个子容器。该子容器负责处理接收到的请求。若找到了相应的子容器,则调用其invoke方法。转到step1继续运行;
step1)SimpleContext类的invoke方法调用管道的invoke方法:step2)管道SimplePipeline的invoke例如以下:
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Invoke the first Valve in this pipeline for this request
(new SimplePipelineValveContext()).invokeNext(request, response); // 会调用全部加入到Context 实例中的阀,然后再调用基础阀的invoke方法;
}
step3)SimpleContext类中。基础阀是 SimpleContextValve类的实例。在SimpleContextValve类的 invoke方法中。 SimpleContextValve实例使用了 Context实例的映射器来查找 Wrapper容器;public class SimpleContext implements Context, Pipeline { public SimpleContext() {
pipeline.setBasic(new SimpleContextValve());
}
public void invoke(Request request, Response response, ValveContext valveContext) // SimpleContextValve.invoke()
throws IOException, ServletException {
// Validate the request and response object types
if (!(request.getRequest() instanceof HttpServletRequest) ||
!(response.getResponse() instanceof HttpServletResponse)) {
return; // NOTE - Not much else we can do generically
} // Disallow any direct access to resources under WEB-INF or META-INF
HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
String contextPath = hreq.getContextPath();
String requestURI = ((HttpRequest) request).getDecodedRequestURI();
String relativeURI =
requestURI.substring(contextPath.length()).toUpperCase(); Context context = (Context) getContainer();
// Select the Wrapper to be used for this Request
Wrapper wrapper = null;
try {
wrapper = (Wrapper) context.map(request, true); // attention for this line.
}
catch (IllegalArgumentException e) {
badRequest(requestURI, (HttpServletResponse) response.getResponse());
return;
}
if (wrapper == null) {
notFound(requestURI, (HttpServletResponse) response.getResponse());
return;
}
// Ask this Wrapper to process this Request
response.setContext(context);
wrapper.invoke(request, response);
}
A1)Wrapper实例的管道会调用 SimpleWrapperValve类的 invoke方法,它会分配servlet实例,并调用其 service方法;A2)Wrapper实例中:并没有与加载器相关联。可是Context 实例关联了类加载器。因此,SimpleWrapper类的 getLoader() 方法会返回父容器的加载器。
public class SimpleContextMapper implements Mapper {
/**
* The Container with which this Mapper is associated.
*/
private SimpleContext context = null;
public Container getContainer() {
return (context);
}
public void setContainer(Container container) {
if (!(container instanceof SimpleContext))
throw new IllegalArgumentException
("Illegal type of container");
context = (SimpleContext) container;
}
public String getProtocol() {
return null;
}
public void setProtocol(String protocol) {
}
/**
* Return the child Container that should be used to process this Request,
* based upon its characteristics. If no such child Container can be
* identified, return <code>null</code> instead.
*
* @param request Request being processed
* @param update Update the Request to reflect the mapping selection?
*
* @exception IllegalArgumentException if the relative portion of the
* path cannot be URL decoded
*/
public Container map(Request request, boolean update) {
// Identify the context-relative URI to be mapped
String contextPath =
((HttpServletRequest) request.getRequest()).getContextPath();
String requestURI = ((HttpRequest) request).getDecodedRequestURI();
String relativeURI = requestURI.substring(contextPath.length());
// Apply the standard request URI mapping rules from the specification
Wrapper wrapper = null;
String servletPath = relativeURI;
String pathInfo = null;
String name = context.findServletMapping(relativeURI);
if (name != null)
wrapper = (Wrapper) context.findChild(name);
return (wrapper);
}
}
map() 方法:
会从request对象中解析出请求的上下文路径,并调用 Conetext 实例的findServletMapping() 方法 来获取一个与该路径相关联的名称,假设找到了这个名称,则它调用 Context实例的findChild方法获取一个 Wrapper 实例。1)intro to SimpleContext: 该类是 Context容器 的实例。是与连接器相关联的主容器;2)本应用程序有两种URL模式:用来调用两个 Wrapper实例,如/Primitive 和 /Modern 模式;当然,也能够将多个 URL模式映射到一个Wrapper实例上。仅仅须要加入这些模式就可以;
3)SimpleContext类必须实现 Container 和 Context接口,实现的方法包括以下几个(methods):method1)addServletMapping(): 加入一个 URL模式 / Wrapper实例的名称对;通过给定的名称加入用于调用Wrapper实例的每种模式;method2)findServletMapping():通过URL模式 查找相应的Wrapper 实例名称;该方法用来查找某个特殊URL 模式相应的Wrapper实例。method3)addMapper():在Context容器中加入一个映射器。SimpleContext类声明有两个变量: mapper and mappers 。mapper表示程序使用的默认映射器,mappers包括SimpleContext 实例中全部可用的映射器。第一个被加入到 Context容器中的映射器称为默认映射器;
method4)findMapper():找到正确的映射器,在 SimpleContext类中,它返回默认映射器;method5)map(): 返回负责处理当前请求的 Wrapper实例。
step1)首先实例化Tomcat的默认连接器,创建两个Wrapper实例。并指定名称。HttpConnector connector = new HttpConnector(); Wrapper wrapper1 = new SimpleWrapper();
wrapper1.setName("Primitive");
wrapper1.setServletClass("servlet.PrimitiveServlet"); Wrapper wrapper2 = new SimpleWrapper();
wrapper2.setName("Modern");
wrapper2.setServletClass("servlet.ModernServlet");
step2)main() 方法创建一个 SimpleContext实例,并将 wrapper1 和 wrapper2 作为子容器加入到 SimpleContext 实例中。
此外,它还会实例化两个阀:ClientIPLoggerValve 和 HeaderLoggerValve,并将它们加入到 SimpleContext实例中:
Context context = new SimpleContext();
context.addChild(wrapper1);
context.addChild(wrapper2); Valve valve1 = new HeaderLoggerValve();
Valve valve2 = new ClientIPLoggerValve(); ((Pipeline) context).addValve(valve1);
((Pipeline) context).addValve(valve2);
step3)接下来,它会从SimpleMapper类创建一个映射器对象,将其加入到 SimpleContext 实例中。映射器负责查找Context 实例中的子容器来处理 HTTP请求
Mapper mapper = new SimpleContextMapper();
mapper.setProtocol("http");
context.addMapper(mapper);
step4)要加载servlet类。还须要一个加载器。并将其加入到 Context实例中。Wrapper实例能够通过 其 getLoader方法来获取加载器。因为Wrapper实例是 Context实例的子容器:Loader loader = new SimpleLoader();
context.setLoader(loader);
step5)加入servlet映射。为 两个Wrapper 实例加入两种模式:
// context.addServletMapping(pattern, name);
context.addServletMapping("/Primitive", "Primitive");
context.addServletMapping("/Modern", "Modern");
step6)将Context容器与 连接器相关联,并初始化连接器,调用其 start方法。connector.setContainer(context);
try {
connector.initialize();
connector.start(); // make the application wait until we press a key.
System.in.read();
}
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\webroot com.tomcat.chapter5.startup.
Bootstrap2
HttpConnector Opening server socket on all host IP addresses
HttpConnector[8080] Starting background thread
Client IP Logger Valve
127.0.0.1
------------------------------------
Header Logger Valve
host:localhost:8080
connection:keep-alive
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
accept-encoding:gzip, deflate, sdch
accept-language:zh-CN,zh;q=0.8,en;q=0.6
------------------------------------
init
from service
Client IP Logger Valve
127.0.0.1
------------------------------------

tomcat(5)servlet容器的更多相关文章
- JSP学习 —— 开篇:JSP,servlet容器,Tomcat,servlet容器之间的关系
JSP(JAVA SERVER PAGE)的缩写,其本身就是servlet的简化,是一种动态网页标准,其特点是在HTML代码中嵌入JAVA代码,JSP标签或用户标签来生成网页.至于它为什么会出现,主要 ...
- How tomcat works(深入剖析tomcat)servlet容器
How tomcat works (5)servlet容器阅读笔记 第四章阅读了tomcat默认连接器的实现,当时connector中的使用的容器是自定义的容器,也是非常之简单奥,一个人就干完了所有的 ...
- tomcat和servlet容器的关系
- Web服务器(Apache)与Servlet容器(Tomcat)
之前一直比较迷惑Apache与Tomcat的关系,通过查询资料,有所了解,现记录于此. Apache与Tomcat 两者定位:Apache是HTTP Web服务器,Tomcat是Web容器. 有一个非 ...
- SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)
Spring Boot默认使用Tomcat作为嵌入式的Servlet容器,只要引入了spring-boot-start-web依赖,则默认是用Tomcat作为Servlet容器: <depend ...
- web服务器、tomcat、servlet是什么?它们之间的关系又是什么?
今天偶然看到常见web服务器的介绍有Apache HTTP server.Nginx.Microsoft IIS.GWS,心中不禁产生了疑问,这些都是什么呢?一直认为tomcat就是web服务器,以下 ...
- 尚硅谷springboot学习25-嵌入式Servlet容器
SpringBoot默认使用Tomcat作为嵌入式的Servlet容器:
- 19. SpringBoot_web开发-使用外部Servlet容器&JSP支持
還沒有web.xml,生 配置tomcat 嵌入式Servlet容器:应用打成可执行的jar 优点:简单.便携: 缺点:默认不支持JSP.优化定制比较复杂 使用定制器[ServerPropertie ...
- tomcat和servlet的关系
一.什么是servlet? 处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,并且Servlet是为了解决实现动态页面而衍生的东西.理解这个的前提是了解一些http协议的东西,并且知道 ...
随机推荐
- 安装与配置ironic
安装及配置 由于Ironic的配置很长,下面我们简短的说一下安装和配置过程,具体的安装配置教程参考官方手动配置教程或者使用devstack安装. Ironic需要与Nova.Neutron.Glanc ...
- java8新特性——Lambda表达式
上文中简单介绍了一下java8得一些新特性,与优点,也是为本次学习java8新特性制定一个学习的方向,后面几篇会根据上文中得新特性一一展开学习.本文就从java8新特性中比较重要的Lambda表达式开 ...
- 数据仓库之父——Bill Inmon(转载)
从此处转载 http://blog.sina.com.cn/s/blog_615f9dba0100f67p.html 比尔·恩门(Bill Inmon),被称为数据仓库之父,最早的数据仓库概念提出者, ...
- 又见Python<1>:使用Anaconda搭建Python开发环境(Windows7)
1.为什么选择Anaconda? Anaconda解决了Python使用痛点. Python好用但是令人头疼的就是库管理与Python不同版本的问题,特别是Windows环境下. 2.什么是Anaco ...
- 矩阵&行列式
# 代数 排列 对换,对于一个排列操作,对于一个偶排列一次对换之后变为奇排列 反之变为偶排列 行列式 N阶行列式室友N^2个数aij(i,j = 1,2,3,...n) 行列式的数=\(\sum_ { ...
- 我的OI生涯 第二章
第二章 很快就开学了,我们几个到了16班,开哥茂嵩到了15班,MJX和ZZJ去了四班,YST去了九班. 竞赛课改成了一周两节,每周都学习一点新的语言,这期间来了一些新同学例如于北,LTY,他们刚来感觉 ...
- Week Four
2018.12.18 1.[USACO Platinum C] 2.[Gym 102028H] 3.[BZOJ 2750] 4.[BZOJ 3238] 5.[BZOJ 4310] 6.[BZOJ 38 ...
- ARC 101 C - Candles
题面在这里! 显然直接枚举左端点(右端点)就OK啦. #include<cstdio> #include<cstdlib> #include<algorithm> ...
- 禁用substr、substring、mid函数的sql注入脚本
#encodeing=utf-8 import requests import sys reload(sys) sys.setdefaultencoding('utf-8') payloads = l ...
- Java泛型应用总结
一.泛型的引入原因 在操作集合的时候,之前方法的定义都是Object类型,向集合中添加对象,都自动向上转型,加入的元素可以是任何类型 但是,在取出元素的时候,通常想要使用对象的特有功能,就必须向下转型 ...