Filter概述

Filter不用于客户端请求,只用于对request,response进行修改或对context,session,request事件进行监听。

1.概述

如上图,多个filter组成一个FilterChain。

2.Filter接口

3.Filter配置

防盗链Filter

代码详解:

1.编写过滤器

public class ImageRedirectFilter implements Filter {

public void init(FilterConfig config) throws ServletException {

}

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) res;

// 禁止缓存

response.setHeader("Cache-Control", "no-store");

response.setHeader("Pragrma", "no-cache");

response.setDateHeader("Expires", 0);

// 链接来源地址

String referer = request.getHeader("referer");

if (referer == null || !referer.contains(request.getServerName())) {

request.getServerName()//获取你的网站的域名

/**

* 如果 链接地址来自其他网站,则返回错误图片

*/

request.getRequestDispatcher("/error.gif").forward(request,

response);

} else {

/**

* 图片正常显示

*/

chain.doFilter(request, response);

}

}

public void destroy() {

}

}

过滤器继承Filter接口,重载三个方法,分别是init(),doFilter(),destroy().其中doFilter()中必须执行

chain.doFilter(request, response);以便于执行接下来的过滤器。在doFilter()中判断浏览器请求的源地址和服务器的域名是否一致。

2.过滤器配置

通过配置<url-pattern>,说明只有当浏览器访问/images或者/upload/images目录时才执行该过滤器。

字符编码Filter

public class CharacterEncodingFilter implements Filter {

private String characterEncoding;

private String enable;

private boolean enabled;

@Override

public void init(FilterConfig config) throws ServletException {

characterEncoding = config.getInitParameter("characterEncoding");

enable = config.getInitParameter("enable");

enabled = "true".equalsIgnoreCase(enable.trim())

|| "1".equalsIgnoreCase(enable.trim());

}

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

if (enabled&&characterEncoding != null) {

request.setCharacterEncoding(characterEncoding);

response.setCharacterEncoding(characterEncoding);

}

chain.doFilter(request, response);

}

@Override

public void destroy() {

characterEncoding = null;

}

}

个人认为编码Filter应该处于第一个Filter,这样,在tomcat解析request参数前就对参数进行编码设置了。

日志记录Filter

public class LogFilter implements Filter {

private Log log = LogFactory.getLog(this.getClass());

private String filterName;

public void init(FilterConfig config) throws ServletException {

// 获取 Filter 的 name,配置在 web.xml 中

filterName = config.getFilterName();

log.info("启动 Filter: " + filterName);

}

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) res;

long startTime = System.currentTimeMillis();

String requestURI = request.getRequestURI();

requestURI = request.getQueryString() == null ? requestURI

: (requestURI + "?" + request.getQueryString()); //判断请求中是否含有参数,如果有,则加入到requestURI中去。

chain.doFilter(request, response);

long endTime = System.currentTimeMillis();

log.info(request.getRemoteAddr() + " 访问了 " + requestURI + ", 总用时 "

+ (endTime - startTime) + " 毫秒。");//request.getRemoteAddr()返回客户端或代理服务器的IP地址

}

public void destroy() {

log.info("关闭 Filter: " + filterName);

}

}

web配置省略。

异常捕捉Filter

public class ExceptionHandlerFilter implements Filter {

public void destroy() {

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

try { //捕获异常

chain.doFilter(request, response);

} catch (Exception e) { //得到异常后,根据不同异常作相应的处理

Throwable rootCause = e;

while (rootCause.getCause() != null) {

rootCause = rootCause.getCause();

}

String message = rootCause.getMessage();

message = message == null ? "异常:" + rootCause.getClass().getName()

: message;

request.setAttribute("message", message);

request.setAttribute("e", e);

if (rootCause instanceof AccountException) {//判断rootCause是否是AccountException的一个实例

request.getRequestDispatcher("/accountException.jsp").forward(

request, response);

} else if (rootCause instanceof BusinessException) {

request.getRequestDispatcher("/businessException.jsp").forward(

request, response);

} else {

request.getRequestDispatcher("/exception.jsp").forward(request,

response);

}

}

}

public void init(FilterConfig arg0) throws ServletException {

}

}

权限验证Filter

