学习要点

  • 过滤器
  • 监听器

过滤器Filter

过滤器的概念

  • 过滤器位于客户端和web应用程序之间,用于检查和修改两者之间流过的请求和响应。
  • 在请求到达Servlet/JSP之前,过滤器截获请求。
  • 在响应送给客户端之前,过滤器截获响应。
  • 多个过滤器形成一个过滤器链,过滤器链中不同过滤器的先后顺序由部署文件web.xml中过滤器映射<filter-mapping>的顺序决定。
  • 最先截获客户端请求的过滤器将最后截获Servlet/JSP的响应信息。

过滤器的链式结构

可以为一个Web应用组件部署多个过滤器,这些过滤器组成一个过滤器链,每个过滤器只执行某个特定的操作或者检查。这样请求在到达被访问的目标之前,需要经过这个过滤器链。

实现过滤器

在Web应用中使用过滤器需要实现javax.servlet.Filter接口,实现Filter接口中所定义的方法,并在web.xml中部署过滤器。

public class MyFilter implements Filter {

    public void init(FilterConfig fc) {
//过滤器初始化代码
} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
//在这里可以对客户端请求进行检查
//沿过滤器链将请求传递到下一个过滤器。
chain.doFilter(request, response);
//在这里可以对响应进行处理 } public void destroy( ) {
//过滤器被销毁时执行的代码
} }

  

Filter接口常用方法

方法名称

功能描述

public void init(FilterConfig config)

容器在实例化过滤器调用。FilterConfig对象包含Filter相关的配置信息。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

每当请求和响应经过过滤器链时,容器都调用一次该方法。过滤器的一个实例可以同时服务于多个请求,需要注意线程同步问题,尽量不用或少用实例变量。 在过滤器的doFilter()方法实现中,任何出现在FilterChain的doFilter方法之前地方,request是可用的;在doFilter()方法之后response是可用的。

public void destroy()

容器调用destroy()方法指出将从服务中删除该过滤器。如果过滤器使用了其他资源,需要在这个方法中释放这些资源。

部署过滤器

在Web应用的WEB-INF目录下,找到web.xml文件,在其中添加如下代码来声明Filter。

<filter>
<filter-name>MyFilter</filter-name>
<filter-class>
com.etc.web.MyFilter
</filter-class>
<init-param>
<param-name>codeFilter</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
//针对一个Servlet做过滤
<filter-mapping>
<filter-name>MyFilter</filter-name>
<servlet-name>MyServlet</servlet-name>
</filter-mapping>
//针对URL Pattern做过滤
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

  

<filter-mapping>标记是有先后顺序的,它的声明顺序说明容器是如何形成过滤器链的。过滤器应当设计为在部署时很容易配置的形式。通过使用初始化参数,可以得到复用性很高的过滤器。

过滤器逻辑与Servlet逻辑不同,它不依赖于任何用户状态信息,因为一个过滤器实例可能同时处理多个完全不同的请求。

新闻发布系统中,添加Post乱码处理过滤器

在web.xml中配置过滤器信息

<web-app>
<filter>
<filter-name>EncodeFilter</filter-name>
<filter-class>com.etc.news.web.EncodeFilter</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

  

注解方式部署过滤器

<!-- @WebFilter(urlPatterns = {"/*"},filterName="EncodeFilter" ,initParams = {@WebInitParam(name = "encode", value = "utf-8")}) -->

  

编写自定义类EncodeFilter

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class EncodeFilter implements Filter {
private String encode = null; public void destroy() {
encode = null;
} public void init(FilterConfig filterConfig) throws ServletException {
String encode = filterConfig.getInitParameter("encode");
if (this.encode == null) {
this.encode = encode;
}
} // 对所有页面设置字符集
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (null == request.getCharacterEncoding()) {
request.setCharacterEncoding(encode);
}
chain.doFilter(request, response);
response.setContentType("text/html;charset="+encode);
response.setCharacterEncoding(encode);
}
}

  

支持post和get方式的编码过滤器

