友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
第三电子书 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

JSP入门教程(DOC格式)-第10部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!


Model (模型)就值得ContactDao 和数据库了,它提供我们需要的各种数据信息。 

几个 jsp 构成了 View (视图)这一层,用来显示结果数据。  



完整的例子在 lingo…sample/06…02 下,对应的源代码在 WEB…INF/src 下,将 

06…02 复制到 tomcat 的webapps 下就可以执行 pile。bat 进行编译。  



                                     67 / 148  


…………………………………………………………Page 68……………………………………………………………

                                       



               第 7 章 使用 filter 过滤请求  



注意  



Filter 虽然很常用,但是覆盖的范围太广,这里我们只介绍设置编码和控制权 

限的过滤器,其他的使用方式还需要大家自行积累。  



如果你不满足以下任一条件,请继续阅读,否则请跳过此后的部分,进入下一章: 

第 8 章 配置 listener监听器。  



   1。  了解Filter 的使用。  



7。1。 批量设置请求编码  



编码问题会不会成为中国人学 java 的标志呢?  



通过之前的讨论第 2。2。2 节  “POST 乱码”,我们知道为了避免提交数据的乱 

码问题,需要在每次使用请求之前设置编码格式。在你复制粘贴了无数次 

request。setCharacterEncoding(〃gb2312〃);后,有没有想要一劳永逸的方法 

呢?能不能一次性修改所有请求的编码呢?  



用 Filter 吧,它的名字是过滤器,可以批量拦截修改 servlet 的请求和响应。  



我们编写一个 EncodingFilter。java,来批量设置请求编码。  



package anni;  

  

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 EncodingFilter implements Filter {  

  

    public void init(FilterConfig config) throws ServletException {}  

  

    public void destroy() {}  

  

    public void doFilter(ServletRequest request;  



                                   68 / 148  


…………………………………………………………Page 69……………………………………………………………

                                       



            ServletResponse response;  

            FilterChain chain)  

            throws IOException; ServletException {  

  

        request。setCharacterEncoding(〃gb2312〃);  

        chain。doFilter(request; response);  

    }  

  

}   



在此 EncodingFilter 实现了 Filter 接口,Filter 接口中定义的三个方法都要 

在 EncodingFilter 中实现,其中 doFilter()的代码实现主要的功能:为请求设 

置 gb2312 编码并执行 chain。doFilter()继续下面的操作。  



