2006年12月27日

 public ActionErrors validate(ActionMapping actionMapping,
                                 HttpServletRequest httpServletRequest) {
        String style =
                "^[a-zA-Z][a-zA-Z0-9._-]*@([a-zA-Z0-9-_]+\\.)+(com|gov|net|com\\.cn|edu\\.cn)$";
        Pattern ptt = Pattern.compile(style);
        Matcher mch=ptt.matcher(email);
        ActionErrors errors = new ActionErrors();
        if ((name == null || name.equals(""))) {
            ActionError error = new ActionError("error.name");
            errors.add("name", error);
        } else
        if (!mch.matches()) {
            ActionError error = new ActionError("error.email");
            errors.add("email", error);
        }
        return errors;
    }

posted @ 2006-12-28 11:58 鹭 阅读(1290) | 评论 (0)编辑 收藏

在Struts中,担任 MVC / Model 2 中Controller角色的是ActionServlet,所有的请求都必须先通过它,然而在Struts 1.1後,有关於请求的处理大部份已交由RequestProcessor,当ActionServlet收到GET或POST的请求,其doGet() 或doPost()会呼叫process()方法来处理请求:
protected void process(HttpServletRequest request,
                        HttpServletResponse response)
                   throws IOException, ServletException {
    RequestUtils.selectApplication(request,
                                   getServletContext());
    getApplicationConfig(
         request).getProcessor().process(request, response);
}
 
RequestUtils是个工具类,ActionServlet呼叫其selectApplication()方法,藉由 request.getServletPath()来取得请求路径以选择应用程式模块来处理请求,之後从ApplicationConfig物件取得 RequestProcessor物件,将使用者的请求委托它来进行处理。

通常是将ActionServlet当作黑盒子,您只要使用它,然而您也可以继承ActionServlet来定义自己的控制器,但由於在Struts 1.1中大部份的请求已经委托RequestProcessor来处理,继承ActionServlet来定义自己的控制器请求处理意义已经不大,通常的 目的是重新定义ActionServlet的init()方法,增加自己的初始化动作:
public class CustomActionServlet extends ActionServlet {
    public void init() throws ServletException {
        super.init();

        // 增加自己的初始化动作
        ....
    }
}
 
预设的RequestProcessor物件是org.apache.struts.action.RequestProcessor,您可以藉由观看 process()方法的原始码来了解它作了哪些事情:
public void process(HttpServletRequest request,
                     HttpServletResponse response)
                  throws IOException, ServletException {
    // 处理 contentType 为 multipart/form-data 的 POST 请求
    request = processMultipart(request);

    // 取得 URI 路径
    String path = processPath(request, response);
    if(path == null)
        return;
    .....

    // 确定客户端的位置
    // 是否要将一个Locale物件储存在 session 中
    // 配合 <controller> 的 locale 属性使用
    processLocale(request, response);

    // 确定contentType,预设是 text/html
    processContent(request, response);

    // 判断<controller>属性nocache是否被确定
    // 若是,在 response 中加入防止快取的header
    processNoCache(request, response);

    // 前置处理,预设返回 true
    //子类可以重新定义它以决定要不要继续处理
    if(!processPreProcess(request, response)) {
        return;
    }

    // 从URI路径确定ActionMapping
    ActionMapping mapping =
                   processMapping(request, response, path);
    if(mapping == null) {
        return;
    }

    ....

    // 处理ActionForm
    // 如果没有就新增一个,之後一直使用它
    ActionForm form =
            processActionForm(request, response, mapping);
   
    // 将表单的栏位值填入ActionForm
    processPopulate(request, response, form, mapping);

    // 判断是否执行ActionForm的validate()方法
    if(!processValidate(request, response, form, mapping)) {
        return;
    }

    // 判断 标签的 forward 或 include 标签
// 是不是被设定,这两个标签在设定一个路径
// 其与 type 属性是互斥的,当设定其中一个属性时
// 调用 RequestDispatcher 的 forward() 或 include()
// 其作用与设定ForwardAction或IncludeAction相同
// 直接绕送而不再使用Action物件进行接下来的处理

    if(!processForward(request, response, mapping)) {
        return;
    }
    if(processInclude(request, response, mapping)) {
        return;
    }

    // 处理Action,如果没有就生成一个,之後一直使用它
    Action action =
            processActionCreate(request, response, mapping);
    if(action == null) {
        return;
    }

    // 呼叫Action的execute()或perform()方法
// 并返回ActionForward

    ActionForward forward =
                    processActionPerform(request,
                                         response,
                                         action,
                                         for, mapping);

    // 处理ActionForward
    processActionForward(request, response, forward);
}
 

您可以继承RequestProcessor,并改写其中的processXXXXX()方法来自定义请求的处理方式,如果您要使用自己的 RequestProcessor,要在struts-config.xml中使用<controller>标签来定义,例如:
  • struts-config.xml
