config.getInitParameter() 用来在过滤器中chain.dofilter报异常中执行 可以获取到值嘛?这个需要在web.xml中配置嘛?

java web中的过滤器_百度知道Filter概述
Filter不用于客户端请求,只用于对request,response进行修改或对context,session,request事件进行监听。
如上图,多个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)
HttpServletResponse response = (HttpServletResponse)
// 禁止缓存
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);
* 图片正常显示
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 characterE
public void init(FilterConfig config) throws ServletException {
characterEncoding = config.getInitParameter(&characterEncoding&);
enable = config.getInitParameter(&enable&);
enabled = &true&.equalsIgnoreCase(enable.trim())
|| &1&.equalsIgnoreCase(enable.trim());
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);
public void destroy() {
characterEncoding =
个人认为编码Filter应该处于第一个Filter,这样,在tomcat解析request参数前就对参数进行编码设置了。
日志记录Filter
public class LogFilter implements Filter {
private Log log = LogFactory.getLog(this.getClass());
private String filterN
public void init(FilterConfig config) throws ServletException {
// 获取 Filter 的 name,配置在 web.xml 中
filterName = config.getFilterName();
<(&启动 Filter: & + filterName);
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)
HttpServletResponse response = (HttpServletResponse)
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();
<(request.getRemoteAddr() + & 访问了 & + requestURI + &, 总用时 &
+ (endTime - startTime) + & 毫秒。&);//request.getRemoteAddr()返回客户端或代理服务器的IP地址
public void destroy() {
<(&关闭 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 =
while (rootCause.getCause() != null) {
rootCause = rootCause.getCause();
String message = rootCause.getMessage();
message = message == null ? &异常:& + rootCause.getClass().getName()
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);
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);
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)
// 获取访问的路径,例如:admin.jsp
String requestURI = request.getRequestURI().replace(
request.getContextPath() + &/&, &&);
// 获取 action 参数,例如:add
String action = req.getParameter(&action&);
action = action == null ? && :
// 拼接成 URI。例如:log.do?action=list
String uri = requestURI + &?action=& +
// 从 session 中获取用户权限角色。
String role = (String) request.getSession(true).getAttribute(&role&);
role = role == null ? &guest& :
boolean authentificated =
// 开始检查该用户角色是否有权限访问 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 =
if (!authentificated) {
throw new RuntimeException(new AccountException(
&您无权访问该页面。请以合适的身份登陆后查看。&));
// 继续运行
chain.doFilter(req, res);
public void destroy() {
内容替换Filter
public class HttpCharacterResponseWrapper extends HttpServletResponseWrapper {
private CharArrayWriter charArrayWriter = new CharArrayWriter();
public HttpCharacterResponseWrapper(HttpServletResponse response) {
super(response);
public PrintWriter getWriter() throws IOException {
return new PrintWriter(charArrayWriter);//将response的输出目标变为charArrayWriter
public CharArrayWriter getCharArrayWriter() {
return charArrayW
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);
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)
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)
HttpServletResponse response = (HttpServletResponse)
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();
// 否则, 不压缩
chain.doFilter(request, response);
public void init(FilterConfig arg0) throws ServletException {
类GZipResponseWrapper代码如下:
public class GZipResponseWrapper extends HttpServletResponseWrapper {
// 默认的 response
private HttpServletR
// 自定义的 outputStream, 执行close()的时候对数据压缩,并输出
private GZipOutputStream gzipOutputS
// 自定义 printWriter,将内容输出到 GZipOutputStream 中
private PrintW
public GZipResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
this.response =
public ServletOutputStream getOutputStream() throws IOException {
if (gzipOutputStream == null)
gzipOutputStream = new GZipOutputStream(response);
return gzipOutputS
public PrintWriter getWriter() throws IOException {
if (writer == null)
writer = new PrintWriter(new OutputStreamWriter(
new GZipOutputStream(response), &UTF-8&));
// 压缩后数据长度会发生变化 因此将该方法内容置空
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 HttpServletR
// JDK 自带的压缩数据的类
private GZIPOutputStream gzipOutputS
// 将压缩后的数据存放到 ByteArrayOutputStream 对象中
private ByteArrayOutputStream byteArrayOutputS
public GZipOutputStream(HttpServletResponse response) throws IOException {
this.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&));
因此过滤器中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 waterMarkF
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)
HttpServletResponse response = (HttpServletResponse)
// 自定义的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 waterMarkF
// 原response
private HttpServletR
// 自定义servletOutputStream,用于缓冲图像数据
private WaterMarkOutputStream waterMarkOutputS
public WaterMarkResponseWrapper(HttpServletResponse response,
String waterMarkFile) throws IOException {
super(response);
this.response =
this.waterMarkFile = waterMarkF
this.waterMarkOutputStream = new WaterMarkOutputStream();
// 覆盖getOutputStream(),返回自定义的waterMarkOutputStream
public ServletOutputStream getOutputStream() throws IOException {
return waterMarkOutputS
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 byteArrayOutputS
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 byteArrayOutputS
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 imageD
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();
代码详解:
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&;
// 是否是上传文件
// 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) {
// 使用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&));
// 否则,为文件,先获取文件名称
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();
public Object getAttribute(String name) {
// 如果为上传文件,则从map中取值
if (multipart && params.containsKey(name)) {
return params.get(name);
return super.getAttribute(name);
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(&, &,
以上代码自定义了request并重写其相关方法。并且判断request中的数据类型,如果是multipart,则把数据名和对应的值放入map集合。通过request.getParameter()和request.getAttribute()方法便可方便获取request的数据。<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&}

我要回帖

更多关于 getinitparameter 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信