HttpServletRequestWrapper和HttpServletResponseWrapper类

  • Servlet2.1规范中的filter引入了一个功能强大的拦截模式。Filter能在request到达servlet的服务方法之前拦截HttpServletRequest对象,而在服务方法转移控制后又能拦截HttpServletResponse对象。
  • 但是HttpServletRequest中的参数是无法改变的,若是手动执行修改request中的参数,则会抛出异常。且无法获取到HttpServletResponse中的输出流中的数据,因为HttpServletResponse中输出流的数据会写入到默认的输出端,你手动无法获取到数据。
  • 我们可以利用HttpServletRequestWrapper包装HttpServletRequest,用HttpServletResponseWrapper包装HttpServletResponse,在Wrapper中实现参数的修改或者是response输出流的读取,然后用HttpServletRequestWrapper替换HttpServletRequest,HttpServletResponseWrapper替换HttpServletResponse。这样就实现了参数的修改设置和输出流的读取。
  • HttpServletRequestWrapper是HttpServletRequest的一个实现类,所以可以用HttpServletRequestWrapper替换HttpServletRequest。ServletRequestWrapper采取了装饰器器模式,实际上内部操作的就是构造方法中传递的ServletRequest。
  • HttpServletResponseWrapper是HttpServletResponse的实现类,所以HttpServletResponseWrapper可以替换HttpServletResponse。同ServletResponseWrapper一样,ServletResponseWrapper也是采去了装饰器模式,内部操作的也是构造方法中传递的ServletResponse。
  • 装饰器模式:在java输入输出流中常见,处理流经常需要节点流作为参数来构建。例如BufferedInputStream,BufferedOutputSteam、BuffereReader、BuferedWriter等等。

请求装饰类示例代码

import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; /**
* 对Get方式传递的请求参数进行编码
*/
public class CharacterEncodingRequest extends HttpServletRequestWrapper {
private HttpServletRequest request = null;
public CharacterEncodingRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
/**
* 对参数重新编码
*/
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value == null)
return null;
String method = request.getMethod();
if ("get".equalsIgnoreCase(method)) {
try {
value = new String(value.getBytes("ISO8859-1"),
request.getCharacterEncoding());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return value;
}
}

  

过滤器代码

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class CharacterEncodingFilter implements Filter {
private String encode = "UTF-8";// 默认UTF-8编码
public void init(FilterConfig filterConfig) throws ServletException {
String encoding = filterConfig.getInitParameter("encode");
if (encoding != null) {
this.encode = encoding;
}
} public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 设置request编码
request.setCharacterEncoding(encode);
chain.doFilter(new CharacterEncodingRequest(request), response);
// 设置响应信息编码
response.setContentType("text/html;charset=" + encode);
response.setCharacterEncoding(encode);
}
public void destroy() {
}
}

  

HttpServletRequestWrapper用于实现敏感字过滤

项目结构

定义HTTP包装类

package com.etc.filter;

import java.util.Iterator;
import java.util.Map;
import java.util.Set; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; /** http 请求包装器 */
public class HttpRequestWrapper extends HttpServletRequestWrapper { private Map<String, String> map = null;// 需要替换内容的集合key敏感字 value替换内容 public HttpRequestWrapper(HttpServletRequest request) {
super(request);
} /**
* 敏感字替换
*
* @param rs请求字符串
* @return 替换敏感字后的字符串
*/
public String replace(String rs) {
StringBuffer rssb = new StringBuffer(rs);// StringBuffer修改字符串不产生副本,非线程安全,速度快
Set<String> keys = this.getMap().keySet();// map的key为敏感字集合
Iterator<String> it = keys.iterator();// 敏感字迭代器
//String ss = null;// 存储key变量
while (it.hasNext()) {
String key = it.next();
int index = rssb.indexOf(key);// 查找字符串中是否存在需要替换的内容
if (index != -1 && key != null) {// 找到敏感字并且敏感字集合该敏感字不为空,执行替换
//ss = key;
rssb.replace(index, index + key.length(), this.getMap().get(key));// 替换敏感字
}
}
// if (ss != null) {
// if (rssb.toString().indexOf(ss) == -1) {// 确保已经替换完毕
// return rssb.toString();
// } else {// 再次进行替换
// return replace(rssb.toString());
// }
// }
return rssb.toString();
} //Servlet中实际调用的getParameter方法: 重写的getParameter()方法
public String getParameter(String str) {
String content = super.getParameter(str);
return replace(content);// 返回被替换文本
// if (str.equals("pager.offset")) {// JSP视图使用pager-taglib分页框架的分页信息。忽略处理
// return super.getParameter(str);
// } else {// 敏感字替换
// String content = super.getParameter(str);
// return replace(content);// 返回被替换文本
// }
} public Map<String, String> getMap() {
return map;
} public void setMap(Map<String, String> map) {
this.map = map;
} }

  

