如果不能简单的把事情说清楚,说明你还没有完全明白。
Filter我们一般用于做字符编码
,登录拦截
,跨域请求
,压缩处理
。
登录拦截
如果用户知道了页面的url,通过直接在浏览器上输入url,跳过了登录。我们需要对其非法操作进行拦截,如果不用过滤器的话,需要在每个页面在上判断,session里面的用户是否为Null,有了过滤器Filter我们可以为其加上个登录拦截的过滤器。
<form action="" id="Myform">
<input name="username" placeholder="用户名" required="" type="text" value="<%=uname%>"
/>
<hr class="hr15">
<input name="password" placeholder="密码" required="" type="password" value="<%=password%>"
<input value="登录" style="width:100%;" type="submit" id="btn_login">
/>
当我们在登录的时候,会在serlvlet上为用户设置在session保存信息
session.setAttribute("user_name", username);
下面开始编辑我们的登录拦截器filter
首先,配置xml文件,拦截所有的url :/*
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这里设置拦截的地址是/* 则文件访问的.js .css .jsp .do 等都会被拦截,即访问一个jsp界面,可能会被拦截很多次。所以应该做如下修改:只拦截.jsp 和.do
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>filter.LoginFilter</filter-class>
<init-param>
<param-name>login</param-name>
<param-value>login.jsp</param-value>
</init-param>
<init-param>
<param-name>LoginServlet</param-name>
<param-value>LoginServlet</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
下面是同步拦截,Filter的写法:
public class LoginFilter implements Filter {
//不拦截的登录界面jsp 与不拦截的执行登录的servlet
String login="";
String servlet="";
/**
* Default constructor.
*/
public LoginFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
// pass the request along the filter chain
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
String contextUrl = req.getRequestURI();
if(contextUrl.indexOf(login)>-1||contextUrl.indexOf(servlet)>-1)
{
chain.doFilter(request, response);
return;
}
HttpSession session = req.getSession();
if(session.getAttribute("user_name")==null){//说明没有登录,或者超时
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<script language='javascript' type='text/javascript'>");
out.println("alert('登录信息失效!请你重新登录!');window.parent.location.href='" + req.getContextPath() + "/login.jsp'");
out.println("</script>");
return;
}
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
login=fConfig.getInitParameter("login");
servlet=fConfig.getInitParameter("LoginServlet");
System.out.println(login+servlet);
}
}
以上,当我们通过同步去请求.jsp和.do都会拦截。但如果我们采用的是ajax,则虽然有拦截到进去,但是并没有什么用。
下面介绍下ajax拦截:
if(session.getAttribute("user_name")==null){//说明没有登录,或者超时
//异步
if (req.getHeader("x-requested-with") != null&& req.getHeader("x-requested-with") .equalsIgnoreCase("XMLHttpRequest")) {
resp.addHeader("sessionstatus", "timeOut"); //这个头是随意加的,键值对。
resp.addHeader("loginPath", "login.jsp");
return ;
}
else //同步
{
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<script language='javascript' type='text/javascript'>");
out.println("alert('登录信息失效!请你重新登录!');window.parent.location.href='" + req.getContextPath() + "/login.jsp'");
out.println("</script>");
return;
}
}
之后,新建个.js文件,在每个需要拦截的.jsp加入.js
$(document).ajaxComplete(function(event, xhr, settings) {
if(xhr.getResponseHeader("sessionstatus")=="timeOut"){
if(xhr.getResponseHeader("loginPath")){
alert("由于你长时间没有操作,导致Session失效!请你重新登录!");
window.parent.location.href="/SaleOnline/"+xhr.getResponseHeader("loginPath");
}else{
alert("由于你长时间没有操作,导致Session失效!请你重新登录!");
}
}
});
于是,我们的拦截 完美成功。
跨域请求
什么是跨域
当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.google.com),那么我们就可以认为它们是相同的域(协议,域名,端口都必须相同)。
跨域就指着协议,域名,端口不一致,出于安全考虑,跨域的资源之间是无法交互的(例如一般情况跨域的JavaScript无法交互,当然有很多解决跨域的方案)
作为java开发,同样需要解决跨域的问题。
思路:设置个拦截器,对需要支持跨域的请求进行拦截,然后在Filter里增加跨域支持。
Filter代码:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); //实际开发需要修改为指定的IP地址
httpServletResponse.setHeader("Access-Control-Allow-Headers", "accept,content-type");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "OPTIONS,GET,POST,DELETE,PUT");
chain.doFilter(httpServletRequest, httpServletResponse);
//chain.doFilter(request, response);
}
压缩处理
压缩处理涉及到文件IO处理,渣渣程序猿对这个文件处理一直都是绕过去的,这里备份下代码留着日后 好 翻笔记。 难受
public class GzipFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
final HttpServletRequest request = (HttpServletRequest) arg0;
final HttpServletResponse response = (HttpServletResponse) arg1;
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
final PrintWriter pw = new PrintWriter(new OutputStreamWriter(bout,"UTF-8"));
chain.doFilter(request, getHttpServletResponseProxy(response, bout, pw));
pw.close();
//拿到目标资源的输出
byte result[] = bout.toByteArray();
System.out.println("原始大小:" + result.length);
ByteArrayOutputStream bout2 = new ByteArrayOutputStream();
GZIPOutputStream gout = new GZIPOutputStream(bout2);
gout.write(result);
gout.close();
//拿到目标资源输出的压缩数据
byte gzip[] = bout2.toByteArray();
System.out.println("压缩大小:" + gzip.length);
response.setHeader("content-encoding", "gzip");
response.setContentLength(gzip.length);
response.getOutputStream().write(gzip);
}
private ServletResponse getHttpServletResponseProxy(
final HttpServletResponse response,
final ByteArrayOutputStream bout,
final PrintWriter pw) {
return (ServletResponse) Proxy.newProxyInstance(GzipFilter.class.getClassLoader(),
response.getClass().getInterfaces(),
new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("getWriter")){
return pw;
}else if(method.getName().equals("getOutputStream")){
return new MyServletOutputStream(bout);
}else{
return method.invoke(response, args);
}
}
});
}
class MyServletOutputStream extends ServletOutputStream{
private ByteArrayOutputStream bout = null;
public MyServletOutputStream(ByteArrayOutputStream bout){
this.bout = bout;
}
@Override
public void write(int b) throws IOException {
bout.write(b);
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setWriteListener(WriteListener arg0) {
// TODO Auto-generated method stub
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
web.xml
网友评论