JavaWeb过滤器——案例(一)

案例1:分IP统计网站的访问次数

分析

统计不同的IP访问网站的次数,需要在所有资源中执行,这个工作可以放在Filter中。

使用Map<String,Integer>来装载统计数据,整个网站只需要一个map,并存放在ServletContext中。

  • Map在监听器中创建(使用监听器:ServletContextListener,在服务器启动时创建,并存储到ServletContext中)
  • Ip统计工作在Filter中完成:获取的ip如果存在Map中,就将对应的map值加一,否则添加该ip,并将值设置成1。

 

实例代码

监听器:AListener.java

public class AListener implements ServletContextListener{


    /**
     * 启动服务创建ServletContext时启动
     * 只调用一次
     * @param servletContextEvent
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //创建map用来存放访问统计结果
        Map<String,Integer>map=new HashMap<>();
        //获得servletcontext对象,并将map存入
        ServletContext application=servletContextEvent.getServletContext();
        application.setAttribute("map",map);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

过滤器:AFilter.java

@WebFilter(filterName = "AFilter",urlPatterns = "/*")
public class AFilter implements Filter {
    private FilterConfig config;
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        //获得servletContext域中的map
        ServletContext application=config.getServletContext();
        Map<String,Integer> map= (Map<String, Integer>) application.getAttribute("map");

        //获取访问ip
        String ip=req.getRemoteAddr();

        /**
         * 判断map中是否含有该ip
         * 如果有 值再加一
         * 如果没有,值设置成1
         */
        if (map.containsKey(ip)) {
            int count = map.get(ip);
            map.put(ip,count+1);
        }else{
            map.put(ip,1);
        }

        //将map存入application
        application.setAttribute("map",map);

        //放行
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

        this.config=config;
    }

}

显示结果界面:show.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>显示</title>
</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>
            <th>${entry.key}</th>
            <th>${entry.value}</th>
        </tr>
    </c:forEach>
</table>


</body>
</html>

效果

 

案例2 粗粒度权限控制(根据用户名登陆)

RBAC(Role-Based policies Access Control) -> 基于角色的权限控制:例如不同用户的权限不同,可以查看的资源不同。对资操作的权限也不同:增删改查等等。

我们这个案例只是简单的根据登陆名来拦截。

说明:

我们给出三个页面:index.jsp、user.jsp、admin.jsp。

  1. index.jsp:谁都可以访问,没有限制;
  2. u.jsp:只有登录用户(包含管理员)才能访问,否则返回登陆界面;
  3. a.jsp:只有管理员才能访问,否则返回登陆界面;
  4. login.jsp:登陆界面。

分析:

用户访问登陆界面后,只需要输入登录名,包含user为用户,包含admin为管理员,登陆名保存到session中

AdminFilter拦截a.jsp请求,判断当前请求是否为管理员

UserFilter拦截u.jsp,判断当前请求是否为用户

 

代码实例

登陆界面login.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆</title>
</head>
<body>
${msg}
<form action="<c:url value="/LoginServlet"/>" method="post">
    用户名:<input type="text" name="username"/>
    <input type="submit" value="登陆"/>
</form>
</body>
</html>

index.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>主页</title>
  </head>
  <body>
  游客您好,欢迎访问!<br/>
  <a href="<c:url value='/index.jsp'/>">游客页面</a><br/>
  <a href="<c:url value='/admin/a.jsp'/>">管理员页面</a><br/>
  <a href="<c:url value='/user/u.jsp'/>">用户页面</a><br/>
  </body>
</html>

a.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>管理您好!</h1><br/>
<a href="<c:url value='/index.jsp'/>">游客页面</a><br/>
<a href="<c:url value='/admin/a.jsp'/>">管理员页面</a><br/>
<a href="<c:url value='/user/u.jsp'/>">用户页面</a><br/>
</body>
</html>

u.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>管理员</title>
</head>
<body>

<h1>用户您好!</h1><br/>
<a href="<c:url value='/index.jsp'/>">游客页面</a><br/>
<a href="<c:url value='/admin/a.jsp'/>">管理员页面</a><br/>
<a href="<c:url value='/user/u.jsp'/>">用户页面</a><br/>

</body>
</html>

LoginServlet.java

@WebServlet(name = "LoginServlet",urlPatterns = "/LoginServlet")
public class LoginServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String username=request.getParameter("username");

        if(username.contains("admin")){//用户名中包含admin,进入管理员页面
            //保存管理员账号到session中
            request.getSession().setAttribute("admin",username);
        }else{//进入用户页面
            //保存用户账号到session中
            request.getSession().setAttribute("user",username);
        }
        request.getRequestDispatcher("/index.jsp").forward(request,response);
    }

}

AdminFilter.java

public class AdminFilter implements Filter {
    public void destroy() {
    }


    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        //将ServletRequest对象强转成HttpServletRequest
        HttpServletRequest request= (HttpServletRequest) req;

