Webx--实践细节点

0.action、screen、control的作用

action:用于接收请求参数,处理请求,并控制页面跳转。若跳转后的页面需要用到action中的参数,可以在action中将参数放到TemplateContext中。若是需要存储用户登录信息,可以将参数放到HttpSession当中。

screen:用于读取数据库中的信息,直接显示到页面,而没有用于显示页面的vm模板。

1.直接通过url访问Action

假设,要访问的Action类是user/AbcAction.java,方法是doSave(int id)

对应的url应该是:user/abcAction?action=user/abc_action&event_submit_do_save=anything&id=123

当有action参数时,其中的abcAction不重要,只要是abcAction类对应的目录即可,但要注意,提交到的方法一定要是doXxx,否则会报以下错误:

caused by com.alibaba.citrus.service.moduleloader.UnadaptableModuleException
Could not adapt object to module: type=action, name=AbcAction, class=class com.alibaba.webx.tutorial1.register.module.action.AbcAction
Could not find handler method for action event: null

action中对应的下划线表示法都会被mybatis改为java的驼峰表示法。有个mybatis设置是用于开关该表示法转换的。

2.通过form表单访问Action

在form表单中创建一个隐藏的input元素,name为action,value为目标Action.如,

<input type="hidden" name="action" value="login_action"/>

3.在Action中解析表单数据

public void doLogin(@FormGroup("login")Manager manager, Navigator nav, HttpSession session){
    Manager existedManager=managerMapper.selectManager(manager.getName(),manager.getPswd());
    if(existedManager!=null){
        session.setAttribute("manager",existedManager);
        nav.redirectTo("app1Link").withTarget("manager/home");
    }
}

4.在Action中解析URL参数

public class MyAction{
    @Autowired
    HttpServletRequest request;
    @Autowired
    HttpServletResponse response;
    @Autowired
    ManagerMapper managerMapper;
    
    public void deleteUser(Navigator nav){
        long id=Long.parseLong(request.getParameter("id"));
        Client client=clientMapper.selectClientById(id);
        clientMapper.deleteClient(client);
        nav.redirectTo("@app1Link").withTarget("manage/hint").withParameter("operation","删除");
    }
}

5.通过url访问Screen

对于一个请求localhost:8081/manager/manage_user?id=1,

1)webx会先看有没有action参数,这里没有,所以跳过Action执行步骤;

2)webx会看action/manager/下有没有ManageUser类,若有,会执行其execute方法;

3)webx会查看template/manager/下有没有manageUser.vm模板,若有,渲染模板;

6.在Screen中获取url的参数

public class ModifyUser {
    @Autowired
    HttpServletRequest request;
    @Autowired
    ClientMapper clientMapper;

    /**
     * 获取modifyUser页面需要用到的信息
     * @param context
     */
    public void modifyUser(Context context){
        long id=Long.parseLong(request.getParameter("id"));
        Client client=clientMapper.selectClientById(id);
        context.put("client",client);
    }
}

6.在Screen中获取form的参数

public class ModifyUser {
    @Autowired
    HttpServletRequest request;
    @Autowired
    ClientMapper clientMapper;

    /**
     * 获取modifyUser页面需要用到的信息
     * @param context
     */
    public void modifyUser(Rundata rundata,TemplateContext context){
        ParameterParser p = rundata.getParameters();
        long clientId=p.getString("clientId");
        context.put("clientId",clientId);
    }
}

7.pipeline处理请求

pipeline控制了请求处理的流程。

<loop>
    <choose>
        <when>
            <!-- 执行带模板的screen,默认有layout。 -->
            <pl-conditions:target-extension-condition extension="null, vm, jsp, jspx" />
            <performAction />
            <performTemplateScreen />
            <renderTemplate />
        </when>
        <when>
            <!-- 执行不带模板的screen,默认无layout。 -->
            <pl-conditions:target-extension-condition extension="do" />
            <performAction />
            <performScreen />
        </when>
        <otherwise>
            <!-- 将控制交还给servlet engine。 -->
            <exit />
        </otherwise>
    </choose>

