Petstore源码追踪记(3)-商业逻辑处理(二)

使用者基本数据浏览流程
=======================
现在让我们进入主题- Petstore 商业逻辑,笔者以使用者基本资料浏览流程为例,请激活 cloudscape 数据库:
cloudscape –start

1 激活数据库

接着激活 RI Application Server( 应用服务器 )
j2ee –verbose

2 激活 RI

Petstore
系统激活无误后,请开启浏览器,输入
http://localhost:8080/petstore/index.jsp

3 进入 Petstore 系统

进入系统看到那大大的鹦鹉头,请点选右上角的 ”Account” 连结,
进入使用者登入流程:

4 Petstore 首页

我们会看到登入画面,直接使用预设的使用者 (j2ee) 及密码 (j2ee)
点选 ”Sign In” 钮:

5 登入画面

看到以下显示个人信息画面就表示我们已登入成功啦!


6 个人信息画面

若此时我们按浏览器之 上一页 钮返回首页:


7 再返回首页

再按右上角 ”Account” 连结,会发现画面直接跳至个人信息画面:

8 个人信息画面

    
请注意图 4 Petstore 首页画面左下角出现的

URL:http://localhost:8080/petstore/customer.do
,它其实就是图 6 个人信息画面,但系统并没有直接从图 4 跳至图 6 ,而先换成图 5 登入画面,要求我们做登入动作,输入帐号及密码,验证成功后才跳至图 6 ;若是再次从首页进入个人信息,系统并不会再次要求登入,在这里有两个重点要提:
1.SignOnFilter
:若使用者进入的页面是受到保护的,则系统会先将画面转至登入画面,要求登入。
2.customer.do
:它代表的是一个动作加一个画面的组合,以本例来说,从数据库读取个人信息,组成完整 HTML 画面显示。

SignOnFilter
    
笔者将使用者进入使用者基本资料浏览画面的流程分为三个阶段:
1.
使用者欲进入使用者基本资料浏览画面 (customer.do) ,因未登入过,被 SignOnFilter 拦截,转至登入画面 (signon.screen)
2.
使用者输入帐号及密码按 ”sumit” 后,再度由 SignOnFilter 拦截, SignOnFilter 亦负责帐号、密码检核工作,确认无误后,则将网页转导 (forward) 至第一阶段使用者欲进入之使用者基本资料浏览画面 (customer.do)
3.
重复第一阶段动作, SignOnFilter 检查使用者已登入过,放行转导至使用者基本资料浏览画面 (customer.do)

第一阶段
欲观察 Servlet Filter ,先要了解它的影响范围,请开启 deploytool( 2) ,鼠标点选 PetstoreWAR ,选择右边 Filter Mapping 页,会发现此 Filter 的影响范围是所有网页。

9 Filter 影响范围

也可在 web.xml 看到设定,请参考前面叙述,接下来请开启 SignOnFilter.java
,它的源码位置在
Petstore_home/src/components/signon/src/com/sun/j2ee/blueprints/signon/web/SignOnFilter.java

先看 SignOnFilter 初始动作,约在 87 列:
public void init(FilterConfig config) throws ServletException {
    this.config = config;
    URL protectedResourcesURL = null;
    try {
       //
謮取 signon-config.xml
       protectedResourcesURL =
config.getServletContext().getResource("/WEB-INF/signon-config.xml");
       SignOnDAO dao = new SignOnDAO(protectedResourcesURL);
       //
读取登入失败画面 (signon_error.screen)
       signOnErrorPage = dao.getSignOnErrorPage();
       //
读取登入画面 (signon.screen)
       signOnPage = dao.getSignOnPage();
       //
读取所有欲保护画面,组成 HashMap
       protectedResources = dao.getProtectedResources();
    } catch (java.net.MalformedURLException ex) {
            System.err.println("SignonFilter: malformed URL exception: " + ex);
    }
}