与 servlet 相似,为了让 filter 发挥作用还需要在 web。xml 进行配置。  



  

    EncodingFilter  

    anni。EncodingFilter  

  

  

  

    EncodingFilter  

    /*  

  



filter 标签部分定义使用的过滤器,filter…mapping 标签告诉服务器把哪些请 

求交给过滤器处理。这里的/*表示所有请求,/表示根路径,* (星号)代表所有 

请求,加在一起就变成了根路径下的所有请求。  



这样,所有的请求都会先被EncodingFilter 拦截,并在请求里设置上指定的 

gb2312 编码。  



例子在 lingo…sample/07…01 目录下,这次我们不需要在test。jsp 中为请求设置 

编码也可以得到正常的中文参数了,EncodingFilter 圆满的完成了它的工作。  



7。2。 用 filter 控制用户访问权限  



出于信息安全和其他一些原因的考虑,项目中的一些页面要求用户满足了一定条 

件之后才能访问。比如,让用户输入帐号和密码,如果输入的信息正确就在 

session 里做一个成功登录的标记,其后在请求保密信息的时候判断 session 中 

是否有已经登录成功的标记,存在则可以访问,不存在则禁止访问。  



                                    69 / 148  


…………………………………………………………Page 70……………………………………………………………

                                                           



如 07…02 例子中所示,进入首页看到的就是登录页面。  



                                                                                         



现在用户还没有登录,如果直接访问保密信息,就会显示无法访问保密信息的页 

面,并提醒用户进行注册。  



                                                                                           



返回登录页面后,输入正确的用户名和密码,点击登录。  



                                                                                           



后台程序判断用户名和密码正确无误后,在 session 中设置已登录的标记,然后 

跳转到保密信息页面。  



                                                      70 / 148  


…………………………………………………………Page 71……………………………………………………………

                                             



                                                                       



我们要保护的页面是 admin/index。jsp,为此我们在web。xml 进行如下配置。  



  

    SecurityFilter  

    anni。SecurityFilter  

  

  

    SecurityFilter  

    /admin/*  

    



定义 SecurityFilter 过滤器,让它过滤匹配/admin/*的所有请求,这就是说, 

对/admin/路径下的所有请求都会接受 SecurityFilter 的检查,那么 

SecurityFilter 里到底做了些什么呢?  



public void doFilter(ServletRequest request;  

        ServletResponse response;  

        FilterChain chain)  

        throws IOException; ServletException {  

  

    HttpServletRequest req = (HttpServletRequest) request;  

    HttpServletResponse res = (HttpServletResponse) response;  

  

    HttpSession session = req。getSession();  

    if  (session。getAttribute(〃username〃) != null) {  

        chain。doFilter(request; response);  

    } else  {  

        res。sendRedirect(〃。。/failure。jsp〃);  

    }  

}    



首先要将 ServletRequest 和 ServletResponse 转换成 HttpServletRequest 和 

HttpServletResponse,因为Filter 本来设计成为多种协议服务,http 协议仅 

仅是其中一部分。不过我们接触到的也只有 http,而且也只有转换成对应 



                                         71 / 148  


…………………………………………………………Page 72……………………………………………………………

                                   



HttpServletRequest 和 HttpServletResponse 才能进行下面的 session 操作和 

页面重定向。  



得到了 http 请求之后,可以获得请求对应的 session,判断 session 中的 

username 变量是否为 null,如果不为 null,说明用户已经登录,就可以调用 

doFilter 继续请求访问的资源。如果为 null,说明用户还没有登录,禁止用户 

访问,并使用页面重定向跳转到 failure。jsp 页面显示提示信息。  



session 中的username 实在登录的时候设置进去的,值就是登录用户使用的用 

户名,详细代码可以参考 07…02/WEB…INF/src/LoginServlet。java,登录和注销 

都写成了 servlet 并映射到/login。do 和/logout。do 这两个请求路径上。源代码 

和 web。xml 配置请自行参考 07…02 中的例子,这里就不复述了。  



我们再来看看页面重定向的写法,res。sendRedirect()中使用的是 

〃。。/failure。jsp〃,两个点(。。)代表当前路径的上一级路径,这是因为 

SecurityFilter 负责处理的是/admin/下的请求,而/failure。jsp 的位置在 

/admin/ 目录的上一级,所以加上两个点才能正确跳转到failure。jsp。当然这 

里使用 forward()也可以,但是要注意在不同路径下做请求转发会影响页面中相 

对路径的指向。相关讨论在:第 3。4。2 节  “forward 导致找不到图片”。  



7。3。 filter 所谓的特性  



7。3。1。 请求映射  



filter…mapping 和 servlet…mapping 都是将对应的 filter 或 servlet 映射到某 

个 url…pattern 上,当客户发起某一请求时,服务器先将此请求与 web。xml 中定 

义的所有 url…pattern 进行匹配,然后执行匹配通过的 filter 和 servlet。  



你可以使用三种方式定义 url…pattern。  



   1。  直接映射一个请求。  



        

          ContactServlet  

          /contact。do  

        



      像第 6。3 节  “使用servlet 改写联系簿”中对 servlet 的映射,只有当 

      请求是/contact。do 的时候才会执行ContactServlet。/contact。do?id=1 

      或/contact。do?method=list&id=1 的请求也可以匹配到 

      ContactServlet,这是因为根据http 规范,请求的路径不包含问号以后 

      的部分。  



                                72 / 148  


…………………………………………………………Page 73……………………………………………………………

                                      



2。  映射一个路径下的所有请求。  



     

       EncodingFilter  

       /*  

      



   像第 7。1 节  “批量设置请求编码”中这样使用星号(*)的形式,可以 

   将某个路径下的所有请求都映射到 EncodingFilter 过滤器下,如果这个 

   路径下还有子路径,那么子路径下的请求也会被 EncodingFilter 过滤。 

   所以 /*这种写法就会过滤应用下所有的请求。  



   如果像第 7。2 节  “用filter 控制用户访问权限”中那样把映射配置成 

   /admin/*,就会只处理/admin/路径下的请求,不会处理根路径下的 

   /index。jsp 和/failure。jsp。  



   需要注意的是,这种写法必须以/开头,写成与绝对路径的形式,即便是 

    映射所有请求也要写成/*,不能简化成*。  



3。  映射结尾相同的一类请求。  



     

       ControllerServlet  

       *。do  

      



   具体效果请参考 07…03 的例子,index。jsp 中有四个链接,分别指向/a1。do;  

   /a2。do; /xx/b1。do; /xx/yy/c1。do。  



                                                                



   web。xml 中的ControllerServlet 会接收以。do 结尾的请求,并使用 

   forward 将请求转发到/test。jsp。  



   点击/a1。do 的情况。  



                                  73 / 148  


…………………………………………………………Page 74……………………………………………………………

                                            



                                                                        



       点击/xx/yy/c1。do 的情况。  



                                                                        



       这样做的一个好处是语义更清楚,只要看到以。do 结尾的请求就知道肯定 

       是交给 ControllerServlet 处理了,不管这个请求是在根路径还是子路径 

       下,都会准确无误的找到对应的 servlet。  



       缺点就是不同路径之间进行 forward,jsp 里就不能再使用相对路径了, 

       所以我们在 test。jsp 中使用request。getContextPath()获得当前应用在 

       服务器中的位置(例子中是/07…03)将相对路径都组装成绝对路径,这种 

       用法在以后也会经常用到。  



         

       返回    



       最后需要注意的是,这种请求映射就不能指定某一路径了,它必须是以星 

       号(*)开始字母结尾,不能写成/*。do 的形式。  



现在咱们也发现 java 的请求映射有多傻了,灵活配置根本是不可能的任务。  



想要获得所有以 user 开头。do 结尾的请求吗?user*。do 在 url…pattern 是无法 

识别的,只能配置成*。do,再去 servlet 中对请求进行筛选。  



想要让一个 servlet 负责多个请求吗?/user/*;/admin/*;*。do 写在一起 

url…pattern 也不认识,只能配成多个 servlet…mapping。  



  



                                        74 / 148  


…………………………………………………………Page 75……………………………………………………………

                                          



    ControllerServlet  

    /user/*  
返回目录 上一页 下一页 回到顶部 0 0
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!