public class PrivilegeFilter implements Filter {

private Properties pp = new Properties();

public void init(FilterConfig config) throws ServletException {

// 从 初始化参数 中获取权 限配置文件 的位置

String file = config.getInitParameter("file");

String realPath = config.getServletContext().getRealPath(file);

try {

pp.load(new FileInputStream(realPath));

} catch (Exception e) {

config.getServletContext().log("读取权限控制文件失败。", e);

}

}

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

// 获取访问的路径,例如:admin.jsp

String requestURI = request.getRequestURI().replace(

request.getContextPath() + "/", "");

// 获取 action 参数,例如:add

String action = req.getParameter("action");

action = action == null ? "" : action;

// 拼接成 URI。例如:log.do?action=list

String uri = requestURI + "?action=" + action;

// 从 session 中获取用户权限角色。

String role = (String) request.getSession(true).getAttribute("role");

role = role == null ? "guest" : role;

boolean authentificated = false;

// 开始检查该用户角色是否有权限访问 uri

for (Object obj : pp.keySet()) {

String key = ((String) obj);

// 使用正则表达式验证 需要将 ? . 替换一下,并将通配符 * 处理一下

if (uri.matches(key.replace("?", "\\?").replace(".", "\\.")

.replace("*", ".*"))) {

// 如果 role 匹配

if (role.equals(pp.get(key))) {

authentificated = true;

break;

}

}

}

if (!authentificated) {

throw new RuntimeException(new AccountException(

"您无权访问该页面。请以合适的身份登陆后查看。"));

}

// 继续运行

chain.doFilter(req, res);

}

public void destroy() {

pp = null;

}

}

内容替换Filter

public class HttpCharacterResponseWrapper extends HttpServletResponseWrapper {

private CharArrayWriter charArrayWriter = new CharArrayWriter();

public HttpCharacterResponseWrapper(HttpServletResponse response) {

super(response);

}

@Override

public PrintWriter getWriter() throws IOException {

return new PrintWriter(charArrayWriter);//将response的输出目标变为charArrayWriter

}

public CharArrayWriter getCharArrayWriter() {

return charArrayWriter;

}

}

public class OutputReplaceFilter implements Filter {

private Properties pp = new Properties();

public void init(FilterConfig config) throws ServletException {

String file = config.getInitParameter("file");

String realPath = config.getServletContext().getRealPath(file);

try {

pp.load(new FileInputStream(realPath));

} catch (IOException e) {

}

}

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

// 自定义的 response

HttpCharacterResponseWrapper response = new HttpCharacterResponseWrapper(

(HttpServletResponse) res);

// 提交给 Servlet 或者下一个 Filter

chain.doFilter(req, response);

// 得到缓存在自定义 response 中的输出内容

String output = response.getCharArrayWriter().toString();

// 修改,替换

for (Object obj : pp.keySet()) {

String key = (String) obj;

output = output.replace(key, pp.getProperty(key));

}

// 输出

PrintWriter out = res.getWriter();

out.write(output);

out.println("<!-- Generated at " + new java.util.Date() + " -->");

}

public void destroy() {

}

}

代码解析:

1.定义一个类HttpCharacterResponseWrapper用于替换原来的response。

2.在过滤器中用res声明一个新的response:

HttpCharacterResponseWrapper response = new HttpCharacterResponseWrapper(

(HttpServletResponse) res);

3.调用chain.doFilter(req, response)时,如果有输出就会调用response.getWriter(), 此时调用的是覆盖后的PrintWriter(),该PrintWriter()将会把数据写到charArrayWriter中去。

4.执行完chain.doFilter(req, response)后,获取charArrayWriter中的数据:

String output = response.getCharArrayWriter().toString();

5.修改output数据

6.再通过原始的res来输出output中的数据

PrintWriter out = res.getWriter();

out.write(output);

以上代码的功能是先将res包装成response(此时response的输出目标不再是客户端,而是charArrayWriter缓存区),接着在读取charArrayWriter内的内用,再通过res的写出方法写到客户端。

GZIP压缩Filter

public class GZipFilter implements Filter {

public void destroy() {

}

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) res;

String acceptEncoding = request.getHeader("Accept-Encoding");

System.out.println("Accept-Encoding: " + acceptEncoding);

if (acceptEncoding != null

&& acceptEncoding.toLowerCase().indexOf("gzip") != -1) {

// 如果客户浏览器支持 GZIP 格式, 则使用 GZIP 压缩数据

GZipResponseWrapper gzipResponse = new GZipResponseWrapper(response);

chain.doFilter(request, gzipResponse);

// 输出压缩数据

gzipResponse.finishResponse();

} else {

// 否则, 不压缩

chain.doFilter(request, response);

}

}

