RIACHINA 中国RIA开发者论坛RIA 客户端开发FLEX 专区 Flex 中 使用 HttpSession 问题的讨论

Flex 中 使用 HttpSession 问题的讨论

Flex 中 使用 HttpSession 问题的讨论

需求很简单
整个项目由 flex 组成的客户端
flex 和 后台 通信 采用 RemoteService  方式

客户要求  超过10 分钟 不操作 系统自动退出 ,用户 再重新操作与服务器有交互的时候 要提醒客户 重新登陆。
(这在以往 jsp 项目中很容易实现  filter 中判断session 过期转入登陆页面 即可 )

现在 俺搞不定了 

俺 到是 同样在 filter 中  判断出了 session 是否登陆过 或者是否过期  但是 我无法把过期的信息  返回给 flex

我尝试了 
1  throw new RuntimeException("重新登陆") 
2  response.sendRedirect("http://localhost:8088/01-flex/login!nologin.action");
等方式  最终也没有成功 ,我无法在

private function faultHander(event:FaultEvent):void{}

函数中 得到  真正的错误的原因  如  "重新登陆" 等字样.


另 我注意到 另一个帖子中 提到过  在客户端  写 定时器 来判断session 是否过期

但是  项目  安全级别比较高 客户端的 方式不可取.

那位仁兄  有 解决方案  请公开下 ,  我还在研究  有方案  一定公开。
最后编辑leezyu 最后编辑于 2007-11-27 14:23:31
 

回复:Flex 中 HttpSession 过期 问题的讨论

如果 采用 HttpService 的方式  这个问题很好解决  但是 RemoteService 开发比较方便
所以 HttpService 的方式 不在考虑之中
 

回复: Flex 中 HttpSession 过期 问题的讨论

RemoteService 中捕捉到的所有信息
其中 没有俺 需要的

(mx.messaging.messages::ErrorMessage)#0
  body = (Object)#1
  clientId = (null)
  correlationId = "4E82AD14-025B-0A47-2F61-75CA2AC5E8AE"
  destination = ""
  extendedData = (null)
  faultCode = "Client.Error.MessageSend"
  faultDetail = "Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Status 500: url: 'http://localhost:8088/01-flex/messagebroker/amf'"
  faultString = "Send failed"
  headers = (Object)#2
  messageId = "4A14C3EA-2AC2-2BB4-AD21-75CA2B13C7A8"
  rootCause = (Object)#3
    code = "NetConnection.Call.Failed"
    description = "HTTP: Status 500"
    details = "http://localhost:8088/01-flex/messagebroker/amf"
    level = "error"
  timestamp = 0
  timeToLive = 0
 

回复: Flex 中 HttpSession 过期 问题的讨论

不明白为什么response.sendredirect不行呢?
要不就在resultHandler中返回重新登陆的信息,客户端判断是这个信息就提示重新登陆
 

回复:Flex 中 HttpSession 过期 问题的讨论

就用定时器就可以
什么项目  安全级别比较高 客户端的 方式不可取无意义
 

回复: Flex 中 HttpSession 过期 问题的讨论

先回复 4 楼的
您说的两个方法我都试过
在remoteService 中  得到的 是 AMFChannel connected failed 错误
无法 区分 是因为session 过去  还是因为 网络连接错误  或者 其他 服务器内部 500错误
您尝试下  也许您有更好的 得到 result 和 fault 的方法

再说5 楼的
项目 中 每比单据的资金都过百万
我无法控制  所有的客户端都和服务器端的时间同步

只要有一比单据 因为这个出错 俺们都吃不了兜者走  所以  必须 服务器端验证才保险
 

回复:Flex 中 HttpSession 过期 问题的讨论

今天发现了
aop+ThreadLocal 的方法  也许可以搞定
有些眉目了  正在整理中
 

回复:Flex 中 使用 HttpSession 问题的讨论

测试成功了 
AOP+ThreadLocal 的方法  搞定了
感谢 网络上那个 session 和 应用服务器和 thread 关系的帖子
 

回复:Flex 中 使用 HttpSession 问题的讨论

从此 项目中  完全采用 remoteService 了
http 的方式 彻底放弃
 

回复: Flex 中 使用 HttpSession 问题的讨论

解决方案很简单  针对flex2

采用filter 监控 MessageBrokerServlet  把context 放入  ThreadLocal  中

然后你就可以从 java 程序的任何 方法中 利用 ThreadLocal  得到 当前的session

这个时候结合aop 我采用spring 的aop  在需要 session 验证的方法前 调用一个 Interceptor  来验证 session 过期或者其他权限等

具体代码:

