SkyHome DEMO//学习Struts等而做的系统,欢迎指正

03-04-26 anonymous
SkyHome is a web system base on MVC and developed with

a simple and similar Struts framework.It developed for learn

J2EE,Patterns and other things like XP and PSP etc.

去年刚毕业时想着学点什么,于是从JSP入手看J2EE,光看不练没什么用,

正好想着把原来的网站改改,于是就开始了skyinn的计划,由于自己懒惰等

中途一直搁浅,直到11月底才又重新开始。由于自己原来基本什么都不懂,

所以边学边用的进度一直很慢,写了近半年才有了现在的这个样子,虽然可以

用了,但还有N多地方需要改进,甚而还有很多纰漏,执行速度也不是很理想,

汗颜的很!

一开始模仿雷霆论坛,看懂一点写一点,花了很长时间,后来接触了

Struts,就花了点工夫研究了下,想多写很多了,全部放弃换Struts再做有

点不甘心,而且觉的用Struts做个简单的网站也没都大意思,能学到的技术

也并不是很多,于是想着干脆再将Struts里的好东西拿来为我所用什么的,即

可以对Struts有更深入的学习,又不用全部推翻原来的东西,何乐而不为呢?

于是在过年后不久开始一点点的应用起来,其实也不过是简化了Struts中的某

几个类来用而已,而到现在则越来越Struts了:)所以当看到和Struts很像或

一样的代码时别犯疑惑:怎么这么熟悉:P

半年多来,基本上把所有的业余时间都花在这上了,虽然学了不少,但正

如前人所说:学的越多不知道的也越多。换句话叫终于知道自己不知道了。也

终于能静下心来学习了,只是感到时间老是不够用。

独学而无友,则孤陋而寡闻。共享之,如班门弄斧,贻笑大方了。不足之

处尚请谅解,更希望能将错误、意见、建议等告诉我,欢迎一起讨论交流:)

网站:http://www.skyinn.org

源码及工程文档:http://www.skyinn.org/project/index.jsp

邮件:webmaster@skyinn.org

banq
2003-04-28 16:03
非常不错的网站,我已经在首页和你做了友情连接。

看来你的struts使用是有一定的经验,顺便问一个困扰我的问题:比如:当用户发言时,他因为没有登陆故后台推出一个login的页面,当用户输入用户名和口令进入后可继续到发言的页面。这个流程机制有很多实现方式,我想知道你的方式,可否相告?

anonymous
2003-04-29 01:28
板桥的话让偶极度汗颜~~~呵呵

我现在的做法使这样的:

1:在AuthorizationFilter中判断是否已经登陆,

若没有,则记下此时的requestURI和所有参数(很奇怪,用request的getParamSet()再转回来就不对了,不知道那里错了,现在改成用hashtable了),把这些存到session中(放到request中不成,放到ServletContext中也有问题,还是用session好处理点)

2:然后再登陆处理的LoginAction中,当用户登陆成功后

取出session中的这些参数组合成请求串

用此请求串向web服务器请求(我用request的setAttinbute()等方法都不成功,没办法只有把所有参数连在URI后面了,不知道还有什么办法的没,哪位高手知道给指点下:)

即已实现

但这样做有很多弊病,