public void init(FilterConfig arg0) throws ServletException {

}

}

类GZipResponseWrapper代码如下:

public class GZipResponseWrapper extends HttpServletResponseWrapper {

// 默认的 response

private HttpServletResponse response;

// 自定义的 outputStream, 执行close()的时候对数据压缩,并输出

private GZipOutputStream gzipOutputStream;

// 自定义 printWriter,将内容输出到 GZipOutputStream 中

private PrintWriter writer;

public GZipResponseWrapper(HttpServletResponse response) throws IOException {

super(response);

this.response = response;

}

public ServletOutputStream getOutputStream() throws IOException {

if (gzipOutputStream == null)

gzipOutputStream = new GZipOutputStream(response);

return gzipOutputStream;

}

public PrintWriter getWriter() throws IOException {

if (writer == null)

writer = new PrintWriter(new OutputStreamWriter(

new GZipOutputStream(response), "UTF-8"));

return writer;

}

// 压缩后数据长度会发生变化 因此将该方法内容置空

public void setContentLength(int contentLength) {

}

public void flushBuffer() throws IOException {

gzipOutputStream.flush();

}

public void finishResponse() throws IOException {

if (gzipOutputStream != null)

gzipOutputStream.close();

if (writer != null)

writer.close();

}

}

类GZipOutputStream代码如下:

public class GZipOutputStream extends ServletOutputStream {

private HttpServletResponse response;

// JDK 自带的压缩数据的类

private GZIPOutputStream gzipOutputStream;

// 将压缩后的数据存放到 ByteArrayOutputStream 对象中

private ByteArrayOutputStream byteArrayOutputStream;

public GZipOutputStream(HttpServletResponse response) throws IOException {

this.response = response;

byteArrayOutputStream = new ByteArrayOutputStream();

gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);

}

public void write(int b) throws IOException {

gzipOutputStream.write(b);

}

public void close() throws IOException {

// 压缩完毕 一定要调用该方法

gzipOutputStream.finish();

// 将压缩后的数据输出到客户端

byte[] content = byteArrayOutputStream.toByteArray();

// 设定压缩方式为 GZIP, 客户端浏览器会自动将数据解压

response.addHeader("Content-Encoding", "gzip");

response.addHeader("Content-Length", Integer.toString(content.length));

// 输出

ServletOutputStream out = response.getOutputStream();

out.write(content);

out.close();

}

public void flush() throws IOException {

gzipOutputStream.flush();

}

public void write(byte[] b, int off, int len) throws IOException {

gzipOutputStream.write(b, off, len);

}

public void write(byte[] b) throws IOException {

gzipOutputStream.write(b);

}

}

代码详解:

1.在过滤器中有如下代码:

// 如果客户浏览器支持 GZIP 格式, 则使用 GZIP 压缩数据

GZipResponseWrapper gzipResponse = new GZipResponseWrapper(response);

chain.doFilter(request, gzipResponse);

// 输出压缩数据

gzipResponse.finishResponse();

第一行是将response包装,目的是压缩response中的数据

第三行是将response中压缩的数据输出到客户端

2.构造一个GZipResponseWrapper类,在此类中重写getWriter方法改变其输出目的地。

public PrintWriter getWriter() throws IOException {

if (writer == null)

writer = new PrintWriter(new OutputStreamWriter(

new GZipOutputStream(response), "UTF-8"));

return writer;

}

因此过滤器中gzipResponse获取的writer将会把数据输出到GZipOutputStream(response)流中。

3.GZipOutputStream流继承于ServletOutputStream,在此类中创建一个缓存区ByteArrayOutputStream并生成GZIPOutputStream的对象gzipOutputStream,并将该流的输出指向缓存区,该类的write方法自动将数据压缩并写到指定目的地。GZipOutputStream的输出都是通过GZIPOutputStream的gzipOutputStream写入到缓存区。

4.当过滤器执行chain.doFilter(request, gzipResponse)期间,假如有数据输出则会调用gzipResponse.getWriter()方法得到PrintWriter out对象。执行out.write("String"),则会进一步调用OutputStreamWriter的write()方法,又会进一步调用GZipOutputStream的write()方法,在

GZipOutputStream的write()方法中,调用GZIPOutputStream的write方法把需要输出的数据压缩并缓存到ByteArrayOutputStream中。

