ContextAttribute与ContextBoundObject应用开发2

昨天了解了ContextAttribute与ContextBoundObject应用开发的一些基础,今天准备在ContextBoundObject对象之上加入消息拦截器,来测试一下应用。
 经过昨天了学习了解到ContextAttribute与ContextBoundObject这一组对象之间的核心关系为:
   IContextAttribute:用于标识上下文环境相关Attribute,当CLR在创建MarshalByRefObject对象时会先查看对象是否包括:IContextAttribute特性,如果存在则询问IContextAttribute.IsContextOK来查询是否需要新的上下文环境,如果返回false则表示需要创建新的上下文环境,并且调用GetPropertiesForNewContext来设计新环境的属性。
   IContextProperty:用于标识上下文环境的属性,可以在GetPropertysForNewContext向新的上下文环境中添加新的自定义属性。
   IContributeObjectSink:如果需要向上下文环境中添加自定义的消息拦截器,由需要IContextProperty的实现对象同时实现本接口。
   还有更多的XXXObjectSink:如果实现也实现相应的消息接收,这里暂不考虑。
注意:如果IContextAttribute附加的对象没有继承自MarshalByRefObject则附加的IContextAttribute会与普通特性一样,不会产生新的上环境文环境。
   了解这一核心关系后,再回过来看昨天所编写的代码,发现其实ConextAttribute已实现IContextAttribute, IContextProperty两个接口。这里所需要添加的只是需要DemoContextAttribute实现IContributeObjectSink接口,并且添加新的消息拦截器。修改后的代码为:

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Runtime.Remoting.Contexts;
using  System.Runtime.Remoting.Activation;
using  System.Runtime.Remoting.Messaging;

namespace  ContextDemo  {
    
public class DemoContextAttribute : ContextAttribute, IContributeObjectSink {
        
public DemoContextAttribute()
            : 
base("DemoContextAttribute"{
            Console.WriteLine(
"Call 'DemoContextAttribute' - 'Constructor' ");
        }


        
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink) {
            Console.WriteLine(
"Call 'DemoContextAttribute' - 'GetObjectSink' ");

            
return new DemoMessageSink(nextSink);
        }

    }


    
public class DemoMessageSink : IMessageSink {
        
public DemoMessageSink(IMessageSink nextSink) {
            Console.WriteLine(
"Call 'DemoMessageSink' - 'Constructor' ");
            
this.nextSink = nextSink;
        }


        
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) {
            
// 暂不考虑
            return null;
        }


        
private IMessageSink nextSink = null;
        
public IMessageSink NextSink {
            
get return nextSink; }
        }


        
public IMessage SyncProcessMessage(IMessage msg) {
            Console.WriteLine(
"Call Begin 'DemoMessageSink' - 'SyncProcessMessage' ");

            IMessage returnMsg 
= nextSink.SyncProcessMessage(msg);
            Console.WriteLine(
"Call End 'DemoMessageSink' - 'SyncProcessMessage' ");

            
return returnMsg;
        }

    }


    [DemoContext]
    
public class DemoContextBoundObject : ContextBoundObject {
        
public DemoContextBoundObject() {
            Console.WriteLine(
"Call 'DemoContextBoundObject' - 'Constructor' ");
        }


        
public void CallMethod() {
            Console.WriteLine(
"Call 'DemoContextBoundObject' - 'Call Method' ");
        }

    }


    
class Program {
        
static void Main(string[] args) {
            Console.WriteLine(
"Begin Main ");
            
new DemoContextBoundObject().CallMethod();
            Console.WriteLine(
"End Main ");
            Console.Read();
        }

    }

}

执行后的结果为

查看结果了解到,获取消息拦截器的操作是在调用方法操作后才进行了,那么如果我在这里调用两次操作,是否会产生两次获取消息消息拦截器的操作呢。这里我将Main()操作修改如下:

  static   void  Main( string [] args)  {
            Console.WriteLine(
"Begin Main ");
            DemoContextBoundObject dcbo 
= new DemoContextBoundObject();
            dcbo.CallMethod();
            dcbo.CallMethod();
            Console.WriteLine(
"End Main ");
            Console.Read();
        }

显示的结果如下:

 这里可以看出只调用了一次获取消息拦截器的操作。那么我又想如果这里生成两个对象并且调用同一个方法又会产生什么结果呢。Main()方法修改如下:

static   void  Main( string [] args)  {
            Console.WriteLine(
"Begin Main ");
            
new DemoContextBoundObject().CallMethod();
            
new DemoContextBoundObject().CallMethod();
            Console.WriteLine(
"End Main ");
            Console.Read();
        }
最后的结果显示为:

和想像中的一样,调用了两次生成Sink的过程。我又想如果在消息拦截的过程中引发了异常将会也现什么总是呢。于是我再次DemoObjectSink的代码修改如下:
    public  IMessage SyncProcessMessage(IMessage msg)  {
            Console.WriteLine(
"Call Begin 'DemoMessageSink' - 'SyncProcessMessage' ");
            
throw new Exception("I'm a exception");
            IMessage returnMsg 
= nextSink.SyncProcessMessage(msg);
            Console.WriteLine(
"Call End 'DemoMessageSink' - 'SyncProcessMessage' ");
            
return returnMsg;
        }
并且将Main()的代码修改如下:
  static   void  Main( string [] args)  {
            Console.WriteLine(
"Begin Main ");
            
try {
                
new DemoContextBoundObject().CallMethod();
                Console.WriteLine(
"End Main ");
            }

            
catch (Exception ex) {
                Console.WriteLine(
"Raise Exeption Message:{0}", ex.Message);
            }

            Console.Read();
        }
执行的结果如下:

这里可以发现执行的结果与在方法中执行时产生异常的形式是相同的,已是我就要如果用这种方式来进行安全检查会不会得以实现呢?

转载于:https://www.cnblogs.com/jeffwoot/archive/2008/05/20/1203174.html

如果不能通过request对象来获取所有session,可以通过ServletContext对象来获取。以下是一种常见的实现方式: 1. 在web.xml文件中添加一个初始化参数,用于指定ServletContext的属性名称。例如: ``` <context-param> <param-name>contextAttribute</param-name> <param-value>myapp.sessions</param-value> </context-param> ``` 2. 在应用程序启动时,创建一个ServletContextListener监听器,用于在ServletContext初始化时将所有session保存到ServletContext中。例如: ``` public class SessionListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { ServletContext servletContext = event.getServletContext(); String attributeName = servletContext.getInitParameter("contextAttribute"); Map<String, HttpSession> sessions = new ConcurrentHashMap<String, HttpSession>(); servletContext.setAttribute(attributeName, sessions); } public void contextDestroyed(ServletContextEvent event) { ServletContext servletContext = event.getServletContext(); String attributeName = servletContext.getInitParameter("contextAttribute"); servletContext.removeAttribute(attributeName); } } ``` 3. 在应用程序中,使用ServletContext对象来获取所有session。例如: ``` ServletContext servletContext = getServletContext(); String attributeName = servletContext.getInitParameter("contextAttribute"); Map<String, HttpSession> sessions = (Map<String, HttpSession>) servletContext.getAttribute(attributeName); for (HttpSession session : sessions.values()) { //操作session } ``` 需要注意的是,这种方式需要在ServletContext初始化时将所有session保存到ServletContext中,因此需要考虑如何处理session的创建和销毁事件。另外,由于所有session都保存在内存中,可能会占用大量的系统资源,需要考虑如何优化数据结构和存储方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值