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

Petstore 源码记纵记 (3) -商业逻辑处理 ( )
                                         
欧宣修
图文并茂版请参考
http://www.javatwo.net/JavaPaper/Petstore-3_business_logic.pdf

接续上期 ...

我们已了解 SignOnFilter Web tier 处理登入工作的步骤,它需要透过 EJB tier 从数据库读取资料进行比对,所以接下来探讨在 EJB tier 的运作情形,从图 14 15 可找出实际对应的 EJB ,从图上面可知此 EJB 的属性是 Local Stateless
Session Bean
,这很少见,大部份的书介绍到 Local Bean 的用法都用在 Entity Bean ,由此可知 Local Bean 的用法亦可用在 Session Bean
     SignOnEJB
,源码在 Petstore_home/src/components/signon/src/com/sun/j2ee/blueprints/signon/ejb/SignOnEJB.java ,请读者顺便加上侦察程序代码:
    
public class SignOnEJB implements SessionBean {

    private static final String USER_HOME_ENV_NAME =
"java:comp/env/ejb/local/User";
    private InitialContext ic = null;
    private UserLocalHome ulh = null;

    public void ejbCreate() throws CreateException {
      try {
        ic = new InitialContext();
        //
取得 UserLocalHome Reference ,它是代表使用者基本资料的 Local Entity Bean
        ulh = (UserLocalHome) ic.lookup(USER_HOME_ENV_NAME);
      } catch (NamingException ne) {
         throw new EJBException("SignOnEJB Got naming exception! " +
ne.getMessage());
      }
    }

    /**
     *
此函数由 SignOnFilter 呼叫,依使用者帐号找出对应的 User 实体
    *(instance) ,然后呼叫 User 实体的密码比对函数- user.matchPassword()
     * business method used to check if a user is allowed to sign on
     */
    public boolean authenticate(String userName, String password) {
     // 请加入侦察程序代码,方便稍候程序验证
System.out.println("SignOnEJB
执行 authenticate() 进行使用者验证
userName="+userName+", password="+password);
        try {
            UserLocal user = ulh.findByPrimaryKey(userName);
            return user.matchPassword(password);
        } catch (FinderException fe) {
            return false; // User not found, so authentication failed.
        }
    }
    
以下略 ...
    

16 SignOnEJB EJB Reference
    
UserEJB
,源码在
Petstore_home/src/components/signon/src/com/sun/j2ee/blueprints/signon/user/ejb/
UserEJB.java
,它是 Local Entity Bean ,对应数据库中实际资料表-
UserEJBTable
在约 88 列可看到 SignOnEJB 所呼叫的函数,请读者顺便加
上侦察程序代码:
    
   
public boolean matchPassword(String password) {
   // 请加入侦察程序代码,方便稍候程序验证
   System.out.println("UserEJB 执行 matchPassword() 进行密码比对 ");
    return password.equals(getPassword());
}
    

17 UserEJB Entity Bean

点选图 17 右下角 ”Deployment Settings” 钮,可见到图 18 画面,
选择左下角 ”Method Implementation Queries” ”Container Methods”
”createRow” ,即可看到图 18 SQL Query

18 UserEJB 对应资料表为 UserEJBTable

由上述所列程序代码及图,读者应该可以了解使用者登入在 EJBz tier 的运作情形,在 UserEJB 也看到一个不一样的用法,就是在 Entity Bean 上使用商业逻辑- matchPassword() 函数,在大部份的 EJB 书籍或文件都告诉我们商业逻辑应该用 Session Bean 去实作,资料则用 Entity Bean 来实作,但在这里密码比较的商业逻辑是非常简单的,只用了一行程序就解决了,所以也不需为了它另外再做一个 Session Bean
也许读者会问为什么不将此函数写在 SignOnEJB ?笔者认为密码比对不只在登入流程上会使用,在使用者基本资料编辑时也可能会用到,所以还是放在 UserEJB 比较适合: )     我们能够知道使用者基本资料是存于 UserEJBTable ,我们要如何知道此资料表所存内容是什么?请参阅注 4

现在请重复第一阶段验证步骤将程序重新编辑及部署,可发现程序如我们所预期般执行!

19 第二阶段程序验证结果

第三阶段
大家还记得在 SignOnFilter validateSignOn() 函数,验证成功会将
SIGNED_ON_USER
变量 ( 对应实际变量为 j_signon) 的值设为真值 (true)

hreq.getSession().setAttribute(SIGNED_ON_USER, new Boolean(true));

当我们再次从首页进入使用者基本资料浏览页,会再度给 SignOnFilter 拦截,从 Session 取出 SIGNED_ON_USER 变量 ( 对应实际变量为 j_signon) ,经判断为真值 (true) SignOnFilter 则会放行转导至使用者基本资料浏览画面 (customer.do) ,读者可参考下列程序代码加入侦察码,在约 125 doFilter() 函数:


