JavaWeb学习总结(十五)--过滤器的应用
一、解决全站字符乱码(post和get中文编码问题)
乱码问题:
- 获取请求参数中的乱码问题;
- POST请求:request.setCharacterEncoding(“utf-8”);
- GET请求:new String(request.getParameter(“xxx”).getBytes(“iso-8859-1”), “utf-8”);
- 响应的乱码问题:
- response.setContextType(“text/html;charset=utf-8”)
使用Decorator模式包装request对象解决get和post请求方式下的中文乱码问题
编写一个用于处理中文乱码的过滤器CharacterEncodingFilter,代码如下:
package cn.zy.filter; 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.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse; public class CharacterEncodingFilter implements Filter {
private FilterConfig filterConfig = null;
//设置默认的字符编码
private String defaultCharset = "UTF-8"; public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse) resp;
//得到在web.xml中配置的字符编码
String charset = filterConfig.getInitParameter("charset");
if(charset==null){
charset = defaultCharset;
}
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
response.setContentType("text/html;charset="+charset); //使用得到加强的request
EncodingRequest requestWrapper = new EncodingRequest(request);
chain.doFilter(requestWrapper, response);
} public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig; } public void destroy() {
} /*
* 写一个装饰类增强HttpServletRequest对象
*/
class EncodingRequest extends HttpServletRequestWrapper {
//定义一个变量记住被增强对象(request对象是需要被增强的对象)
private HttpServletRequest request;
//定义一个构造函数,接收被增强对象
public EncodingRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
/* 覆盖需要增强的getParameter方法
* @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
*/
@Override
public String getParameter(String name) {
try{
//获取参数的值
String value= this.request.getParameter(name);
if(value==null){
return null;
}
//如果不是以get方式提交数据的,就直接返回获取到的值
if(!this.request.getMethod().equalsIgnoreCase("get")) {
return value;
}else{
//如果是以get方式提交数据的,就对获取到的值进行转码处理
value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
return value;
}
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
在web.xml文件中配置Filter
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>cn.zy.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
编写一个测试的用的jsp提交表单
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head> <body>
<form action="<c:url value='/Aservlet'/>" method="post">
用户名: <input type="text" name="username">
<input type="submit" value="提交"/>
</form>
<a href="<c:url value='/Aservlet?username=张三'/>">点击这里</a><br/>
</body>
</html>
编写一个Servlet用于处理请求
package cn.zy.filter; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class Aservlet extends HttpServlet { /**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
//获取请求方式
String method = request.getMethod();
response.getWriter().print("请求方式" +method+"参数:"+username);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }
二、统计每个访问次数
写一个监听器,在服务启动时创建一个map,用于保存访问IP和次数
package cn.zy.listener; import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; public class CreateMapListener implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) {
/*
* 在服务器启动时创建map
*/
Map<String,Integer> map = new LinkedHashMap<String,Integer>();
//得到ServletContext
ServletContext application = sce.getServletContext();
//把Map保存到ServletContext中
application.setAttribute("map", map);
} public void contextDestroyed(ServletContextEvent sce) { } }
创建一个Filter用于统计访问次数
package cn.zy.filter; import java.io.IOException;
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; /*
* 获取某个IP访问本站的次数
*/
public class AccessCountFilter implements Filter {
private FilterConfig config; public void destroy() {
} public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//1. 得到appliction
ServletContext app = config.getServletContext();
//2.从application中获取map
Map<String,Integer> map = (Map<String, Integer>) app.getAttribute("map");
//3.获取客户端的地址
String ip = request.getRemoteAddr();
/*
* 4.进行判断IP是否是第一次访问,如果不是则加1,如果是则设置为1
*/
if(map.containsKey(ip)){
int cnt = map.get(ip);
map.put(ip, cnt+1);
}else{
map.put(ip, 1);
}
//5.把map重新放回到app中
app.setAttribute("map", map);
//6.放行
chain.doFilter(request, response);
} public void init(FilterConfig filterConfig) throws ServletException {
this.config=filterConfig; } }
web.xml中的配置:
<filter>
<filter-name>AccessCountFilter</filter-name>
<filter-class>cn.zy.filter.AccessCountFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AccessCountFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 配置Listener -->
<listener>
<listener-class>cn.zy.listener.CreateMapListener</listener-class>
</listener>
创建一个jsp用于显示
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'show.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> </head> <body>
<h1 align="center">显示结果</h1>
<table align="center" width="60%" border="1">
<tr>
<th>IP</th>
<th>次数</th>
</tr>
<c:forEach items="${applicationScope.map }" var="entry">
<tr>
<td>${entry.key }</td>
<td>${entry.value }</td>
</tr>
</c:forEach>
</table>
</body>
</html>
结果如下图所示:
三、粗粒度权限控制(控制页面的访问权限)
目的:
我们给出三个页面:index.jsp、user.jsp、admin.jsp。
l index.jsp:谁都可以访问,没有限制;
l user.jsp:只有登录用户才能访问;
l admin.jsp:只有管理员才能访问。
创建一个登陆界面,用于提交表单
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'login.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
--> </head> <body>
<h1>登录</h1>
${msg }
<form action="<c:url value='/LoginServlet' />" method="post">
用户名:<input type="text" name="username" /><br>
密码:<input type="password" name="password" /> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
2.创建一个Servlet处理表单
package cn.zy.web.servlet; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); /*
* 1.获取用户名
* 2.如果含有admin则是管理员
* 3.如果不包含则为普通用户
*/ String username = request.getParameter("username");
if(username.contains("admin")){
request.getSession().setAttribute("admin", username);
}else{
request.getSession().setAttribute("username", username);
}
request.getRequestDispatcher("/index.jsp").forward(request, response);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
} }
2.创建一个jsp,用于链接到不同的页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head> <body>
<h1>你就是个游客而已</h1>
<a href="<c:url value='/index.jsp'/>">游客入口</a><br/>
<a href="<c:url value='/users/u.jsp'/>">会员入口</a><br/>
<a href="<c:url value='/admin/a.jsp'/>">管理员入口</a><br/>
</body>
</html>
3.创建两个jsp,内容就是普通用户能访问的页面和管理员才能访问的页面
4.做两个过滤器,用于权限控制
AdminFilter
package cn.zy.filter; 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; public class AdminFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//得到Session
HttpServletRequest req = (HttpServletRequest)request;
String name = (String)req.getSession().getAttribute("admin");
if(name != null){
chain.doFilter(request, response);
}else{
req.setAttribute("msg", "您不是管理员!");
req.getRequestDispatcher("/login.jsp").forward(request, response);
}
} public void init(FilterConfig arg0) throws ServletException {
}
}
UserFilter
package cn.zy.filter; 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; public class UserFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request;
String name = (String)req.getSession().getAttribute("admin");
if(name != null) {
chain.doFilter(request, response);
return;
} name = (String)req.getSession().getAttribute("username");
if(name != null){
chain.doFilter(request, response);
}else{
req.setAttribute("msg", "您不是管理员也不是会员!");
req.getRequestDispatcher("/login.jsp").forward(request, response);
} } public void destroy() {
} }
web.xml中的配置
<filter>
<display-name>UserFilter</display-name>
<filter-name>UserFilter</filter-name>
<filter-class>cn.zy.filter.UserFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UserFilter</filter-name>
<url-pattern>/users/*</url-pattern>
</filter-mapping>
<filter>
<display-name>AdminFilter</display-name>
<filter-name>AdminFilter</filter-name>
<filter-class>cn.zy.filter.AdminFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdminFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
四、 response增强案例——缓存数据到内存
对于页面中很少更新的数据,例如商品分类,为避免每次都要从数据库查询分类数据,因此可把分类数据缓存在内存或文件中,以此来减轻数据库压力,提高系统响应速度。
编写缓存数据的过滤器,代码如下:
package cn.zy.filter; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper; public class WebResourceCachedFilter implements Filter {
/**
* @Field: map
* 缓存Web资源的Map容器
*/
private Map<String,byte[]> map = new HashMap<String,byte[]>(); public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
response.setCharacterEncoding("utf-8");
//1.得到用户请求的uri
String uri = request.getRequestURI();
//2.看缓存中有没有uri对应的数据
byte b[] = map.get(uri);
//3.如果缓存中有,直接拿缓存的数据打给浏览器,程序返回
if(b!=null){
//根据字节数组和指定的字符编码构建字符串
String webResourceHtmlStr = new String(b,response.getCharacterEncoding());
System.out.println(webResourceHtmlStr);
response.getOutputStream().write(b);
return;
}
//4.如果缓存没有,让目标资源执行,并捕获目标资源的输出
BufferResponse myresponse = new BufferResponse(response);
chain.doFilter(request, myresponse);
//获取缓冲流中的内容的字节数组
byte out[] = myresponse.getBuffer();
//5.把资源的数据以用户请求的uri为关键字保存到缓存中
map.put(uri, out);
//6.把数据打给浏览器
response.getOutputStream().write(out);
} public void destroy() { } class BufferResponse extends HttpServletResponseWrapper{
private ByteArrayOutputStream bout = new ByteArrayOutputStream(); //捕获输出的缓存
private PrintWriter pw;
private HttpServletResponse response;
public BufferResponse(HttpServletResponse response) {
super(response);
this.response = response;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyServletOutputStream(bout);
}
@Override
public PrintWriter getWriter() throws IOException {
pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));
return pw;
} public byte[] getBuffer(){
try{
if(pw!=null){
pw.close();
}
return bout.toByteArray();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
} class MyServletOutputStream extends ServletOutputStream{
private ByteArrayOutputStream bout;
public MyServletOutputStream(ByteArrayOutputStream bout){ //接收数据写到哪里
this.bout = bout;
}
@Override
public void write(int b) throws IOException {
bout.write(b);
}
}
}
在web.xml中配置Web资源缓存过滤器
<filter>
<description>Web资源缓存过滤器</description>
<filter-name>WebResourceCachedFilter</filter-name>
<filter-class>cn.zy.filter.WebResourceCachedFilter</filter-class>
</filter> <filter-mapping>
<filter-name>WebResourceCachedFilter</filter-name>
<!-- 映射需要缓存输出的JSP页面,这几个页面都只是单纯作为输入UI,不会有太多的变化,因此可以缓存输出 -->
<url-pattern>/login.jsp</url-pattern>
<url-pattern>/test.jsp</url-pattern>
<url-pattern>/test2.jsp</url-pattern>
</filter-mapping>
JavaWeb学习总结(十五)--过滤器的应用的更多相关文章
- javaweb学习总结(十五)——JSP基础语法
任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依然有其自己扩充的语法,而且在JSP中,所有的JAVA语句都可以使用. 一.JSP模版元素 JSP页面中的HTML内容称之 ...
- javaweb学习总结十五(web开发的相关概念以及常用服务器介绍)
一:java web开发的相关概念 1:web分为静态web和动态web 2:模拟web服务器 web页面如果想让外部网络访问,必须通过网络程序读取资源,流程: a:用户通过浏览器访问网络程序 b:网 ...
- JavaWeb学习 (二十五)————监听器(Listener)
一.监听器介绍 1.1.监听器的概念
- javaweb学习总结(十五)——JSP基础语法(转)
任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依然有其自己扩充的语法,而且在JSP中,所有的JAVA语句都可以使用. 一.JSP模版元素 JSP页面中的HTML内容称之 ...
- python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...
- 201671010140. 2016-2017-2 《Java程序设计》java学习第十五周
java学习第十五周 Java的GUI界面设计,框架以及主要部件填充,归置,布局管理,在第十一章和第十二章进行了系统的学习,在这两章的知识奠基下,可以简单的构造一个GUI用户界面,在两周的学习后,可以 ...
- 学习笔记:CentOS7学习之十五: RAID磁盘阵列的原理与搭建
目录 学习笔记:CentOS7学习之十五: RAID磁盘阵列的原理与搭建 14.1 RAID概念 14.1.1 RAID几种常见的类型 14.1.2 RAID-0工作原理 14.1.3 RAID-1工 ...
- 风炫安全WEB安全学习第二十五节课 利用XSS键盘记录
风炫安全WEB安全学习第二十五节课 利用XSS键盘记录 XSS键盘记录 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源.所以xyz.com下的js脚本采用a ...
- (C/C++学习笔记) 十五. 构造数据类型
十五. 构造数据类型 ● 构造数据类型概念 Structured data types 构造数据类型 结构体(structure), 联合体/共用体 (union), 枚举类型(enumeration ...
- JavaWeb学习 (二十四)————Filter(过滤器)常见应用
一.统一全站字符编码 通过配置参数charset指明使用何种字符编码,以处理Html Form请求参数的中文问题 1 package me.gacl.web.filter; 2 3 import ja ...
随机推荐
- Python基础第一篇
一.第一句python代码 1.python执行过程:1.加载内存-词法分析-语法分析-编译-执行 2.创建hello.py文件,输入内容 #!/usr/bin/env python print &q ...
- StringUtils 帮助类所涉及的方法
/*1.字符串以prefix开始*/StringUtils.startsWith("sssdf","");//结果是:trueStringUtils.start ...
- python 购物车和三级菜单
程序:购物车程序 需求: 启动程序后,让用户输入工资,然后打印商品列表 允许用户根据商品编号购买商品 用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒 可随时退出,退出时,打印已购买商品和余额 ...
- Poj(3687),拓扑排序,
题目链接:http://poj.org/problem?id=3687 题意:n个重量为1~n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小.(先保证1号 ...
- 谈EXPORT_SYMBOL使用
EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static 函数和变量都会自动导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的.2.6就必须用EXPO ...
- C#中的字符串处理——找出最长数字子串
百度测试部2015年10月份的面试题之——字符串处理,找出最长的子串. 代码如下: private static string SelectNumberFromString(string input) ...
- request、response 中文乱码问题与解决方式
request乱码指的是:浏览器向服务器发送的请求参数中包含中文字符,服务器获取到的请求参数的值是乱码: response乱码指的是:服务器向浏览器发送的数据包含中文字符,浏览器中显示的是乱码: ...
- CentOS 配置solr中文分词器
第一步:使用IK-Analyzer.把分析器的文件夹上传到服务器. 第二步:需要把分析器的jar包添加到solr工程中. [root@bogon IK Analyzer 2012FF_hf1]# cp ...
- C++中的const详解
const的用法,特别是用在函数后面 在普通的非 const成员函数中,this的类型是一个指向类类型的 const指针.可以改变this所指向的值,但不能改变 this所保存的地址. 在 const ...
- 2016年11月18日 星期五 --出埃及记 Exodus 20:9
2016年11月18日 星期五 --出埃及记 Exodus 20:9 Six days you shall labor and do all your work,六日要劳碌作你一切的工,