WebX实践指南_请求处理(一)

  1. 云栖社区>
  2. 博客>
  3. 正文

WebX实践指南_请求处理(一)

fibojie 2015-11-26 16:03:00 浏览944
展开阅读全文

通过WebX入门指南,相信大家都能开始尝试添加自己的处理页面了。基本上能够完成简单的页面设计了。我们通常说网站是B/S架构的,那这种模式只要掌握前后端的分工和交互,就能游刃有余。因此,本节就从前后端交互方式来说明如何实现高效的代码设计。

前后端交互方式

Http协议请求方法

这一节的详细内容请参考HTTP权威指南,这里只关注WebX中如何实现交互。

网站的前后端交互,都是通过HTTP协议实现的,因此网站的前后端交互也是在HTTP协议下展开的,因此前端的交互模式也受限于通信协议,标准的协议中支持的请求方式有get、post、put、delete、head、options。WebX框架中通过Servlet来处理具体的业务逻辑处理。关于Servlet的知识,后面讲解WebX原理时,再做说明。

Request

  • get: 获取资源,例如html网页、图片、视频等
  • head:本质上和get一样,不过请求中不包含数据信息
  • put: 提交请求,表单不支持,通常要指定资源的地址
  • post: 向服务端提交数据
  • delete: 用于删除资源文件,很少用
  • options: 询问服务端支持的请求方式,请求的结果保存在Allow的协议头中。

Response

每一次HTTP请求,通常都有对应的HTTP响应,消息返回结果通常包含Request处理的状态信息,以及返回结果的格式信息。
返回结果支持的格式有(Context-Type)种类很多,常见的有:
[参考]: http://blog.csdn.net/blueheart20/article/details/45174399

常见的媒体格式类型如下:

text/html : HTML格式
text/plain :纯文本格式      
text/xml :  XML格式
image/gif :gif图片格式    
image/jpeg :jpg图片格式 
image/png:png图片格式

以application开头的媒体格式类型:

application/xhtml+xml :XHTML格式
application/xml     : XML数据格式
application/atom+xml  :Atom XML聚合格式    
application/json    : JSON数据格式
application/pdf       :pdf格式  
application/msword  : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

另外一种常见的媒体格式是上传文件之时使用的:

multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

对一个Http请求,用户只需要通过解析Request请求,并返回处理结果Response。只不过这里的Request和Respose是满足HTTP协议的消息。因此,大家可以简单地把这个过程理解成一个函数调用:

Response get/post/ (Request request);
//把request, response简单地理解成遵循HTTP协议的结构体

WebX中如何处理Request && Response

WebX中处理请求是通过Module来实现的,包括了Screen、Control以及Action三类。具体的实现中是通过HttpServletRequest、HttpServletResponse以及HttpServletSession对象来完成的。当然WebX的实现中,对相关的Servlet进行了其他的处理。后续的文章中再讲解。

WebX中的请求响应处理

WebX中请求响应处理时,之前的使用都是从页面驱动来认识的。现在从Request/Response角度看下。只需要在对应的Module对象中注入Servlet对象就可以使用了。关于对象注入可以去看下Spring相关的知识。
举例说明:
场景:通过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方法。

实现:/screen目录下新建一个User对象,实现getUserName(int userId)方法

public class User {

    @Autowired
    private HttpServletResponse response;
    @Autowired
    private HttpServletRequest request;

    public void doGetUserName() throws IOException {
        String userId = request.getParameter("userId");
        //response.setContentType("text/plain");
        System.out.println("userId is " + userId);
        //do  something

        //response
        PrintWriter writer = response.getWriter();
        writer.write("get user name!!");
    }
}

WebX中的 Screen对象使用说明

Response结果的处理可以通过两种方式,一种方式.do的方式,如上例所示通过response.write()返回处理结果。可以通过response.setContentType(“application/json”);以及response.addHeader(“Cache-Control”);设置对应的来设置返回结果的格式。也可以直接返回结果对象: http://localhost:8081/user/get_user_name.json?userId=10000