...
<controller
contentType="text/html;charset=Big5"
locale="true"
nocache="true"
processorClass="caterpillar.CustomRequestProcessor"/>
...

在Struts 1.1後,新增了<controller>标签,它可以用於指定ActionServlet的一些参数,在Struts 1.1之前,这些参数是在<init-params>中加以指定,使用<controller>标签,应用程式中不同的模组也可 以指定各自的参数给ActionServlet。

posted @ 2006-12-28 10:24 鹭 阅读(808) | 评论 (0)编辑 收藏

html:link有很多参数选项,如关键有:
action --指定点击链接后,进入的*.do动作action的值不需要跟后缀,struts自动补上.do
page  -- 跟action一样的功能,不过这个不会自动补.do,也就是说可以链接其他类型的动作,如html,jsp,php等

paramId--指定参数的key名称,如要输出http://abc.com/ss?kk=abc,则paramId="kk"
paramName -- 能识别作用域(任意)内的Object的名称。
paramProperty--paramName的输出属性,paramId,paramName ,paramProperty可以组成单一参数传递的link,如<html:link  action="/PRC301E1"  paramId="prc_no" paramName="element" paramProperty="fjPrcNo">,当element.getfjPrcNo()的值为prc1时,则输出为 http://xxoo.com/PRC301E1.do?prc_no=prc1

name--为HashMap属性的对象,用此属性,可以进行多参数输出。例:

CODE:
[Copy to clipboard]
     <%
        HashMap map=new HashMap();
       map.put("check","22");
       map.put("name","abc");
       pageContext.setAttribute("map",map); //因为所有tag的取值只会搜索作用域(page/request/session/application),而不会识别当前的实例,所以只有存入。
      %>
      <html:link action="/PRC301E1"  name="map">
        多参数输出
      </html:link>

-----------------------------------------------------------------------------------------

在struts标签<html:link>的page属性指定的URI后面传递参数可以有几种方式:

1.若明确参数名和参数值则直接在URI后输出,
如:<html:link page="/test.do?action=add">add</html:link>

2.对于参数值不确定的,paramName和paramProperty来输出,用paramId属性指定参数名。
对于paramName指定的对象应该存在于page、request、session、application其中之一。一般来说,是从Action类传过来的,作为request的属性之一(requst.setAttribute("name",object))。
如果paramName指定的对象是action的ActionForm,则无需使用request.setAttribute方法。
例:<html:link page="/test.do" paramId="userid" paramName="uid">uname</html:link>
若参数值是一个bean对象的属性值(比如ActionForm,或者集合中存放的对象)则:
<html:link page="/test.do" paramId="userid" paramName="user" paramProperty="uid">uname</html:link>

3.若两个参数,一个确定一个不确定,则是以上两种方法的结合,即:
<html:link page="/test.do?action=modify" paramId="userid" paramName="uid">modify</html:link>

4.对于多个参数的问题,可以使用一个HashMap集合对象来存放所有的参数名及对应的参数值的方式,paramName属性值指定为该HashMap集合对象即可。
举例:
<%
//代码理想的位置应该是在action中
//可以在jsp页面测试
  java.util.HashMap pms = new java.util.HashMap();
  pms.put("code", "001002");
  pms.put("name", "tester");
  pms.put("alias", new String[]{"matin","jack"});
  request.setAttribute("params", pms);
%>
<html:link action="/test.do" name="params" >test</html:link>
编译后的结果:<a href="/test.do?code=001002&name=tester&alias=matin&alias=jack">test</a>
这种方式虽然可以解决传多参数的问题,但是实现起来也比较麻烦,特别是对记录集中的数据逐条列出的时候

5.针对有的网友在<html:link>标签中嵌入使用jsp脚本(scriptlet)的问题,
例如:
<html:link page="/test.do?code=<%=varible%>">add</html:link>,这种写法是错误的,是无法编译的。
有的网友认为在struts标签内是不允许使用jsp脚本的,这种说法也不准确。如果前面的写法改成:
<html:link page="<%="/test.do?code="+varible%>">add</html:link>,就可以被执行,但是要注意URL相对路径的问题。

虽然在struts标签中嵌入jsp脚本不是真正意义上的struts应用,但是有时在委曲求全的情况下也只能如此了,除非使用自定义标签。比如在form表单中可能需要根据具体数据让某个字段是只读的,就可以用嵌入jsp脚本来实现:
<%
boolean rdonly=false;
if(2==2) rdonly=true;
%>
<html:text property="userid" readonly="<%=rdonly%>" />

6.另外一种比较变态的方法,既不是真正意义上的struts,也不符合xml规范。那就是在<a>标签中用<bean:write>标签输出参数值。
如:<a href="test.do?uid=<bean:write name="user" property="userid"/>&name=<bean:write name="user" property="username"/>">test</a>

posted @ 2006-12-27 14:35 鹭 阅读(337) | 评论 (0)编辑 收藏