定义内容过滤器

package com.etc.filter;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest; /** 内容过滤器 */
@WebFilter(filterName = "ContentFilter", urlPatterns = "*.action", initParams = {
@WebInitParam(name = "filePath", value = "/WEB-INF/words") })
public class ContentFilter implements Filter { private Map<String, String> map = new HashMap<String, String>(); // 过滤器的初始化:读取敏感字文件
public void init(FilterConfig config) throws ServletException {
String filePath = config.getInitParameter("filePath");// 从配置文件中取得文件的相对路径/WEB-INF/words
ServletContext context = config.getServletContext();// 读取上下文环境
String realPath = context.getRealPath(filePath);// 绝对路径D:\Tomcat7\webapps\guestbook\WEB-INF\words
FileReader fr = null;//节点流
BufferedReader br = null;//处理流
// 根据相对路径取得绝对路径
try {
fr = new FileReader(realPath);// 根据绝对路径,通过文件流来读取文件
br = new BufferedReader(fr);
String line = null;
while ((line = br.readLine()) != null) {
String[] str = line.split("==");// 按照==拆分字符串
map.put(str[0], str[1]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
if (fr != null) {
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 处理请求中的数据:使用HttpRequestWrapper包装类替换HttpRequest
HttpRequestWrapper hrw = new HttpRequestWrapper((HttpServletRequest) request);
hrw.setMap(map);
chain.doFilter(hrw, response);// 过滤链
} @Override
public void destroy() {
this.map = null;
}
}

  

监听器

Servlet事件

Web容器管理Servlet/JSP相关的生命周期。

Servlet事件是指HttpServletRequest对象、HttpSession对象、ServletContext对象生成、销毁或相关属性进行了设置等等事件。

Servlet监听器

监听器由web容器管理,它的作用是监听Servlet有效事件,并根据需求做出适当响应。下表为Servlet和JSP中的8个Listener和6个Event类。

Listener接口

监听Event类

ServletContextListener

ServletContextEvent

ServletContextAttributeListener

ServletContextAttributevent

HttpSessionListener

HttpSessionEvent

HttpSessionActivationListener

HttpSessionAttributeListener

HttpSessionBindingEvent

HttpSessionBindingListener

ServletRequestListener

ServletRequestEvent

ServletRequestAttributeListener

ServletRequestAttributeEvent

Servlet监听器的功能和Java的GUI的监听器类似,可以监听Servlet容器由于Web应用程序中状态改变而产生的相应事件,然后接受和处理这些事件。

监听Servlet上下文

用于监听ServletContext对象的创建、删除和添加属性,以及删除和修改操作,主要用到以下接口:

1.ServletContextListener接口

该接口主要用来监听SerrvletContext的创建和删除,他提供了以下两个方法,也称为“web应用程序的生命周期方法”:

    • contextInitialized(ServletContextEvent event)方法:通知正在收听的对象应用程序已经被加载及初始化。
    • contextInitialized(ServletContextEvent event)方法:通知正在收听的对象应用程序已经被载出、即将关闭。

2.ServletContextAttributeListener接口

用来监听ServletContext属性的增加、删除及修改,它提供了一下三个方法:

    • attributeAdded(ServletContextAttributeEvent event)方法:若有对象加入application范围,通知正在收听的对象。
    • attributeReplaced(ServletContextAttributeEvent event)方法:若在application范围内的对象取代另一个对象,通知正在收听的对象。
    • attributeRemoved(ServletContextAttributeEvent event)方法:若有对象从application范围被移除,则通知正在收听的对象。

监听HTTP会话

提供了4个接口监听HTTP会话(HTTPSEession)信息。

1.HttpSessionListener接口

该接口监听HTTP会话的创建及撤销,它提供了两个方法:

    • sessionCreated(HttpSessionEvent  event)方法:通知正在收听的对象,session已经被加载及初始化。
    • sessionDestroyed(HttpSessionEvent  event)方法:通知正在收听的对象,session已经被载出(HttpSessionEvent类的主要方法是getSession,可以使用该方法回传一个session对象)。

2.HttpSessionActivationListener接口

该接口实现监听HTTP会话active和passivate情况,它提供了如下2个方法。

  • sessionDidActivate(HttpSessionEvent  event)方法:通知正在收听的对象,其session已经变为有效状态。
  • sessionWillPassivate(HttpSessionEvent  event)方法:通知正在收听的对象,其session已经变为无效的状态。

3.HttpSessionAttributeListener接口

该接口实现监听HTTP会话中属性的设置请求,它提供了3个方法:

  • attributeAdded(HttpSessionBindingEvent event)方法:若有对象加入session的范围,通知正在收听的对象。
  • attributeRemoved(HttpSessionBindingEvent event)方法:若有对象从session的范围移除,通知正在收听的对象(HttpSessionBindingEvent类主要有三个方法:getName()、getSession()、getValues())。
  • attributeReplaced(HttpSessionBindingEvent event)方法:若在session范围内一个对象取代另一个对象,则通知在收听的对象。

4.HttpSessionBindingListener接口

该接口实现监听HTTP会话中对象的绑定信息,它是唯一不需要在web.xml中设置Listener的,它提供了两个方法:

  • valueBound(HttpSessionBindingEvent event)方法:当有对象加入session范围时,自动调用。
  • valueUnbound(HttpSessionBindingEvent  event)方法:当有对象从session范围内移除时,会被自动调用。

监听Servlet请求

用来监听客户端的请求,一旦在监听程序中获取了客户端的请求,就可以统一处理请求,它提供了两个接口。

1.ServletRequestListener接口

    • requestInitialized(ServletRequestEvent  event)方法:通知正在收听的对象,ServletRequest已经被加载及初始化。
    • requestDestroyed(ServletRequestEvent  event)方法:通知正在收听的对象,ServletRequest已经被载出,即将关闭。

2.ServletRequestAttributeListener接口

    • attributeAdded(ServletRequestAttributeEvent event)方法:若有对象加入request的范围,通知正在收听的对象。
    • attributeRemoved(ServletRequestAttributeEvent event)方法:若有对象从request范围移除,通知正在收听的对象。
    • attributeReplaced(ServletRequestAttributeEvent event)方法:若有对象在request范围被取代,通知正在收听的对象。

监听器实例:使用监听器查看在线用户

1.UserContainer类

package com.etc.listener;

import java.util.LinkedList;
import java.util.List; /** 在线用户操作类 ————单例模式 */
public class UserContainer {
private static UserContainer userContainer = new UserContainer(); private List<String> list = null;//保存用户账号 private UserContainer() {
this.list = new LinkedList<String>();
} /** 在线用户操作类单例模式 :所有的用户都保存在一个UserInfoList对象中 */
public static UserContainer getInstance() {
return userContainer;
} /** 添加用户 */
public boolean addUser(String user) {
if (user != null) {
this.list.add(user);
return true;
} else {
return false;
}
} /** 删除用户 */
public void removeUser(String user) {
if (user != null) {
for (int i = 0; i < list.size(); i++) {
if (user.equals(list.get(i))) {
list.remove(i);
}
}
}
} /** 获取用户列表 */
public List<String> getList() {
return this.list;
} }

  

2.监听在线用户类

 

package com.etc.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener; /** 监听在线用户类 */
@WebListener
public class UserListener implements HttpSessionBindingListener { private String user;// 用户字符串
private UserContainer userContainer = UserContainer.getInstance();// 用户信息处理实例 public UserListener() {
this.user = null;
} /** 设置在线监听人员 */
public void setUser(String user) {
this.user = user;
} /** 获取在线人员 */
public String getUser() {
return this.user;
} /** 当有对象加入session范围时,自动调用 */
@Override
public void valueBound(HttpSessionBindingEvent arg0) {
System.out.println(this.user + "上线 ");
this.userContainer.addUser(this.user);
} /** 当有对象从session范围内移除时,会被自动调用 */
@Override
public void valueUnbound(HttpSessionBindingEvent arg0) {
System.out.println(this.user + "下线 ");
this.userContainer.removeUser(this.user);
}
}

  

3.Servlet处理类

package com.etc.action;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import com.etc.listener.UserContainer;
import com.etc.listener.UserListener; @WebServlet("/ServletLogin.action")
public class ServletLogin extends HttpServlet {
private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
UserContainer userContainer = UserContainer.getInstance();
UserListener userListener = new UserListener();
String user = request.getParameter("name").trim();// 获取用户名
if (user.length() == 0) {
user = "默认用户";
}
userListener.setUser(user);// 设定监听用户
session.setAttribute("userListener", userListener);
userContainer.addUser(userListener.getUser());// 用户信息添加到用户信息处理类
session.setMaxInactiveInterval(30);
System.out.println(userContainer.getList().size());
} protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }

  

4.登陆处理代码

<%
UserInfoList list = UserInfoList.getInstance();
UserInfoTrace trace = new UserInfoTrace();
request.setCharacterEncoding("utf-8");
String user = request.getParameter("name").trim();//获取用户名
if (user.length() == 0) {
user = "默认用户";
}
trace.setUser(user);//设定监听用户
session.setAttribute("trace", trace);
list.addUser(trace.getUser());//用户信息添加到用户信息处理类
session.setMaxInactiveInterval(30);
%>
<h3>当前登录用户</h3>
<ul>
<%
Vector<String> vector = list.getList();
for (int i = 0; i < vector.size(); i++) {
out.print("<li>" + vector.elementAt(i) + "</li>");
}
%>
</ul>

  

5.登陆视图代码

  

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登陆视图</title>
</head>
<body>
<form action="ServletLogin.action" method="post">
<p>
用户名:<input type="text" name="name">
</p>
<p>
<input type="submit" value="登陆">
</p>
</form>
</body>
</html>

  

JavaEE-07 过滤器和监听器的更多相关文章