web.xml 中

                <filter>
    <filter-name>AMFContextFilter</filter-name>
    <filter-class>flex.context.AMFContextFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>AMFContextFilter</filter-name>
    <servlet-name>MessageBrokerServlet</servlet-name>
    </filter-mapping>


AMFContextFilter文件

package flex.context;

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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class AMFContextFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws ServletException, IOException {

        AMFContext.setCurrentContext((HttpServletRequest) request,
                (HttpServletResponse) response);

        chain.doFilter(request, response);
    }

    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

    public void destroy() {
        // TODO Auto-generated method stub

    }

}


AMFContext文件

package flex.context;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class AMFContext {

    /**
     * ThreadLocal object for storing object in current thread.
     */
    private static ThreadLocal tl = new ThreadLocal();

    /**
     * Set current context
     *
     * @param request
     *            The HttpRequest object
     * @param response
     *            The HttpResponses object
     */
    @SuppressWarnings(&amp;quot;unchecked&amp;quot;)
    static public void setCurrentContext(HttpServletRequest request,
            HttpServletResponse response) {
        AMFContext c = getCurrentContext();
        if (c == null) {
            c = new AMFContext(request, response);
            tl.set(c);
        } else {
            c.setRequest(request);
            c.setResponse(response);
        }
    }

    /**
     * Get current context value
     *
     * @return The current context
     */
    static public AMFContext getCurrentContext() {
        return (AMFContext) tl.get();
    }

    // ----------------------------------------------------------
    //
    // Class members
    //
    // ----------------------------------------------------------

    /**
     * The http request object. The lifecycle of the request object is defined
     * as the request scope. It may be reused in another incoming connection, so
     * dont use it in another thread.
     */
    private HttpServletRequest request;

    /**
     * The http response object. The lifecycle of the response object is defined
     * as the request scope. Dont use it in another thread. Also dont write
     * output to the response when it is used in the context, but you may get or
     * set some response header when it is safe.
     */
    private HttpServletResponse response;

    /**
     * The constructor is private, to get an instance of the AMFContext, please
     * use getCurrentContext() method.
     *
     * @param request
     * @param response
     */
    private AMFContext(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    /**
     * Get request object
     *
     * @return Http request object
     */
    public HttpServletRequest getRequest() {
        return request;
    }

    /**
     * Set request object
     *
     * @param Http
     *            request object
     */
    public void setRequest(HttpServletRequest request) {
        this.request = request;
    }

    /**
     * Get response object
     *
     * @return Http response object
     */
    public HttpServletResponse getResponse() {
        return response;
    }

    /**
     * Set response object
     *
     * @param response
     *            Http response object
     */
    public void setResponse(HttpServletResponse response) {
        this.response = response;
    }

    /**
     * Get the servlet context
     *
     * @return
     */
    public ServletContext getServletContext() {
        HttpSession session = this.getSession();
        return session.getServletContext();
    }

    /**
     * Get the current running session
     *
     * @return
     */
    public HttpSession getSession() {
        return request.getSession();
    }

    /**
     * Get an object stored in the session.
     *
     * @param attr
     *            Attribute Name
     * @return The value stored under the attribute name.
     */
    public Object getSessionAttribute(String attr) {
        HttpSession session = this.getSession();
        return session.getAttribute(attr);
    }

    /**
     * Store an object in the session.
     *
     * @param attr
     *            Attribute Name
     * @param value
     *            The value.
     */
    public void setSessionAttribute(String attr, Object value) {
        HttpSession session = this.getSession();
        session.setAttribute(attr, value);
    }

    /**
     * Get an object stored in the servlet context.
     *
     * @param attr
     *            Attribute Name
     * @return The value stored under the attribute name.
     */
    public Object getContextAttribute(String attr) {
        ServletContext sc = this.getServletContext();
        return sc.getAttribute(attr);
    }

    /**
     * Store an object in the servlet context.
     *
     * @param attr
     *            Attribute Name
     * @param value
     *            The value.
     */
    public void setContextAttribute(String attr, Object value) {
        ServletContext sc = this.getServletContext();
        sc.setAttribute(attr, value);
    }

    /**
     * Get an object stored in the current request.
     *
     * @param attr
     *            Attribute Name
     * @return The value stored under the attribute name.
     */
    public Object getRequestAttribute(String attr) {
        return request.getAttribute(attr);
    }

    /**
     * Store an object in the current request.
     *
     * @param attr
     *            Attribute Name
     * @param value
     *            The value.
     */
    public void setRequestAttribute(String attr, Object value) {
        request.setAttribute(attr, value);
    }

}


MethodInterceptor 文件

package com.sunwayworld.flex;

import javax.servlet.http.HttpServletRequest;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import com.sunwayworld.common.utils.SessionUtils;

import flex.context.AMFContext;

public class FlexSessionInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {

        AMFContext context = AMFContext.getCurrentContext();

        HttpServletRequest request = context.getRequest();
        if (!SessionUtils.isLogin(request)) {
            throw new RuntimeException(&amp;quot;请您重新登陆!&amp;quot;);
        }

        Object obj = invocation.proceed();

        return obj;
    }

}


