概述

Spring web 的工具类 WebApplicationContextUtils 位于包

org.springframework.web.context.support

是访问一个ServletContext的根WebApplicationContext的便捷方法类。该工具类提供了如下工具方法 :

  1. 在web容器启动过程中注册web相关作用域bean : request,session , globalSession , application

  2. 在web容器启动过程中注册相应类型的工厂bean,开发人员依赖注入相应的bean时能访问到正确的请求/响应/会话

    对象 : ServletRequest,ServletResponse,HttpSession,WebRequest

  3. 在web容器启动过程中注册web相关环境bean : contextParameters , contextAttributes

  4. 在web容器启动过程中初始化servlet propertySources

  5. 在客户化web视图(custom web view)或者MVC action中,使用该工具类可以很方便地在程序中访问Spring应用上下文(application context)。

源代码解析

/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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.springframework.web.context.support; import java.io.Serializable;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSession; import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource.StubPropertySource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.RequestScope;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.SessionScope;
import org.springframework.web.context.request.WebRequest; /**
* Convenience methods for retrieving the root WebApplicationContext for
* a given ServletContext. This is useful for programmatically accessing
* a Spring application context from within custom web views or MVC actions.
*
* Note that there are more convenient ways of accessing the root context for
* many web frameworks, either part of Spring or available as an external library.
* This helper class is just the most generic way to access the root context.
*
* @author Juergen Hoeller
* @see org.springframework.web.context.ContextLoader
* @see org.springframework.web.servlet.FrameworkServlet
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.jsf.FacesContextUtils
* @see org.springframework.web.jsf.el.SpringBeanFacesELResolver
*/
public abstract class WebApplicationContextUtils { private static final boolean jsfPresent =
ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader()); /**
* Find the root WebApplicationContext for this web app, typically
* loaded via org.springframework.web.context.ContextLoaderListener.
*
* 根据参数sc指定的ServletContext,找到当前web应用的根WebApplicationContext,该根WebApplicationContext
* 典型情况下由加载org.springframework.web.context.ContextLoaderListener,
* 并记录为ServletContext的属性,属性名称使用
* WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*
* Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
*
* 如果根上下文(root context)启动过程中有异常发生,这里会把该异常重新抛出;如果根本找不到根上下文,
* 抛出另外一个异常IllegalStateException,带如下错误信息 :
* No WebApplicationContext found: no ContextLoaderListener registered?
*
* @param sc ServletContext to find the web application context for
* @return the root WebApplicationContext for this web app
* @throws IllegalStateException if the root WebApplicationContext could not be found
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*/
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc) throws IllegalStateException {
WebApplicationContext wac = getWebApplicationContext(sc);
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
}
return wac;
} /**
* Find the root WebApplicationContext for this web app, typically
* loaded via org.springframework.web.context.ContextLoaderListener.
*
* 根据参数sc指定的ServletContext,找到当前web应用的根WebApplicationContext,该根WebApplicationContext
* 典型情况下由加载org.springframework.web.context.ContextLoaderListener,
* 并记录为ServletContext的属性,属性名称使用
* WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*
* Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
*
* 如果根上下文(root context)启动过程中有异常发生,这里会把该异常重新抛出;如果根本找不到根上下文,
* 返回null,注意,这一点是该方法和方法getRequiredWebApplicationContext不同的地方 * @param sc ServletContext to find the web application context for
* @return the root WebApplicationContext for this web app, or null if none
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*/
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
} /**
* Find a custom WebApplicationContext for this web app.
*
* 根据指定的名称找到ServletContext的某个WebApplicationContext,
* 这些WebApplicationContext会在容器启动过程中添加为ServletContext实例特定名字的属性对象,
* 如果这些WebApplicationContext在容器准备他们的过程中遇到了异常,相应的属性对象记录的是相应的异常
* @param sc ServletContext to find the web application context for
* @param attrName the name of the ServletContext attribute to look for
* @return the desired WebApplicationContext for this web app, or null if none
*/
public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {
Assert.notNull(sc, "ServletContext must not be null");
Object attr = sc.getAttribute(attrName);
if (attr == null) {
//如果该属性不存在,返回null
return null;
}
if (attr instanceof RuntimeException) {
// 如果该属性对象是运行时异常,抛出该异常,这种情况说明容器在启动过程中准备该WebApplicationContext
// 遇到了异常
throw (RuntimeException) attr;
}
if (attr instanceof Error) {
// 如果该属性对象是错误,抛出该错误,这种情况说明容器在启动过程中准备该WebApplicationContext
// 遇到了异常
throw (Error) attr;
}
if (attr instanceof Exception) {
// 如果该属性对象是一般异常,抛出该异常,这种情况说明容器在启动过程中准备该WebApplicationContext
// 遇到了异常
throw new IllegalStateException((Exception) attr);
}
if (!(attr instanceof WebApplicationContext)) {
// 如果该属性对象不是异常,不是错误,也不是WebApplicationContext,抛出一个异常表明该问题
throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr);
}
return (WebApplicationContext) attr;
} /**
* Find a unique WebApplicationContext for this web app: either the
* root web app context (preferred) or a unique WebApplicationContext
* among the registered ServletContext attributes (typically coming
* from a single DispatcherServlet in the current web application).
*
* 找到当前Web应用唯一的那个WebApplicationContext:或者是缺省根web应用上下文(期望的情况),
* 或者是注册的ServletContext属性中唯一的那个WebApplicationContext(典型情况下,来自当前
* web应用中的DispatcherServlet)。如果发现注册的ServletContext属性中有多个WebApplicationContext,
* 会抛出异常声明发现了多个WebApplicationContext。
*
* Note that DispatcherServlet's exposure of its context can be
* controlled through its publishContext property, which is true
* by default but can be selectively switched to only publish a single context
* despite multiple DispatcherServlet registrations in the web app.
* @param sc ServletContext to find the web application context for
* @return the desired WebApplicationContext for this web app, or null if none
* @since 4.2
* @see #getWebApplicationContext(ServletContext)
* @see ServletContext#getAttributeNames()
*/
public static WebApplicationContext findWebApplicationContext(ServletContext sc) {
// 尝试获取根web应用上下文,如果找得到则返回根web应用上下文
WebApplicationContext wac = getWebApplicationContext(sc);
if (wac == null) {
// 如果没有找到根web应用上下文,尝试从ServletContext的属性中查找唯一的一个WebApplicationContext
// 并返回,如果找到的WebApplicationContext不唯一,则抛出异常声明该情况
Enumeration<String> attrNames = sc.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = attrNames.nextElement();
Object attrValue = sc.getAttribute(attrName);
if (attrValue instanceof WebApplicationContext) {
if (wac != null) {
throw new IllegalStateException("No unique WebApplicationContext found: more than one " +
"DispatcherServlet registered with publishContext=true?");
}
wac = (WebApplicationContext) attrValue;
}
}
}
return wac;
} /**
* Register web-specific scopes ("request", "session", "globalSession")
* with the given BeanFactory, as used by the WebApplicationContext.
* @param beanFactory the BeanFactory to configure
*/
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
registerWebApplicationScopes(beanFactory, null);
} /**
* Register web-specific scopes ("request", "session", "globalSession", "application")
* with the given BeanFactory, as used by the WebApplicationContext.
*
* 向WebApplicationContext使用的BeanFactory注册web有关作用域对象 :
* request, session, globalSession, application
* @param beanFactory the BeanFactory to configure
* @param sc the ServletContext that we're running within
*/
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, ServletContext sc) {
// 注册web相关作用域bean
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
if (sc != null) {
ServletContextScope appScope = new ServletContextScope(sc);
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
// Register as ServletContext attribute, for ContextCleanupListener to detect it.
sc.setAttribute(ServletContextScope.class.getName(), appScope);
} // 注册ServletRequest的工厂bean,当开发人员依赖注入ServletRequest对象时,注入的bean其实是这里的
// RequestObjectFactory工厂bean
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory()); // 注册ServletResponse的工厂bean,当开发人员依赖注入ServletResponse对象时,注入的bean其实是这里的
// ResponseObjectFactory工厂bean
beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory()); // 注册HttpSession的工厂bean,当开发人员依赖注入HttpSession对象时,注入的bean其实是这里的
// SessionObjectFactory工厂bean
beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory()); // 注册WebRequest的工厂bean,当开发人员依赖注入WebRequest对象时,注入的bean其实是这里的
// WebRequestObjectFactory工厂bean
beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory()); if (jsfPresent) {
FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
}
} /**
* Register web-specific environment beans ("contextParameters", "contextAttributes")
* with the given BeanFactory, as used by the WebApplicationContext.
* @param bf the BeanFactory to configure
* @param sc the ServletContext that we're running within
*/
public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, ServletContext sc) {
registerEnvironmentBeans(bf, sc, null);
} /**
* Register web-specific environment beans ("contextParameters", "contextAttributes")
* with the given BeanFactory, as used by the WebApplicationContext.
* @param bf the BeanFactory to configure
* @param servletContext the ServletContext that we're running within
* @param servletConfig the ServletConfig of the containing Portlet
*/
public static void registerEnvironmentBeans(
ConfigurableListableBeanFactory bf, ServletContext servletContext, ServletConfig servletConfig) { if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext);
} if (servletConfig != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) {
bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, servletConfig);
} if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
Map<String, String> parameterMap = new HashMap<String, String>();
if (servletContext != null) {
Enumeration<?> paramNameEnum = servletContext.getInitParameterNames();
while (paramNameEnum.hasMoreElements()) {
String paramName = (String) paramNameEnum.nextElement();
parameterMap.put(paramName, servletContext.getInitParameter(paramName));
}
}
if (servletConfig != null) {
Enumeration<?> paramNameEnum = servletConfig.getInitParameterNames();
while (paramNameEnum.hasMoreElements()) {
String paramName = (String) paramNameEnum.nextElement();
parameterMap.put(paramName, servletConfig.getInitParameter(paramName));
}
}
bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME,
Collections.unmodifiableMap(parameterMap));
} if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) {
Map<String, Object> attributeMap = new HashMap<String, Object>();
if (servletContext != null) {
Enumeration<?> attrNameEnum = servletContext.getAttributeNames();
while (attrNameEnum.hasMoreElements()) {
String attrName = (String) attrNameEnum.nextElement();
attributeMap.put(attrName, servletContext.getAttribute(attrName));
}
}
bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME,
Collections.unmodifiableMap(attributeMap));
}
} /**
* Convenient variant of #initServletPropertySources(MutablePropertySources,
* ServletContext, ServletConfig) that always provides null for the
* ServletConfig parameter.
* @see #initServletPropertySources(MutablePropertySources, ServletContext, ServletConfig)
*/
public static void initServletPropertySources(MutablePropertySources propertySources, ServletContext servletContext) {
initServletPropertySources(propertySources, servletContext, null);
} /**
* Replace Servlet-based StubPropertySource stub property sources with
* actual instances populated with the given servletContext and
* servletConfig objects.
* This method is idempotent with respect to the fact it may be called any number
* of times but will perform replacement of stub property sources with their
* corresponding actual property sources once and only once.
* @param propertySources the MutablePropertySources to initialize (must not
* be null)
* @param servletContext the current ServletContext (ignored if null
* or if the StandardServletEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME
* servlet context property source has already been initialized)
* @param servletConfig the current ServletConfig (ignored if null
* or if the StandardServletEnvironment#SERVLET_CONFIG_PROPERTY_SOURCE_NAME
* servlet config property source} has already been initialized)
* @see org.springframework.core.env.PropertySource.StubPropertySource
* @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources()
*/
public static void initServletPropertySources(
MutablePropertySources propertySources, ServletContext servletContext, ServletConfig servletConfig) { Assert.notNull(propertySources, "'propertySources' must not be null");
if (servletContext != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) &&
propertySources.get(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
propertySources.replace(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME,
new ServletContextPropertySource(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, servletContext));
}
if (servletConfig != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) &&
propertySources.get(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
propertySources.replace(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME,
new ServletConfigPropertySource(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, servletConfig));
}
} /**
* Return the current RequestAttributes instance as ServletRequestAttributes.
*
* 获取当前RequestAttributes实例,返回类型为ServletRequestAttributes,
* 该方法使用RequestContextHolder获取和当前请求处理线程绑定的ServletRequestAttributes对象,
* 进而可以获取其中的HttpServletRequest/HttpServletResponse对象
*
* 该类定义该方法的目的是给该类的以下四个私有嵌套静态类使用 :
* RequestObjectFactory,ResponseObjectFactory,SessionObjectFactory,WebRequestObjectFactory
* @see RequestContextHolder#currentRequestAttributes()
*/
private static ServletRequestAttributes currentRequestAttributes() {
RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();
if (!(requestAttr instanceof ServletRequestAttributes)) {
throw new IllegalStateException("Current request is not a servlet request");
}
return (ServletRequestAttributes) requestAttr;
} // 在下面的代码中,该类定义了四个私有嵌套静态类 :
// RequestObjectFactory,ResponseObjectFactory,SessionObjectFactory,WebRequestObjectFactory
// 这四个静态类是四个工厂类,分别用于生成ServletRequest,ServletResponse,HttpSession,WebRequest对象,
// 当开发人员使用@Autowired分别注入了以上四种类型的bean时,返回的其实是下面四个工厂类的对象,这四个工厂类对象
// 均使用了上面定义的currentRequestAttributes()方法,能从当前请求处理线程中获取正确的ServletRequestAttributes
// 对象,进而获取正确的ServletRequest,ServletResponse,HttpSession,WebRequest对象 /**
* Factory that exposes the current request object on demand.
*/
@SuppressWarnings("serial")
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable { @Override
public ServletRequest getObject() {
return currentRequestAttributes().getRequest();
} @Override
public String toString() {
return "Current HttpServletRequest";
}
} /**
* Factory that exposes the current response object on demand.
*/
@SuppressWarnings("serial")
private static class ResponseObjectFactory implements ObjectFactory<ServletResponse>, Serializable { @Override
public ServletResponse getObject() {
ServletResponse response = currentRequestAttributes().getResponse();
if (response == null) {
throw new IllegalStateException("Current servlet response not available - " +
"consider using RequestContextFilter instead of RequestContextListener");
}
return response;
} @Override
public String toString() {
return "Current HttpServletResponse";
}
} /**
* Factory that exposes the current session object on demand.
*/
@SuppressWarnings("serial")
private static class SessionObjectFactory implements ObjectFactory<HttpSession>, Serializable { @Override
public HttpSession getObject() {
return currentRequestAttributes().getRequest().getSession();
} @Override
public String toString() {
return "Current HttpSession";
}
} /**
* Factory that exposes the current WebRequest object on demand.
*/
@SuppressWarnings("serial")
private static class WebRequestObjectFactory implements ObjectFactory<WebRequest>, Serializable { @Override
public WebRequest getObject() {
ServletRequestAttributes requestAttr = currentRequestAttributes();
return new ServletWebRequest(requestAttr.getRequest(), requestAttr.getResponse());
} @Override
public String toString() {
return "Current ServletWebRequest";
}
} /**
* Inner class to avoid hard-coded JSF dependency.
*/
private static class FacesDependencyRegistrar { public static void registerFacesDependencies(ConfigurableListableBeanFactory beanFactory) {
beanFactory.registerResolvableDependency(FacesContext.class, new ObjectFactory<FacesContext>() {
@Override
public FacesContext getObject() {
return FacesContext.getCurrentInstance();
}
@Override
public String toString() {
return "Current JSF FacesContext";
}
});
beanFactory.registerResolvableDependency(ExternalContext.class, new ObjectFactory<ExternalContext>() {
@Override
public ExternalContext getObject() {
return FacesContext.getCurrentInstance().getExternalContext();
}
@Override
public String toString() {
return "Current JSF ExternalContext";
}
});
}
} }