public class User {    
    @Autowired
    private HttpServletRequest request;

    public UserResult doGetUserName() throws IOException {
        String userId = request.getParameter("userId");
        //response.setContentType("text/plain");
        System.out.println("userId is " + userId);
        //do  something

        //result
        UserResult userResult = new UserResult();
        userResult.setName("liujie");
        userResult.setStateCode(1);
        userResult.setErrorMsg("success");
        return userResult;
    }
}

class UserResult {
    private int stateCode;
    private String errorMsg;
    private String name;

    public int getStateCode() {
        return stateCode;
    }
    public void setStateCode(int stateCode) {
        this.stateCode = stateCode;
    }
    public String getErrorMsg() {
        return errorMsg;
    }
    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

可以看到以上两种交互中和以往的页面驱动设计是不同的,以往的页面驱动的场景多是获取页面资源,而这两个场景更多的是提交任务,反馈结果,更类似于函数调用。具体的使用中这两种场景多用于获取对象数据,而不是资源文件。

WebX中的Action对象使用说明

Action主要用于表单的处理,本例使用了WebX示例程序中的注册来讲解。一个典型的表单包括了一下几部分:

<form name="input" action="/login.htm" method="post">
    Username: 
    <input type="text" name="user" />
    <input type="submit" value="Submit" />
</form>

对于 WebX中典型的表单:

<form action="$app1Link.setTarget("form/register")" method="post">
    $csrfToken.hiddenField
    <input type="hidden" name="action" value="register_action"/>
    #set ($group = $form.register.defaultInstance)

    <p>Hello, what's your name?</p>
    #if (!$group.name.valid)
        <p>$group.name.message</p>
    #end

    <p>
        <input type="text" name="$group.name.key" value="$!group.name.value"/>
        <input type="submit" name="event_submit_do_register"/>
    </p>
</form>

input action值用于表明action对象, submit按钮中的event_submit_do_register注明处理该表单的方法是doRegister()。$group变量是通过WebX的form service提供的,需要通过表单配置完成。关于WebX服务见后续的详细讲解。接下来设计对应的Action对象,其实他和普通的对象也一样:

public class RegisterAction {
    public void doRegister(@FormGroup("register") Visitor visitor) {
            String name = visitor.getName();
            nav.redirectTo("app1Link").withTarget("form/welcome").
            withParameter("name", name);
    }
}

这里先不关注怎么用,只是说明调用的逻辑关系。调用之后,怎么将结果返回呢?这里只是用了界面跳转,如果开发者想知道添加一个用户是否成功怎么办呢?目前没有发现好的方法,即使可以注入HttpServletResponse。 这个和Action的定位和设计应该是有关系的。Action用于页面表单数据和应用数据的传递,以及页面的跳转,因此在使用时也尽量以这种方式实现。而且在实际的应用中,大家多是以跳转的方式来实现的。比如注册、或者添加新的数据后通过,页面跳转回原页面,刷新页面,从而验证操作的结果,而不需要返回一个成功的标志。这一点不知道读者怎么理解?

各种交互场景下的代码设计

通过对Action、Control、Screen的介绍中,相信基本的使用场景和场合都有所了解了。对于一般的get请求,使用Templates和Screen Module就可以完成基本的页面渲染。对于一些业务数据的处理和返回,数据资源的查找可以通过Screen返回值或者Response Write的方式完成。对于设计数据的增、删、改操作,通过表单实现,这里的缺陷是,如何将操作的结果返回给客户端。
好吧,这里就不再总结各种场景了,上面的讲解中都有涉及到,就不再赘述,读者可以自己再整理整理。通过对交互场景的介绍,前后端的代码交互就有了,接下来就单独看看前后端开发的一些技术。

网友评论

登录后评论
0/500
评论