    boolean signedOn = false;
    if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
       signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
        //
加入侦察码
System.out.println("signedOn="+signedOn);
    } 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) {
           //
加入侦察码
           System.out.println("
使用者已登入过! ");
           chain.doFilter(request,response);
           return;
       }

参考前面叙述重新编译部署后执行,可得下图预期结果:


20 第三阶段程序验证结果


customer.do

 
到这里相信读者能对 Petstore 登入流程控管有更深入的了解,通过登入流程就到达了使用者基本数据浏览画面 (customer.do) *.do 与前二篇介绍的 *.screen 不同, *.screen 代表的是一个画面,如 main.screen 代表首页,它可由多个 .jsp 所组成; *.do 代表的是一个动作, customer.do 代表对使用者基本资料相关动作,如新增、修改、删除,它会透过 EJB tier 与资料库互动,最后得到的结果也是要展现,运用 *.screen 的机制组成结果画面,所以我们可以这样想象 *.screen 是名词, *.do 是动词,以本例来说,只是读取资料,虽然运用到 *.do ,但并没有任何动作,为了能让读者了解整个架构,还是在此稍事说明。

请开 ?deploytool ,点选左边窗格 Files > Applications > PetstoreEAR > PetstoreWAR > MainServlet ,选择右边 Alias 页,可发现处理 *.do 即是 MainServlet

21 *.do 对应 MainServlet

点选 General 页可找到实际对应类别,源码在
Petstore_home/src/waf/src/controller/com/sun/j2ee/blueprints/waf/controller/web/MainServlet.java
,在约 79 列可找到初始函数:

public void init(ServletConfig config) throws ServletException {
        //
读取预设语系,值为 ”en_US”
        String defaultLocaleString = config.getInitParameter("default_locale");
        defaultLocale = I18nUtil.getLocaleFromString(defaultLocaleString);
        this.context = config.getServletContext();
        String requestMappingsURL = null;
        try {
            //
读取 mapping.xml
            requestMappingsURL =
context.getResource("/WEB-INF/mappings.xml").toString();
        } catch (java.net.MalformedURLException ex) {
            System.err.println("MainServlet: initializing ScreenFlowManager
malformed URL exception: " + ex);
        }
       //
mappings.xml 转成 HashMap 类别并存入 ServletContext
       urlMappings = URLMappingsXmlDAO.loadRequestMappings(requestMappingsURL);
       context.setAttribute(WebKeys.URL_MAPPINGS, urlMappings);
       eventMappings = URLMappingsXmlDAO.loadEventMappings(requestMappingsURL);
       context.setAttribute(WebKeys.EVENT_MAPPINGS, eventMappings);
       //ScreenFlowManager
初始化并存入 ServletContext
       getScreenFlowManager();
       //RequestProcessor
初始化并存入 ServletContext
       getRequestProcessor();
}

22 MainServlet 实际对应类别

MainServlet
在初始化时会读取预设语系及对应设定档 (mapping.xml) ,及初始化 ScreenFlowManager RequestProcessor ,预设语系设定在 MainServlet init. Parameter 页,值为 ”en_US”( 英语系 )

23 MainServlet init. Parameter 设定

对应设定文件位置在
Petstore_home/src/apps/petstore/src/docroot/WEB-INF/mappings.xml
,我们可在约 95 行找到 customer.do 的相关设定

<url-mapping url="customer.do" screen="customer.screen" >
<web-action-class>com.sun.j2ee.blueprints.petstore.controller.web.actions.CustomerHTMLAction</web-action-class>
</url-mapping>

这一段卷标 (tag) 有三个参数:
url:
标示对应动作
web-action-class:
实际执行类别
screen:
结果显示画面

     *.do
的运作机制是 Servlet 接收到 request ,从 mappings.xml 找到对应的 url
RequestProcessor
将对应的 web-action-class 初始化并执行, ScreenFlowManager
将执行结果传回给 *.screen ,再运用本系列前两篇所介绍 *.screen 机制组成实际画面,响应给使用者,大致的流程是这样,实际上更复杂,因牵涉到 Web tier EJB tier 间沟通,但以本例来说, RequestProcessor 对应 web-action-class(CustomerHTMLAction) 并没有做什么事,后续 RequestProcessor 接收到结果显示画面 (customer.screen) ,则进行转导 (forward) 动作。
     mappings.xml
读取后转成 HashMap 类别存入 ServletContext 供所有进入
Petstore
系统的人使用,接着将 ScreenFlowManager RequestProcessor 初始
化并存入 ServletContext


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

打赏
文章很值,打赏犒劳作者一下
相关推荐
<p> <span style="font-size:14px;color:#337FE5;">【为什么学爬虫?】</span> </p> <p> <span style="font-size:14px;">       1、爬虫入手容易,但是深入较难,如何写出高效率的爬虫,如何写出灵活性高可扩展的爬虫都是一项技术活。另外在爬虫过程中,经常容易遇到被反爬虫,比如字体反爬、IP识别、验证码等,如何层层攻克难点拿到想要的数据,这门课程,你都能学到!</span> </p> <p> <span style="font-size:14px;">       2、如果是作为一个其他行业的开发者,比如app开发,web开发,学习爬虫能让你加强对技术的认知,能够开发出更加安全的软件和网站</span> </p> <p> <br /> </p> <span style="font-size:14px;color:#337FE5;">【课程设计】</span> <p class="ql-long-10663260"> <span> </span> </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 一个完整的爬虫程序,无论大小,总体来说可以分成三个步骤,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 网络请求:模拟浏览器的行为从网上抓取数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据解析:将请求下来的数据进行过滤,提取我们想要的数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据存储:将提取到的数据存储到硬盘或者内存中。比如用mysql数据库或者redis等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 那么本课程也是按照这几个步骤循序渐进的进行讲解,带领学生完整的掌握每个步骤的技术。另外,因为爬虫的多样性,在爬取的过程中可能会发生被反爬、效率低下等。因此我们又增加了两个章节用来提高爬虫程序的灵活性,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 爬虫进阶:包括IP代理,多线程爬虫,图形验证码识别、JS加密解密、动态网页爬虫、字体反爬识别等。 </li> <li class="" style="font-size:11pt;color:#494949;"> Scrapy和分布式爬虫:Scrapy框架、Scrapy-redis组件、分布式爬虫等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 通过爬虫进阶的知识点我们能应付大量的反爬网站,而Scrapy框架作为一个专业的爬虫框架,使用他可以快速提高我们编写爬虫程序的效率和速度。另外如果一台机器不能满足你的需求,我们可以用分布式爬虫让多台机器帮助你快速爬取数据。 </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 从基础爬虫到商业化应用爬虫,本套课程满足您的所有需求! </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> <br /> </p> <p> <br /> </p> <p> <span style="font-size:14px;background-color:#FFFFFF;color:#337FE5;">【课程服务】</span> </p> <p> <span style="font-size:14px;">专属付费社群+定期答疑</span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"><br /> </span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"></span> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏

jiangtao

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值