它在初始化时会先读取
Petstore_home/src/apps/petstore/src/docroot/WEB-INF/signon-config.xml
,并组成 Data Access Object(DAO) ,以方便后续程序存取 ( 3) ,此 xml 档案主
要功用记录登入画面、登入失败画面及所有需登入才能使用的画面之 URL ,以下是 signon-config.xml 片段:
<signon-config>

<!-- Form Sign On Page(
登入画面 )-->
<signon-form-login-page>
  signon.screen
</signon-form-login-page>
<!-- Error Page When Sign On fails(
登入失败画面 )-->
<signon-form-error-page>
  signon_error.screen
</signon-form-error-page>

<!-- A Protected Resource-->
<security-constraint>
   <web-resource-collection>
    <web-resource-name>Customer Screen</web-resource-name>
    <url-pattern>customer.screen</url-pattern>
   </web-resource-collection>
</security-constraint>

<!-- A Protected Resource(
本例之保护画面 )-->
<security-constraint>
   <web-resource-collection>
    <web-resource-name>Customer Action</web-resource-name>
    <url-pattern>customer.do</url-pattern>
   </web-resource-collection>
</security-constraint>

接着请看 SignOnFilter 实际运作的主要函式 doFilter() ,约在 107 列:

public  void doFilter(ServletRequest request, ServletResponse  response,
FilterChain chain)  throws IOException, ServletException {
    HttpServletRequest hreq = (HttpServletRequest)request;
    String currentURI = hreq.getRequestURL().toString();
    String currentURL = hreq.getRequestURI();
    // get everything after the context root
    int firstSlash = currentURL.indexOf("/",1); // jump past the starting slash
    String targetURL = null;
    //
取得使用者欲前往之 URL ,以本例来说,即是 customer.do
    if (firstSlash != -1) targetURL = currentURL.substring(firstSlash + 1,
currentURL.length());
    //
判断使用者从登入画面 (signon.screen) 进行验证工作
   
    if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) {
       validateSignOn(request, response, chain);
       // jump out of this method
       return;
    }

    // check if the user is signed on
    //
检查使用者是否登入过,从 Session 取出登入标记,作为判断之用
    boolean signedOn = false;
    if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
       signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
    } else {
       hreq.getSession().setAttribute(SIGNED_ON_USER, new Boolean(false));
    }
       // jump to the resource if signed on
       //
若已登入过,则结束此 Filter 工作,进入 Filter chain ,以本例来说,它为 Filter chain 中最后一个 Filter ,所以就是不做任何事,让使用者进入他的目的画面
       if (signedOn) {
           chain.doFilter(request,response);
           return;
       }
       // find out if the patterns match the target URL
       //
将使用者欲前往之 URL 与所有保护画面 URL 做比对,若符合则导入登入画面
(signon.screen)
       Iterator it = protectedResources.keySet().iterator();
       while (it.hasNext()) {
           String protectedName = (String)it.next();
           ProtectedResource resource  =
(ProtectedResource)protectedResources.get(protectedName);
           String urlPattern = resource.getURLPattern();

           // now check agains the targetURL
           //
若符合则将目的 URL 存入 Session ,并转导至登入画面,结束 Filter 工作
           if (urlPattern.equals(targetURL)) {
             // put the orginal url in the session so others can access
             hreq.getSession().setAttribute(ORIGINAL_URL,  targetURL);
             config.getServletContext().getRequestDispatcher("/" +
signOnPage).forward(request, response);
             // Jump out of the filter and go to the next page
             return;
           }
       }
       // No matches if we made it to here
       chain.doFilter(request,response);
}

SignOnFilter
先取得使用者的目的 URL(customer.do) ,判断使用者并未登入,开始比对目的 URL 是否在保护画面中,发现 customer.do 为保护画面,将 customer.do 此目的 URL 存入 Session ,将 request 转导至登入画面 (signon.screen) ,要求使用者进行登入动作。