        //获得session对象
        HttpSession session=request.getSession();
        String username1= (String) session.getAttribute("admin");
        if (username1 == null) {
            session.setAttribute("msg","你不是管理员!");
            request.getRequestDispatcher("/login.jsp").forward(req,resp);
        }else{
            chain.doFilter(req, resp);
        }

    }

    public void init(FilterConfig config) throws ServletException {

    }

}

UserFilter.java

public class UserFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws ServletException, IOException {

        //将ServletRequest对象强转成HttpServletRequest
        HttpServletRequest request= (HttpServletRequest) req;

        //获得session对象
        HttpSession session=request.getSession();
        String username1= (String) session.getAttribute("admin");
        String username2= (String) session.getAttribute("user");
        if (username1!=null||username2!=null) {
            chain.doFilter(req, resp);
        }else{
            session.setAttribute("msg","你是游客,不能访问用户界面!");
            request.getRequestDispatcher("/login.jsp").forward(req,resp);
        }


    }

    public void init(FilterConfig config) throws ServletException {

    }

}

 

案例4、解决全站字符乱码(POST和GET中文乱码问题)

在servlet中解决乱码问题方式:

  • POST:request.setCharacterEncoding("utf-8");
  • GET:String username = request.getParameter(“username”); username = new String(username.getBytes(“ISO-8859-1”), “utf-8”);

分析:

在过滤器中解决POST乱码很简单,只需要添加request.setCharacterEncoding("utf-8");

但是对于GET乱码就很麻烦,我们不可能一一去处理每个中文参数。这里可以使用装饰者模式参考:设计模式—装饰者模式

在过滤器中将request对象进行调包

  • 写一个request装饰类:增强getParameter方法,对get请求进行编码处理
  • 放行时传递我们自己的request对象

 

说明:

encoding.jsp页面包含get请求链接和post请求链接,都向服务器发送中文。

encodingServlet.java取出中文,显示在客户端

 

代码实现

encoding.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>编码显示</title>
</head>
<body>

<a href="<c:url value='/EncodingServlet?username=张三'/>">点击这里</a><br/>

<form action="<c:url value='/EncodingServlet'/>">
    <input type="text" name="username" value="李四"/>
    <input type="submit" value="点击"/><br/>
</form>
</body>
</html>

encodingServlet.java

@WebServlet(name = "EncodingServlet",urlPatterns = "/EncodingServlet")
public class EncodingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //设置相应编码处理
        response.setContentType("text/html;charset=utf-8");
        String username=request.getParameter("username");
        response.getWriter().println(username);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //设置相应编码处理
        response.setContentType("text/html;charset=utf-8");
        String username=request.getParameter("username");
        response.getWriter().println(username);
    }
}

EncodingReqest.java

/**
 * HttpServletRequestWrapper 类实现了HttpServletRequest接口,把我们把所有的方法都处理了依靠底层对象
 */
public class EncodingRequest extends HttpServletRequestWrapper {
    private String charset;
    //创建底层依赖对象
    private HttpServletRequest request;

    public EncodingRequest(HttpServletRequest request,String charset){
        super(request);
        this.request=request;
        this.charset=charset;
    }

    /**
     * 在这个对每个参数进行GET编码处理
     * @param name
     * @return
     */
    @Override
    public String getParameter(String name) {

        // 获取参数
        String value = request.getParameter(name);
        if(value == null) return null;//如果为null,直接返回null
        try {
            // 对参数进行编码处理后返回
            return new String(value.getBytes("ISO-8859-1"), charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }



    @Override
    public Map getParameterMap() {
        Map<String,String[]> map = request.getParameterMap();
        if(map == null) return map;
        // 遍历map,对每个值进行编码处理
        for(String key : map.keySet()) {
            String[] values = map.get(key);
            for(int i = 0; i < values.length; i++) {
                try {
                    values[i] = new String(values[i].getBytes("ISO-8859-1"), charset);
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        // 处理后返回
        return map;
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        for(int i = 0; i < values.length; i++) {
            try {
                values[i] = new String(values[i].getBytes("ISO-8859-1"), charset);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
        return values;
    }
}

EncodingFilter.java

/**
 * 全站乱码处理
 */
public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //处理POST请求编码
        req.setCharacterEncoding("utf-8");

        HttpServletRequest request= (HttpServletRequest) req;
        if (request.getMethod().equalsIgnoreCase("post")) {
            //直接放行
            chain.doFilter(req, resp);
        }else if(request.getMethod().equalsIgnoreCase("get")){
            //如果是get请求,使用我们自定义的EncodingRequest来处理编码
            EncodingRequest er=new EncodingRequest(request);
            chain.doFilter(er,resp);
        }

    }

    public void init(FilterConfig config) throws ServletException {

    }

}

案例源码(csdn)

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值