Spring web 工具类 WebApplicationContextUtils的更多相关文章

  1. Spring常用工具类

    Spring框架下自带了丰富的工具类,在我们开发时可以简化很多工作: 1.Resource访问文件资源: 具体有: ResourceUtils.getFile(url); FileSystemReso ...

  2. 2015第30周三Spring常用工具类

    文件资源操作 文件资源的操作是应用程序中常见的功能,如当上传一个文件后将其保存在特定目录下,从指定地址加载一个配置文件等等.我们一般使用 JDK 的 I/O 处理类完成这些操作,但对于一般的应用程序来 ...

  3. Spring 常用工具类

    1) 请求工具类 org.springframework.web.bind.ServletRequestUtils //取请求参数的整数值: public static Integer getIntP ...

  4. Spring boot 工具类静态属性注入及多环境配置

    由于需要访问MongoDB,但是本地开发环境不能直接连接MongoDB,需要通过SecureCRT使用127.0.0.2本地IP代理.但是程序部署到线上生产环境后,是可以直接访问MongoDB的,因此 ...

  5. spring注解工具类AnnotatedElementUtils和AnnotationUtils

    一.前言 spring为开发人员提供了两个搜索注解的工具类,分别是AnnotatedElementUtils和AnnotationUtils.在使用的时候,总是傻傻分不清,什么情况下使用哪一个.于是我 ...

  6. Spring的工具类StringUtils使用

    我们经常会对字符串进行操作,spring已经实现了常用的处理功能.我们可以使用org.springframework.util.StringUtils 工具类帮我们处理字符串. 工具类整理如下:   ...

  7. Spring常用工具类(ApplicationContextAware、DisposableBean、InitializingBean)

    原创作品,出自 "晓风残月xj" 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj). 由于各种原因,可能存在诸多不 ...

  8. WEB工具类

    import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; ...

  9. 【SpingBoot】spring静态工具类注入问题

    package cn.zwqh.action; import javax.annotation.PostConstruct; import javax.annotation.Resource; imp ...