如所有参数都连在URI后面了,所以当参数值超大的话肯定要出错,这是目前这种方法的最大隐患:(

下面是部分程序片段,因为是刚写的,所以我网站里的源码中没有这个

AuthorizationFilter部分:

if(passed(servletRequest))
            filterChain.doFilter(servletRequest, servletResponse);
        else{//否则则重定向到错误页
            //get request & response
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            HttpSession session = request.getSession(true);
            //ServletContext sc = filterConfig.getServletContext();
            //存请求路径
            if(null == session.getAttribute(GlobalParams.REQUEST_PATH_KEY)){
                final String requestPath = request.getRequestURI();
                session.setAttribute(GlobalParams.REQUEST_PATH_KEY, requestPath);
            }
            //存请求参数
            if(null == session.getAttribute(GlobalParams.PARAM_MAP_KEY)){
                final Enumeration paramNames = request.getParameterNames();
                final Hashtable hash = new Hashtable();
                Object key = null;
                //逐个添加
                while(paramNames.hasMoreElements()){
                    key = paramNames.nextElement();
                    hash.put(key, request.getParameter(key.toString()));
                }
                session.setAttribute(GlobalParams.PARAM_MAP_KEY, hash);
            }
            final String loginPage = this.filterConfig.getInitParameter("LOGIN_PAGE");
            //重定向
            filterConfig.getServletContext().getRequestDispatcher(loginPage).forward(request, response);


            /*//error infomation
            final ErrorBean errorBean = new ErrorBean("ERROR.AUTHORIZATION.NOT_ALLOW_ACCESS");
            //set to request
            request.setAttribute(ErrorBean.ERRORBEAN_KEY,errorBean);
            final String errorPage;
            //get error page
            errorPage = this.filterConfig.getInitParameter("ERROR_PAGE");
            filterConfig.getServletContext().getRequestDispatcher(errorPage).forward(request, response);*/
        }//end if ... else...

LoginAction部分:

//检查通过,loginBean置入session
                    HttpSession session = request.getSession(true);
                    session.setAttribute(LoginBean.LOGINBEAN_KEY, loginBean);
                    //final ServletContext sc = session.getServletContext();
                    //登陆之前的URL
                    StringBuffer requestPath = new StringBuffer();
                    requestPath.append(session.getAttribute(GlobalParams.REQUEST_PATH_KEY));
                    //*************must
                    session.setAttribute(GlobalParams.REQUEST_PATH_KEY, null);
                    log.debug("requestPath:" + requestPath);
                    //参数
                    final Object obj = session.getAttribute(GlobalParams.PARAM_MAP_KEY);
                    //*************must
                    session.setAttribute(GlobalParams.PARAM_MAP_KEY, null);
                    final Hashtable hash = (Hashtable) obj;
                    //参数名集合
                    final Enumeration paramNames = hash.keys();
                    final StringBuffer strParams = new StringBuffer();
                    //逐个添加参数
                    Object key = null;
                    while(paramNames.hasMoreElements()){
                        key = paramNames.nextElement();
                        request.setAttribute(key.toString(), hash.get(key));
                        //log.debug(key + ":" + hash.get(key));
                        //such as ForumID=0&PageNo=1&
                        strParams.append(key).append("=").append(hash.get(key)).append("&");
                        //request.setAttribute(key.toString(),hash.get(key));
                    }
                    //去掉最后的"&"
                    if(0 < strParams.length()){
                        strParams.substring(0, strParams.length() - 2);
                    }
                    //连接such as:http://www.skyinn.org/Forum.do?ForumID=0&PageNo=1
                    requestPath.append("?").append(strParams);
                    if(0 < requestPath.length()){
                        result = new ActionResult(ActionResult.SUCCESS, requestPath.toString(), true);
                    } else{
                        result = mapping.getResult(ActionResult.SUCCESS);
                    }
<p>

再想想别的办法了,这个总不如意...

and 谢谢你的连接:)

anonymous
2003-04-29 01:30
倒~~~~

早知道预览下了:P

banq
2003-04-29 08:45
不错,你和我想到一块儿去了,我也曾经这样作过,但是总觉得不是很好,特别是参数很长时。

我看有些开放源码如liferay也采取类似这么做法,将下个页面和参数附在form action后传入,然后使用一个forward.jsp来处理跳转,这个办法与Struts原则不容,更不是好办法。

ofbiz也是直接将参数附在login.jsp的action后面。

好像是没有更好的方法了。

wys1978
2003-04-29 09:35
To I_walker,

关于你提到的第2点, 我是用一个中间dummy的jsp来做的, 把session中的变量遍历一下, 放在jsp的form表单里, 然后用javascript自动提交这个表单, 这样就不会出现你提到的问题了.

anonymous
2003-04-29 11:44
good idea!

回去试试先:)

xxgw
2003-04-29 22:54
ejb或者其他什么o/r mapping 工具

anonymous
2003-04-30 10:36
很汗颜,EJB什么的都还好好研究过,现在系统使用的是很“原始”的做法,呵呵:)

O/R mapping偶考虑用jdo,不过只是稍微接触了点JDO,以后再研究了

现在偶把注意力全部放在模块化上,

我的构思是当增加新功能模块时不需要重新编译原有的基本类包,

而只需要提供jar、jsp页面、配置文件等,顶多再修改下基本配置文件,

如此扩展功能而不需要修改其他的东西,岂不简单省事的很,呵呵:)

不懂的太多了,慢慢实现了,请给点意见:)

下面帖俩段刚这俩天天构思的XML配置文件

基本配置文件:

<? xml version="1.0" encoding="gb2312" ?>
<!--Quasar Configuration File
    Create by l_walker(walker@skyinn.org) 2003-04-30.
    It config the system properties of Quasar for web application.
 -->
<quasar_config>
    <!--config the data source-->
    <datasources>
        <datasource
            name="base"
            type="mysql"
            description="Mysql data source"
            driverClass="org.gjt.mm.mysql.Driver"
            url="jdbc:mysql://localhost/skyhome"
            user="skyadmin"
            password="skyadmin"
            maxConn="30"
            minConn="2"
            autoCommit="false"
        />
    </datasources>

    <!--config modules-->
    <modules>
        <module
            name=""
            configFile=""
        />
    </modules>

</quasar_config>