5.当过滤器执行gzipResponse.finishResponse()时,便会关闭PrintWriter writer对象对应的流,即进一步关闭OutputStreamWriter流,进一步关闭GZipOutputStream流,在GZipOutputStream的close方法中将缓存区的ByteArrayOutputStream通过response输出到客户端。

图像水印Filter

思路和上一节GZIP压缩是类似的。

1.WaterMarkFilter代码如下:

public class WaterMarkFilter implements Filter {

// 水印图片,配置在初始化参数中

private String waterMarkFile;

public void init(FilterConfig config) throws ServletException {

String file = config.getInitParameter("waterMarkFile");

waterMarkFile = config.getServletContext().getRealPath(file);

}

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) res;

// 自定义的response

WaterMarkResponseWrapper waterMarkRes = new WaterMarkResponseWrapper(

response, waterMarkFile);

chain.doFilter(request, waterMarkRes);

// 打水印,输出到客户端浏览器

waterMarkRes.finishResponse();

}

public void destroy() {

}

}

2.WaterMarkResponseWrapper代码如下:

public class WaterMarkResponseWrapper extends HttpServletResponseWrapper {

// 水印图片位置

private String waterMarkFile;

// 原response

private HttpServletResponse response;

// 自定义servletOutputStream,用于缓冲图像数据

private WaterMarkOutputStream waterMarkOutputStream;

public WaterMarkResponseWrapper(HttpServletResponse response,

String waterMarkFile) throws IOException {

super(response);

this.response = response;

this.waterMarkFile = waterMarkFile;

this.waterMarkOutputStream = new WaterMarkOutputStream();

}

// 覆盖getOutputStream(),返回自定义的waterMarkOutputStream

public ServletOutputStream getOutputStream() throws IOException {

return waterMarkOutputStream;

}

public void flushBuffer() throws IOException {

waterMarkOutputStream.flush();

}

// 将图像数据打水印,并输出到客户端浏览器

public void finishResponse() throws IOException {

// 原图片数据

byte[] imageData = waterMarkOutputStream.getByteArrayOutputStream()

.toByteArray();

// 打水印后的图片数据

byte[] image = ImageUtil.waterMark(imageData, waterMarkFile);

// 将图像输出到浏览器

response.setContentLength(image.length);

response.getOutputStream().write(image);

waterMarkOutputStream.close();

}

}

3.WaterMarkOutputStream代码如下:

public class WaterMarkOutputStream extends ServletOutputStream {

// 缓冲图片数据

private ByteArrayOutputStream byteArrayOutputStream;

public WaterMarkOutputStream() throws IOException {

byteArrayOutputStream = new ByteArrayOutputStream();

}

public void write(int b) throws IOException {

byteArrayOutputStream.write(b);

}

public void close() throws IOException {

byteArrayOutputStream.close();

}

public void flush() throws IOException {

byteArrayOutputStream.flush();

}

public void write(byte[] b, int off, int len) throws IOException {

byteArrayOutputStream.write(b, off, len);

}

public void write(byte[] b) throws IOException {

byteArrayOutputStream.write(b);

}

public ByteArrayOutputStream getByteArrayOutputStream() {

return byteArrayOutputStream;

}

}

4.ImageUtil代码如下:

public class ImageUtil {

/**

*

* @param imageData

* JPG 图像文件

* @param waterMarkFile

* 水印图片

* @return 加水印后的图像数据

* @throws IOException

*/

public static byte[] waterMark(byte[] imageData, String waterMarkFile)

throws IOException {

// 水印图片的右边距 下边距

int paddingRight = 10;

int paddingBottom = 10;

// 原始图像

Image image = new ImageIcon(imageData).getImage();

int imageWidth = image.getWidth(null);

int imageHeight = image.getHeight(null);

// 水印图片

Image waterMark = ImageIO.read(new File(waterMarkFile));

int waterMarkWidth = waterMark.getWidth(null);

int waterMarkHeight = waterMark.getHeight(null);

// 如果图片尺寸过小,则不打水印,直接返回

if (imageWidth < waterMarkWidth + 2 * paddingRight

|| imageHeight < waterMarkHeight + 2 * paddingBottom) {

return imageData;

}

BufferedImage bufferedImage = new BufferedImage(imageWidth,

imageHeight, BufferedImage.TYPE_INT_RGB);

Graphics g = bufferedImage.createGraphics();

// 绘制原始图像

g.drawImage(image, 0, 0, imageWidth, imageHeight, null);

// 绘制水印图片

g.drawImage(waterMark, imageWidth - waterMarkWidth - paddingRight,

imageHeight - waterMarkHeight - paddingBottom, waterMarkWidth,

waterMarkHeight, null);

g.dispose();

// 转成JPEG格式

ByteArrayOutputStream out = new ByteArrayOutputStream();

JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);

encoder.encode(bufferedImage);

byte[] data = out.toByteArray();

out.close();

return data;

}

}