随机推荐

  1. bootstrap之Orientation

    Orientation 调整屏幕方向的操作. package io.appium.android.bootstrap.handler; import android.os.RemoteExceptio ...

  2. 将 php 转换/编译为 EXE

    将 php 转换/编译为 EXE 本文仅仅是将原文用谷歌作了翻译,原文来源于 http://stackoverflow.com 资料来源  http://stackoverflow.com/quest ...

  3. java三元表达式编程规范问题

    package day01; public class Program { public static void main(String[] args) {        // TODO Auto-g ...

  4. 37.Node.js工具模块---处理和转换文件路径的工具 Path模块

    转自:http://www.runoob.com/nodejs/nodejs-module-system.html Node.js path 模块提供了一些用于处理文件路径的小工具,我们可以通过以下方 ...

  5. 9.Maven之(九)依赖关系

    转自:https://yq.aliyun.com/ziliao/312160 在maven的管理体系中,各个项目组成了一个复杂的关系网,但是每个项目都是平等的,是个没有贵贱高低,众生平等的世界,全球每 ...

  6. 2. APIS官网剖析(博主推荐)

    不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ 2. APIS .APIS Apache Kafka引入一个新的java客户端(在o ...

  7. JAVA Mail邮件实现发送

    package com.test;import java.util.Date;import java.util.Properties;import javax.mail.Message;import ...

  8. 二维LIS(CDQ分治)

    题目描述 给定一个长度为N的序列S,S的每个元素pi是一个二元组(xi,yi),定义pi<pj当且仅当xi<xj并且yi<yj,求S的最长上升子序列长度 输入格式 第一行一个N,表示 ...

  9. layout-maxWidth属性用法

    对于maxWidth属性,相信大家都不陌生.不过,今天我遇到了一个问题,就是当我希望一个relayout的宽度有个最大值的时候,用maxWidth却没办法实现.这里总结下maxWidth 的用法 1. ...

  10. stackFromBottom-listview 内容从底部开始填充

    今天遇到了一个问题,就是listview虽然占满了整个屏幕,但是,当它的内容只有几条的时候,它会从底部开始显示,上面留有空白.后来进入xml发现,listview有个属性stackFromBottom ...