  1. Unit08: 过滤器、监听器

    Unit08: 过滤器.监听器 下面这些小案例主要演示的filter的执行时机: web package web; import java.io.IOException; import javax.s ...

  2. SpringBoot | 第七章:过滤器、监听器、拦截器

    前言 在实际开发过程中,经常会碰见一些比如系统启动初始化信息.统计在线人数.在线用户数.过滤敏高词汇.访问权限控制(URL级别)等业务需求.这些对于业务来说一般上是无关的,业务方是无需关系的,业务只需 ...

  3. struts2 javaweb 过滤器、监听器 拦截器 原理

    转: 过滤器.监听器 拦截器 过滤器 创建一个 Filter 只需两个步骤: (1)创建 Filter 处理类: (2)在 web.xml 文件中配置 Filter . 创建 Filter 必须实现 ...

  4. 面试之servlet、过滤器、监听器

    servlet.过滤器.监听器servlet是Java中WEB请求和响应的容器servlet的运行需要在类似tomcat容器中,一个 Web 应用对应一个 Context 容器,也就是 Servlet ...

  5. 第16 天 JavaWEB过滤器和监听器技术

    Day16 JavaWEB过滤器和监听器技术 复习: 1.大结果集分页mysql的实现,是使用那个关键字,从user表中取第一页的数据,长度为10,sql语句怎么写? 2.分页查询的起始位置(star ...

  6. Servlet过滤器和监听器知识总结(转)

    Servlet过滤器和监听器知识总结(转)  Servlet过滤器是 Servlet 程序的一种特殊用法,主要用来完成一些通用的操作,如编码的过滤.判断用户的登录状态.过滤器使得Servlet开发者能 ...

  7. springBoot(6)---过滤器,监听器,拦截器

    过滤器,监听器,拦截器 一.理解它们 看里十几篇博客,总算有点小明白,总的来讲,两张图可以让我看明白点. 通过两幅图我们可以理解拦截器和过滤器的特点 1.过滤器 过滤器是在请求进入tomcat容器后, ...

  8. SpringBoot学习(八)-->SpringBoot之过滤器、监听器

    本文将直接使用@WebFilter和@WebListener的方式,完成一个Filter 和一个 Listener. 过滤器(Filter)和 监听器(Listener)的注册方法和 Servlet ...

  9. Java基础——过滤器和监听器

    什么是过滤器? Servlet过滤器和Servlet十分相似,但它具有拦截客户端请求的功能,Servlet过滤器可以改变请求中的内容,来满足实际开发中的需要.对于开发人员而言,过滤器实际上就是在Web ...

  10. 小白的springboot之路(十三)、过滤器、监听器、拦截器

    0.前言 过滤器.监听器.拦截器在实际开发中经常需要用到,下面我们来介绍一下spring boot中如何使用: 一.------ 过滤器 ----- 1.作用: 过滤器是客户端与服务器资源文件之间的一 ...

随机推荐

  1. 在头文件#pragma comment(lib,"glaux.lib");编译器提示waring C4081: 应输入“newline“

    在头文件#pragma comment(lib,"glaux.lib");编译器提示waring C4081: 应输入“newline“ #行不能加分号的

  2. 数据类型总结 (C++)

    数据类型总结 (C++) 作用 C++ 大小 取值范围 后缀 字符 char 1 -128~127   字符(无符号) unsigned char 1 0~255   宽字符 wchar_t 2   ...

  3. hdoj1728【搜索的两种写法】

    以前的一道题目,现在拿到总觉得是DFS,然后T掉就没什么想法了,很狗的看了以前的写法(以前还是看题解的AC的),是BFS,每次都要转弯,但是之前你的达到一种他走到了死路,所以才是不得不转弯,写法也是非 ...

  4. poj2421【MST-prim+Kruskal】

    水过~~~~打好基础/~~ ------prim #include <iostream> #include <stdio.h> #include <string.h> ...

  5. poj 2406 Power Strings【kmp】

    kmp,根据next数组的性质如果有答案的话就是n/(n-(ne[n]+1)),否则是1 搬来打算用SA后来发现必须用DC3就没写 #include<iostream> #include& ...

  6. LuoguP2055 [ZJOI2009]假期的宿舍【二分图最大匹配】By cellur925

    题目传送门 这道题开始感觉不出是二分图最大匹配的qwq.但是今天学了匈牙利算法,想来做几个题qwq.做这个题的时候想了很久它哪里是二分图,脑子里是“两列,每列有很多点的那种图 qwq.” 然后看了题解 ...

  7. Mantis优化改造(功能篇)

    共分为两篇,功能篇和技术篇. 时间大约是2016年冬天. 考虑搭一个用于Bug管理和追踪的系统. 综合比较下,选择了小巧的开源工具,Mantis. 在源码基础上,做代码修改,完成了定制版的优化改造. ...

  8. 2018 年度码云热门项目排行榜 TOP 10

    2016 年度码云热门项目排行榜 TOP 10 是通过开源项目2016年在码云上的 Watch.Star.Fork 数量来评定的榜单.码云平台发展至今,涌现了越来越多优秀的开源项目,越来越多的开源作者 ...

  9. java 丢失的异常

    采用finally从句中的,可能会丢失异常 package thinking; //: LostMessage.java // How an exception can be lost class V ...

  10. 跟我一起玩Win32开发(4):创建菜单

    也不知道发生什么事情,CSDN把我的文章弄到首页,结果有不少说我在误人子弟,是啊,我去年就说过了,如果你要成为砖家级人物,请远离我的博客,我这个人没什么特长,唯一厉害的一点就是不相信权威,鄙视砖家,所 ...