代码详解:

1.过滤器中如下代码:

// 自定义的response

WaterMarkResponseWrapper waterMarkRes = new WaterMarkResponseWrapper(

response, waterMarkFile);

对response进行包装,使得response的输出数据放入缓存,并对图像数据添加水印

2.chain.doFilter(request, waterMarkRes)执行过程中,如果输出图片,则会调用waterMarkRes.getOutputStream()方法,由于在WaterMarkResponseWrapper中重写了该方法,故得到的是waterMarkOutputStream流。waterMarkOutputStream流中将数据写入到缓存区byteArrayOutputStream流中。

3.过滤器执行waterMarkRes.finishResponse()时,将会把waterMarkOutputStream中的数据取出并添加水印后,通过response.getOutputStream().write(image)将图片写出。

缓存Filter

具体代码详见《JavaWeb整合开发王者归来》

XSLT转换Filter

具体代码详见《JavaWeb整合开发王者归来》

文件上传Filter

1.UploadRequestWrapper代码如下

public class UploadRequestWrapper extends HttpServletRequestWrapper {

private static final String MULTIPART_HEADER = "Content-type";

// 是否是上传文件

private boolean multipart;

// map,保存所有的域

private Map<String, Object> params = new HashMap<String, Object>();

@SuppressWarnings("all")

public UploadRequestWrapper(HttpServletRequest request) {

super(request);

// 判断是否为上传文件

multipart = request.getHeader(MULTIPART_HEADER) != null

&& request.getHeader(MULTIPART_HEADER).startsWith(

"multipart/form-data");

if (multipart) {

try {

// 使用apache的工具解析

DiskFileUpload upload = new DiskFileUpload();

upload.setHeaderEncoding("utf8");

// 解析,获得所有的文本域与文件域

List<FileItem> fileItems = upload.parseRequest(request);

for (Iterator<FileItem> it = fileItems.iterator(); it.hasNext();) {

// 遍历

FileItem item = it.next();

if (item.isFormField()) {

// 如果是文本域,直接放到map里

params.put(item.getFieldName(), item.getString("utf8"));

} else {

// 否则,为文件,先获取文件名称

String filename = item.getName().replace("\\", "/");

filename = filename

.substring(filename.lastIndexOf("/") + 1);

// 保存到系统临时文件夹中

File file = new File(System

.getProperty("java.io.tmpdir"), filename);

// 保存文件内容

OutputStream ous = new FileOutputStream(file);

ous.write(item.get());

ous.close();

// 放到map中

params.put(item.getFieldName(), file);

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

@Override

public Object getAttribute(String name) {

// 如果为上传文件,则从map中取值

if (multipart && params.containsKey(name)) {

return params.get(name);

}

return super.getAttribute(name);

}

@Override

public String getParameter(String name) {

// 如果为上传文件,则从map中取值

if (multipart && params.containsKey(name)) {

return params.get(name).toString();

}

return super.getParameter(name);

}

public static void main(String[] args) {

System.out.println(System.getProperties().toString().replace(", ",

"\r\n"));

}

}

以上代码自定义了request并重写其相关方法。并且判断request中的数据类型,如果是multipart,则把数据名和对应的值放入map集合。通过request.getParameter()和request.getAttribute()方法便可方便获取request的数据。

第六章 过滤器Filter的更多相关文章

  1. ASP.NET MVC 第六回 过滤器Filter

    在Asp.netMvc中当你有以下及类似以下需求时你可以使用Filter功能 判断登录与否或用户权限 决策输出缓存 防盗链 防蜘蛛 本地化与国际化设置 实现动态Action Filter是一种声明式编 ...

  2. 第七章 过滤器 Filter(二)

    一  过滤器API 由容器实现的接口 –javax.servlet.Filter –javax.servlet.FilterChain –javax.servlet.FilterConfig 四个包装 ...

  3. 一、变量.二、过滤器(filter).三、标签(tag).四、条件分支tag.五、迭代器tag.六、自定义过滤器与标签.七、全系统过滤器(了解)

    一.变量 ''' 1.视图函数可以通过两种方式将变量传递给模板页面 -- render(request, 'test_page.html', {'变量key1': '变量值1', ..., '变量ke ...

  4. 第七章 过滤器基础 Filter

    简介:SUN从Servlet2.3开始添加一项激动人心的功能,就是过滤器(Filter).WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图 ...

  5. 一起来学Spring Cloud | 第六章:服务网关 ( Zuul)

    本章节,我们讲解springcloud重要组件:微服务网关Zuul.如果有同学从第一章看到本章的,会发现我们已经讲解了大部分微服务常用的基本组件. 已经讲解过的: 一起来学Spring Cloud | ...

  6. 第十六章 综合实例——《跟我学Shiro》

    简单的实体关系图 简单数据字典 用户(sys_user) 名称 类型 长度 描述 id bigint 编号 主键 username varchar 100 用户名 password varchar 1 ...

  7. Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧

    第六章 Android绘图机制与处理技巧 1.屏幕尺寸信息屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DP ...

  8. Gradle 1.12 翻译——第十六章. 使用文件

    有关其它已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或訪问:http://gradledoc.qiniudn.com ...

  9. 《Django By Example》第六章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:无他,祝大家年会都中奖!) 第六章 ...

随机推荐

  1. 关于flume的filechannel的 full 问题

    事务启动以后,批量向事务Transaction的一个putList的尾部写入,putlist是一个LinkedBlockingDeque . 事务提交的时候, 把putlist中的event批量移除, ...

  2. 《Nginx高性能Web服务器》系列分享专栏

    <Nginx高性能Web服务器>系列分享专栏 [作者:Poechant] Nginx是目前最流行的基于BSD-like协议.轻量级.高性能的HTTP服务器.反向代理服务器和电子邮件(SMT ...

  3. [Golang学习笔记] 01 工作区和GOPATH

    Go语言3个环境变量: GOROOT:GO语言按照根路径,也就是GO语言的安装路径. GOPATH:若干工作区目录的路径.是我自己定义的工作空间. GOBIN:GO程序生成的可执行文件(executa ...

  4. Java 访问控制规则简介

    1. 概述 老生常谈的内容 巩固一下自己 要摇摇欲坠的基础 内容确实不怎么高级... 2. 常规解释 1. 概述 简单说下什么情况 在单纯考虑 public, protected, 以及 privat ...

  5. 20155222 2016-2017-2《Java程序设计》课程总结

    20155222 2016-2017-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1:期望的师生关系 预备作业2:技能获取与语言学习 预备作业3:安装虚拟机及学习linux系 ...

  6. 20155301 2016-2017-2 《Java程序设计》第10周学习总结

    20155301 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 计算机网络: 1.在计算机网络中,现在命名IP地址的规定是IPv4协议,该协议规定每个IP ...

  7. 2017-2018-1 20155318《信息安全技术》实验二——Windows口令破解

    2017-2018-1 20155318<信息安全技术>实验二--Windows口令破解 一.实验原理 口令破解方法 口令破解主要有两种方法:字典破解和暴力破解. 字典破解是指通过破解者对 ...

  8. 回顾RAC安装过程中对ASM的处理

    1 首先建立好节点间共享的磁盘,要注意从各节点看到的磁盘的序号.名称一致. 2 通过某一个节点,对共享磁盘进行格式化. 3 在Grid Infrastructure 中, 有一个为OCR选择存储介质的 ...

  9. 优步UBER司机全国各地奖励政策汇总:北京、上海、广州、深圳、佛山、天津、南京、武汉、成都、重庆、济南、西安、宁波、青岛、长沙、苏州

    Uber当周奖励政策 当前奖励包括:高峰翻倍奖励.行程奖励.金牌司机奖励 获得任何奖励的前提条件: 当周评分高于4.7分,当周成单率高于45%,且当周完成至少5单(含5单) 滴滴快车单单2.5倍,注册 ...

  10. struts2官方 中文教程 系列四:Action

    先贴个本帖的地址,免得其它网站被爬去了struts2教程 官方系列四:Action  即 http://www.cnblogs.com/linghaoxinpian/p/6905521.html 下载 ...