对于一个具体的url,http://localhost:8081/user/get_user_name.do?userId=10000

    在讲解代码实现之前,对上述的URL路径做下解析,WebX在处理该请求时,会对该路径进行解析,获取对应的Target,用于加载对应的处理方法。这里target后缀是.do,默认的会去查找对应的Screen/Action对象。查找时,对于该路径可能的两种解释是 user下的GetUserName对象或者是User对象的doGetUserName方法。WebX会先按第一中方法解析,失败后换第二种方法解析,如果再找不到对应的方法,报错(这个规则我是从网上看到的,但是对于第一种解析方法,我自己实践没有成功)。在之前的Screen对象中我们看到的对象方法往往只有一个 execute()方法,实际上在调用一个对象时,如果不指定对象的方法名,默认采用的就是execute方法。

1. <analyzeURL> - 分析URL

分析URL的目的是取得target,这里取得的target是collect_list.htm。如果用户访问的URL中并没有提供path信息,通常被理解为:用户想要访问“主页”。AnalyzeURL valve提供了一个可选的参数“homepage”,即是在这种情况下起作用。得到的target为“homepage”。

需要注意的是,target不代表模板名,也不代表类名。Target只是一个抽象的概念 —— 当前页面需要达成的目标。Target可能被后续的valves解释成模板名、类名或者其它东西。

2. 进入<choose> - 多重分支

很明显,“collect_list.htm”满足了第一个<when>所附带的条件:<target-extension-condition extension=" vm, jsp">,意思是target的后缀为“jsp”或为“vm”。

3. <performAction> - 执行action

和其它框架中的action概念不同,在Webx Turbine中,action是用来处理用户提交的表单的。由action变量的值决定处理表单的Action,

若未提供action参数,则跳过该步骤。

4. <performTemplateScreen> - 查找并执行screen。

如果target-extension为”do”,则没有<performTemplateScreen>这个valve,直接执行<performScreen>valve。

这里要用到一个规则:target映射成screen module类名的规则。

假设target为xxx/yyy/zzz,那么Webx Turbine会依次查找下面的screen模块:

screen.xxx.yyy.Zzz,

screen.xxx.yyy.Default,

screen.xxx.Default,

screen.Default。

本次请求的target为collection_list.htm,因此它会尝试查找screen.collection_list类。

如果找到screen类,Webx Turbine就会执行它。Screen类的功能,通常是读取数据库,然后把模板所需要的对象放到TemplateContext中。

如果找不到,也没关系 —— 这就是“页面优先”:一些页面没有业务逻辑,因此不需要screen类,只需要有模板就可以了。

5. <renderTemplate> - 渲染模板

这里用到两个规则:target映射成screen template,以及target映射成layout template。

假设target为xxx/yyy/zzz,那么Webx Turbine会查找下面的screen模板:/templates/screen/xxx/yyy/zzz。Screen模板如果未找到,就会报404 Not Found错误。找到screen模板以后,Webx Turbine还会试着查找下面的layout模板:

/templates/layout/xxx/yyy/zzz

/templates/layout/xxx/yyy/default

/templates/layout/xxx/default

/templates/layout/default

Layout模板如果找不到,就直接渲染screen模板;如果存在,则把渲染screen模板后的结果,嵌入到layout模板中。

Layout模板和screen模板中,都可以调用control。每个页面只有一个screen,却可以有任意多个controls。

6. <breakUnlessTargetRedirected> - 内部重定向

在screen和action中,可以进行“内部重定向”。内部重定向实质上就是由<breakUnlessTargetRedirected>实施的 —— 如果没有重定向标记,就退出;否则循环到<loop>标签。

和外部重定向不同,外部重定向是向浏览器返回一个302或303 response,其中包含Location header,浏览器看到这样的response以后,就会发出第二个请求。而内部重定向发生在pipeline内部,浏览器并不了解内部重定向。











猜你喜欢

转载自blog.csdn.net/qq_30186661/article/details/80450781