第一阶段验证
口说无凭,我们可加入侦察程序代码来验证程序是否如笔者所述般运行,
请在SignOnFilter.init()加入两行程序:
public void init(FilterConfig config) throws ServletException {
    this.config = config;
    URL protectedResourcesURL = null;
    try {
       //
謮取signon-config.xml
       protectedResourcesURL =
config.getServletContext().getResource("/WEB-INF/signon-config.xml");
       SignOnDAO dao = new SignOnDAO(protectedResourcesURL);
       //
读取登入失败画面(signon_error.screen)
       signOnErrorPage = dao.getSignOnErrorPage();
       //
读取登入画面(signon.screen)
       signOnPage = dao.getSignOnPage();
       //
请加入侦察程序代码
    System.out.println("signOnPage="+signOnPage);
    System.out.println("signErrorPage="+signOnErrorPage);
       //
读取所有欲保护画面,组成HashMap
       protectedResources = dao.getProtectedResources();
    } catch (java.net.MalformedURLException ex) {
            System.err.println("SignonFilter: malformed URL exception: " + ex);
    }
}

doFilter()
亦加入侦察程序代码:

public  void doFilter(ServletRequest request, ServletResponse  response,
FilterChain chain)  throws IOException, ServletException {
    HttpServletRequest hreq = (HttpServletRequest)request;
    String currentURI = hreq.getRequestURL().toString();
    String currentURL = hreq.getRequestURI();
    // get everything after the context root
    int firstSlash = currentURL.indexOf("/",1); // jump past the starting slash
    String targetURL = null;
    //
取得使用者欲前往之URL,以本例来说,即是customer.do
    if (firstSlash != -1) targetURL = currentURL.substring(firstSlash + 1,
currentURL.length());
  //请加入侦察程序代码
  System.out.println("targetURL="+targetURL);
    //
判断使用者从登入画面(signon.screen)进行验证工作
    if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) {
       validateSignOn(request, response, chain);
       // jump out of this method
       return;
    }

    // check if the user is signed on
    //
检查使用者是否登入过,从Session取出登入标记,作为判断之用
    boolean signedOn = false;
    if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
       signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
    } else {
       hreq.getSession().setAttribute(SIGNED_ON_USER, new Boolean(false));
    }
       // jump to the resource if signed on
       //
若已登入过,则结束此Filter工作,进入Filter chain,以本例来说,它为
Filter chain
中最后一个Filter,所以就是不做任何事,让使用者进入他的目的画面
       if (signedOn) {
           chain.doFilter(request,response);
           return;
       }
       // find out if the patterns match the target URL
       //
将使用者欲前往之URL与所有保护画面URL做比对,若符合则导入登入画面
(signon.screen)
       Iterator it = protectedResources.keySet().iterator();
       while (it.hasNext()) {
           String protectedName = (String)it.next();
           ProtectedResource resource  =
(ProtectedResource)protectedResources.get(protectedName);
           String urlPattern = resource.getURLPattern();

           // now check agains the targetURL
           //
若符合则将目的URL存入Session,并转导至登入画面,结束Filter工作
           if (urlPattern.equals(targetURL)) {
       //请加入侦察程序代码
       System.out.println("URL Matched! urlPattern="+urlPattern);
             // put the orginal url in the session so others can access
             hreq.getSession().setAttribute(ORIGINAL_URL,  targetURL);
             config.getServletContext().getRequestDispatcher("/" +
signOnPage).forward(request, response);
             // Jump out of the filter and go to the next page
             return;
           }
       }
       // No matches if we made it to here
       chain.doFilter(request,response);
}

接着请重新编译及部署新的程序代码,在命令模式下:切换至Petstore_home/ src/webservices/apps/petstore/src目录如:cd D:/petstore1.3.1/src/webservices/apps/petstore/src

重新编译程序
如:build all


  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值