模块配置文件:

<? xml version="1.0" encoding="gb2312" ?>
<!--Skyhome Configuration File-->
<quasar_module>
    <!--module info-->
    <module_info
        name="Skyhome"
        description="the web site system of www.skyinn.org"
        version="2.0.1"
        author="l_wakler"
        mail="walker@skyinn.org"
        updateTime="2003-04-30"
    />

    <!--action mappings-->
    <action_mappings>

    </action_mappings>
</quasar_module>

正在实现中,希望能成功,呵呵

banq
2003-04-30 10:55
都可以实现,模块配置文件可以参考ofbiz的service的实现,模块实际就是service的意思。

看来l_walker兄的软件经验还是比较丰富的,其实Java里面没什么新东西,只不过是将以前的经验进行归纳系统化。

云卷
2003-04-30 13:54
好人啊!高人啊!

占个地方来听听,先!

anonymous
2003-04-30 19:26
发布几个规范文件:)

http://www.skyinn.org/project/index.jsp

设计开发规范 :

http://www.skyinn.org/project/document/design_conv.doc

Java编程规范

http://www.skyinn.org/project/document/java_codeconv.doc

Javascript编程规范

http://www.skyinn.org/project/document/javascript_codeconv.doc

欢迎指正:)

Jevang
2003-05-02 00:10
if you handle conneciton pool yourself, suggest you need add more control properties. Here is a snippet from my topas datasource.xml.

<datasource

DSName="DefaultDSSQL"

IsDefault="true"

>

<login>sa</login>

<password></password>

<dbType>mssqlserver</dbType>

<url>jdbc:microsoft:sqlserver://wwang_2246:1433;selectMethod=cursor</url>

<driver>topas.server.rsadaptor.JdbcMS2000</driver>

<batchUpdate>false</batchUpdate>

<preparedInsert>false</preparedInsert>

<preparedUpdate>false</preparedUpdate>

<preparedSelect>false</preparedSelect>

<preparedDelete>false</preparedDelete>

<lockingHint></lockingHint>

<maximumPoolSize>50</maximumPoolSize>

<minimumPoolSize>1</minimumPoolSize>

<idleTimeout>30</idleTimeout>

<connectionTimeout>1</connectionTimeout>

<maximumPreparedStatements>50</maximumPreparedStatements>

<statementTimeout>180</statementTimeout>

<numOfFailureBeforeCleanUp>3</numOfFailureBeforeCleanUp>

</datasource>

Jevang
2003-05-02 00:19
looks like the xml get scrambled

datasource

DSName="DefaultDSSQL"

IsDefault="true"

#

loginsa#/login#

password##/password#

dbTypemssqlserver#/dbType#

urljdbc:microsoft:sqlserver://wwang_2246:1433;selectMethod=cursor#/url#

drivertopas.server.rsadaptor.JdbcMS2000#/driver#

batchUpdatefalse#/batchUpdate#

preparedInsertfalse#/preparedInsert#

preparedUpdatefalse#/preparedUpdate#

preparedSelectfalse#/preparedSelect#

preparedDeletefalse#/preparedDelete#

lockingHint##/lockingHint#

maximumPoolSize#50#/maximumPoolSize#

minimumPoolSize#1#/minimumPoolSize#

idleTimeout#30#/idleTimeout#

connectionTimeout#1#/connectionTimeout#

#maximumPreparedStatements#50#/maximumPreparedStatements#

statementTimeout#180#/statementTimeout#

#numOfFailureBeforeCleanUp#3#/numOfFailureBeforeCleanUp#

#/datasource#

Jevang
2003-05-02 00:48
For state info to be preserved between request, I think it's can be either on middle tier/server/httpsession( as pointed out by l_walker and banq) or client( Quake way), the third option is persist it into database( such as Amazon did ). store in middle tier is most straightforward, but for load balance and you only carry very few input, then resend back client is easiest to config. pro and con of using database is abvious.

When building my jsp framework TopStruts, what bother me most was not the implementation, it's figuring out how the user want to control security, below is my take on web based security enforcement pattern,

1. Globally enforced: This is the most straigted forward and many financial web site take this approach, in Struts, we can easily enforce authentication at actionservlet level.

Action(.do) and page(.jsp) are two main elements in struts, it seems make sense to enforce security to these two

2. For critical pages, especially with lots of entry points, declaring security check at individual page has many benefits. imagine a large team working on different area independently, developer does not need to worry about security when interfacing with "external area" as security is atomicly enforced and will be recognized globally as long as the agree on a common policy

3. If an app can be easily dividen into security enforced or unenforced areas and you have limited number of bridges across, action level enforcement is more maintainable than second approach, most shopping cart app fit in this category.

comments, critics are welcomed.

-Wanchun

猜你喜欢