然后 在spring 配置 成调用所有的java 方法前都执行这个  MethodInterceptor  即可
最后编辑leezyu 最后编辑于 2007-11-27 14:46:14
 

回复:Flex 中 使用 HttpSession 问题的讨论

谢谢分享,置顶加精,鼓励各位将问题的解决方案分享。
这样一来,基于flex开发的话,j2ee的传统架构将完全打破了。好事。
最后编辑cimmicola 最后编辑于 2007-11-27 17:16:25
 

回复:Flex 中 使用 HttpSession 问题的讨论

不知道你有没有试过,复杂ASobject在映射到java去的时候,数据还原不完整。
比如在as对象中
group->users(Array)->user1->uname
                                      ->uid
                            ->user2->uname
                                      ->uid

java 方法saveGroup(Group group){.....}
这个group里的数据还原不完整了。当然,我没有在as端建立vo,是动态new的object,动态添加的属性。也有可能是这个原因
 

回复: Flex 中 使用 HttpSession 问题的讨论



引用:
原帖由 cimmicola 于 2007-11-27 17:33:00 发表
不知道你有没有试过,复杂ASobject在映射到java去的时候,数据还原不完整。
比如在as对象中
group->users(Array)->user1->uname
                                      ->uid
                  ......



直接添加的属性,好像不是PUBLIC的吧, 那么序列化将会失败
 

回复:Flex 中 使用 HttpSession 问题的讨论

已经在googlecode上mashup了
http://flex-java.googlecode.com/svn/trunk
Protoss拥有高度的文明、先进的科技和强大的精神力量。但是由于长达千年的寿命,种群数量稀少,消耗不过繁殖能力出众的Zerg,险些被Zerg给灭族。
 

回复: Flex 中 使用 HttpSession 问题的讨论



引用:
原帖由 cimmicola 于 2007-11-28 10:47:00 发表
已经在googlecode上mashup了
http://flex-java.googlecode.com/svn/trunk




斑竹 比我还 积极

简单介绍下
项目只实现了 登陆和注册

googlecode 上 可以采用svn 得到整个工程

工程中分01-java 和01-flex 两部分
项目中 所有的struts2 部分 在web.xml 和spring 的配置文件中注释了  只要打开struts2 马上就可以采用

注释是因为  有上边的session 解决方案 我感觉struts2 完全没有必要再存在了

remote 方式 开发起来更简单
 

回复:Flex 中 使用 HttpSession 问题的讨论

这个方法好像有点歪门邪道,好像没有ThreadLocal 一定是处理同一个session的说法吧,我的解决办法是做一个session listener发送message去客户端,客户端一个consumer监听message, 当收到session过期就自动redirect回登陆页面
 

回复:Flex 中 使用 HttpSession 问题的讨论

楼上的方法 是不是用jms 呢?
jms 开销有点大

至于 ThreadLocal 的问题 也是查了N多资料  并在多个版的服务器里测试通过的
 

回复:Flex 中 使用 HttpSession 问题的讨论

回silver的,这样还有一个好处就是不会因为remoteobject而丧失传统的request信息。
Protoss拥有高度的文明、先进的科技和强大的精神力量。但是由于长达千年的寿命,种群数量稀少,消耗不过繁殖能力出众的Zerg,险些被Zerg给灭族。
 

回复:Flex 中 使用 HttpSession 问题的讨论

一个在.Net采用表单验证的人飘过
 

回复:Flex 中 使用 HttpSession 问题的讨论

已经看了一点相关flex的资料,这个Session是作为我们从其他平台(Java)转用Flex的一个需要考虑的内容,
刚刚测试了这种获得Session的方案,的确可行的。
和楼主一样,我们使用校验也是使用Session过期的方式,但是既然有使用RIA的打算,
给予用户的体验就不能够类似以前,一旦超时则跳转到登录页面,我的打算是通过后台抛出一个未登陆的异常,有没有什么方法从程序的整体来捕获这个异常呢?
 
1  /  2  页   12 跳转

版权所有 riachina.com   Sitemap

Powered by Discuz!NT 2.1.202    Copyright © 2001-2008 Comsenz Inc.
Processed in 0 second(s) (Cached).
返顶部