IT忍者神龟之serfj开源框架

我们在学习一个比较新的框架的时候我们首先要做的是我们去它的官方网站去查看提供的开发文档可是这个矿建是我看见的矿建中文档最少的一个他妈的它,文档太少了官方就有一个例子:

官方地址:http://serfj.sourceforge.net/index.html

参考手册(更新为SerfJ 0.4.0)

目录

1。架构

SerfJ提供了一个MVC架构,但它不会做任何事情的模型,其主要特点是控制器,这些控制器通过REST请求管理。

控制器指应用程序的资源,所以将消息发送到这些资源的方式是通过REST的请求。当一个请求被主的servlet(出席net.sf.serfj.RestServlet),资源(控制器)中搜索,并询问它是否能够回答该请求。在这种情况下,当执行一个动作(一个控制器的方法),和一个响应被提供给客户端。响应可以是一个网页,一个序列化的对象,或HTTP状态代码204,这意味着  没有任何内容

1.1 REST的网址

由于REST请求控制SerfJ的应用程序的流量,这是非常重要的阅读本节。然而,概念解释如下是简单的,所以一切都会很容易理解。

通过SerfJ支持的HTTP方法是:

  • GET:用于概念获取资源信息,网页等
  • POST:概念用于创建新的资源到应用程序中。
  • PUT:概念用于从应用程序更新的资源。
  • 删除:用于在概念上从应用程序中删除资源。

例如,如果你想呈现一个页面,有更新或创建资源的形式,你需要发送一个  GET  请求,而不是一个  PUT  请求。但提交按钮(其目的是更新一些信息)将发送一个  PUT  请求。

该模式对REST请求是:

  • /帐户?QUERY_STRING
  • /帐号/标识符?QUERY_STRING
  • /帐号/非STANDAR行动?QUERY_STRING
  • /帐号/标识符/编辑?QUERY_STRING
  • /帐号/标识符/ newResource?QUERY_STRING
  • /帐号/标识符/非STANDAR行动?QUERY_STRING

请注意,资源的名称必须是复数,且  标识符  必须以数字开头。但SerfJ能够解析与嵌套的资源的URL:

  • /银行/标识符/帐户?QUERY_STRING
  • /银行/标识符/帐号/标识符?QUERY_STRING
  • /银行/标识符/帐号/非STANDAR行动?QUERY_STRING
  • /银行/标识符/帐号/标识符/编辑?QUERY_STRING
  • /银行/标识符/帐号/标识符/ newResource?QUERY_STRING
  • /银行/标识符/帐号/标识符/非STANDAR行动?QUERY_STRING

如果你有一个扩展完成您的网址,那么结果将不会是一个页面,但序列化对象。因此,根据所使用的扩展,可以收到序列化为JSON,XML或使一个对象:

  • / accounts.xml?QUERY_STRING
  • /帐号/ identifier.json?QUERY_STRING
  • /帐号/非STANDAR-action.pdf?QUERY_STRING
  • /帐号/标识符/非STANDAR-action.txt?QUERY_STRING

1.2标准的URL

根据HTTP的方法中使用的相同的URL将调用不同的控制器的方法:

HTTP方法 网址 控制器的方法 视图 意思
GET /账户 指数() 指数 显示每个资源
POST /账户 创建() 创建 创建新的资源
GET /帐号/ 1 秀() 节目 显示一个资源ID为1
PUT /帐号/ 1 更新() 更新 ID为1更新资源
DELETE /帐号/ 1 删除() 删除 删除资源ID为1
GET / accounts/1/newResource newResource() 显示一个表单来创建新的资源
GET / accounts/1/edit 编辑() 编辑 显示一个表单,ID为1更新资源

2。控制器

控制器是在SerfJ主角,REST请求分派给他们,他们回答这些请求。答案可能是一个网页,一个序列化的对象,或没有(一个HTTP代码)。

有两种方法写一个控制器(会有更多的在未来SerfJ版本),延长  net.sf.serfj.RestController  类,甚至写一个JavaBean。最后一种情况是怪异的,因为控制器将无法做到像从请求中获取参数的一些行动,或重定向到另一个页面,或者对象发送到JSP页面。

目前,延长  RestController  类是写一个控制器的最佳方式。方法是参加请求musn't有参数,但可以返回对象并抛出异常。例如,如果我们需要一个控制器来参加请求  /账户,我们必须写一个类是这样的:

1
2
公共 账户 扩展 RestController {
}

2.1注释

有几个注解,告诉哪些HTTP方法是通过一个控制器的方法接受的框架。

  • @ GET:方法只接受GET请求。
  • @ POST:方法只接受POST请求。
  • @ PUT:方法只接受PUT请求。
  • @ DELETE:方法只接受DELETE请求。

此外,还有另外一个,  @ DoNotRenderPage  ,告诉该执行器的方法后,没有页面将被渲染的框架,但一个HTTP 204代码将得到解答。因为它返回一个对象的方法不会呈现一个页面,因此,它并不需要与被注解  @ DoNotRenderPage。然而,一个不返回任何东西(一个方法  无效  的方法),但开发商不希望呈现一个页面作为一个结果,也必须注明。

从请求中获取2.2参数

Obiously,我们写之前不会做任何事情的类,它不会回答任何请求。让我们写更多的东西。如果我们需要从一个帐户(PUT /账户/ 1)更新一些信息的方法,我们可以写一个这样的方法:

1
2
3
4
5
6
7
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         字符串帐号ID = 这个 的getId();
         / /做一些更新帐户
     }
}

我们看到,该方法可以从与请求恢复帐户的标识符  的getId(字符串)  方法。让我们看看我们如何让别人标识符,如果要求有嵌套资源(PUT / banks/1/accounts/2)。

1
2
3
4
5
6
7
8
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         字符串帐号ID = 这个 的getId();
         串bankId = 这个 的getId( “ 银行” );
         / /做一些从银行更新帐户收到
     }
}

如果你把一些参数在请求中,该方法可以得到他们。PARAMS能在一个查询字符串,或在该请求。

1
2
3
4
5
6
7
8
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         字符串帐号ID = 这个 的getId();
         串someInfo = 这个 getStringParam( “some_info_param_name” );
         / /做一些更新帐户
     }
}

但怎么样receiveing​​是不是字符串对象?

1
2
3
4
5
6
7
8
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         字符串帐号ID = 这个 的getId();
         串someInfo = 这个 getStringParam( “some_info_param_name” );
         资产负债余额=(平衡) getParam( “ 平衡” ));
     }
}

2.3参数发送到响应

好了,现在我们知道了如何从请求获取参数,但有时我们需要将对象发送到一个JSP,例如。显然,这些对象必须实现  java.io.Serializable接口

1
2
3
4
5
6
7
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         帐户帐户= / /一些代码来得到一个帐户
         这个 。putParam( “my_object_param_name” ,账号);
     }
}

这将是非常常见的方法返回的对象。正如我们所看到的  第1.1节,这些方法必须调用与扩展下场休息的URL。该扩展会指向哪些序列必须使用作出反应的框架。SerfJ提供了三种不同的序列化(XML,JSON或Base64)三种不同的扩展名(。XML,。json的。Base64编码),但开发人员可以编写自己的序列化(见  第3节)。

例如,响应URL类似的方法  / accounts/1/balance.xml  可以写成两种方式。让我们来看看这样做的第一种方式:

1
2
3
4
5
6
7
公共 账户 扩展 RestController {
     @ GET
     公共 资产负债余额(){
         资产负债余额= 新的 平衡();
         返回 平衡;
     }
}

此方法将总是试图返回一个对象,该对象如何被序列取决于所使用的扩展。但可能是我们需要返回一个对象接收到一个扩展时,或在其他情况下渲染页面的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
公共 账户 扩展 RestController {
     @ GET
     公共 无效 余额(){
         资产负债余额= 新的 平衡();
         如果 这个 。getSerializer()!= ){
             这个 。连载(平衡);
         } 其他 {
             / /这是可选的,我们需要它,只有当我们希望将对象发送到页
             这个 。putParam( “ 平衡” ,平衡);
             这个 。renderPage( “ 平衡” );
         }
     }
}

在这种情况下,如果存在序列的任何对象,该框架将它写在响应中。

2.4渲染网页

控制器的方法,他们的执行后总是会呈现一个页面,除非该方法有一个返回对象或者是标注了  @ DoNotRenderPage。该页面会尝试呈现必须是一个子目录,其名称是资源的名称,还必须在规定的目录下  views.directory  属性(默认情况下它的  观点)。页面必须具备的。的jsp,。的html或。htm扩展名。例如:

调节器 方法 视图
帐户 无效指数() views.directory /帐号/指数
帐户 无效的show() views.directory /帐号/节目
帐户 无效newResource() views.directory /帐号/新
银行 无效的编辑() views.directory /银行/编辑
汽车 无效更新() views.directory /车/更新
帐户 无效的create() views.directory /帐号/创建
帐户 无效删除() views.directory /帐号/删除
帐户 无效myMethod的() views.directory /帐号/ myMethod的
帐户 对象myMethod的() 返回一个序列化对象
帐户 @ DoNotRenderPage无效myMethod的() 返回一个HTTP 204代码

这就是框架呈现默认的页面,但有一些方法可以使其他网页。有三种方法来渲染页面:

  • renderPage() :渲染的默认页。
  • renderPage(字符串页):从相同的资源(帐户,银行等)呈现一个具体页面。传递给该方法的页面可以有一个延伸,或没有。如果它不具有扩展名,SerfJ将寻找STANDAR扩展名(。的jsp,。的html,。HTM)。
  • renderPage(字符串资源,弦乐页):渲染来自其他资源的页面。也就是说,账户的控制器能够使从银行或其他资源的网页。

2.5序列化

URL可能会结束与不同的扩展名。默认扩展名是  。的xml。json的。Base64并。文件。如果一个URL以一个扩展名结尾,该框架将试图在序列化格式的响应使用串行器(读指定的  第3条)。一些例子:

HTTP方法 网址 控制器的方法 视图 意思
GET / accounts.xml 指数() 不适用 发送的每个XML中占序列化
GET / accounts/1.xml 秀() 不适用 发送帐户1中的XML
GET / documents/1.file 秀() 不适用 用ID 1下载文件
GET / songs/1.mp3 玩() 不适用 下载一首MP3歌曲ID为1(你需要实现扩展FileSerializer一个Mp3Serializer)
正如你看到的,只有GET方法具有一定的意义当分机使用。

2.6文件服务

由于版本0.4.0可以使用扩展来提供文件  。文件  的请求。但你必须设置该文件的位置,以获得SerfJ阅读它。

1
2
3
4
5
6
7
@ GET
@ DoNotRenderPage
公共 无效 下载(){
     / /设置文件位置
     这个 。getResponseHelper()setFile(。 文件( “path_to_a_file / avatar_sabreman.png” ));
     / / SerfJ将下载的文件
}

默认的实现设置内容类型  的应用程序/ octect流  ,所以如果你需要发送一个不同的使用相同的文件扩展名,则必须将内容以及文件类型:

1
2
3
4
5
6
7
8
@ GET
@ DoNotRenderPage
公共 无效 下载(){
     / /设置文件位置
     这个 。getResponseHelper()setFile(。 文件( “path_to_a_file / avatar_sabreman.png” ));
     。getResponseHelper()的setContentType( “audio/mpeg3” );
     / / SerfJ将下载的文件
}

在另一方面,如果你想使用一个不同的扩展名等。MP3,。TXT,。PDF或等等,您必须实现自己的文件序列化。例如,对于mp3扩展的实现将是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
net.sf.serfj.serfj_sample.serializers;
 
进口 net.sf.serfj.serializers.FileSerializer;
 
/ **
  *串行的MP3音频文件。<BR>
  * /
公共 Mp3Serializer 扩展 FileSerializer {
     / **
      *将在响应中使用的内容类型。
      * /
     公共 字符串的getContentType(){
         返回 “audio/mpeg3” ;
     }
}

2.7访问  的javax  资源

虽然SerfJ试图避 ​​免该控制器具有依赖关系  的javax.servlet  包,有时显影剂可以通过框架的功能限制,所以作为0.4.0版本,net.sf.serfj.RestController  有一种方法来access  javax.servlet.ServletContextjavax.servlet.http.HttpServletRequest  and  javax.servlet.http.HttpServletResponse .

1
2
3
ServletContext的上下文= 这个 getResponseHelper()的getContext();
HttpServletRequest的请求= 这个 getResponseHelper()的GetRequest();
HttpServletResponse的响应= 这个 getResponseHelper()的GetResponse();

3,串行器

当一个REST请求到达时,如果有查询字符串前申请延期,能够序列化的响应序列化搜索(读  第5节  ,以了解如何资源搜索)。SerfJ提供序列化的XML,JSON,基地64和文件(。xml的。json的。一个base64或。文件扩展名),但开发人员可以让自己拥有,并且可以使别人怎样对待 ​​不同的扩展名。

这很容易开发新的序列化器,你只需要实现  net.sf.serfj.serializers.ObjectSerializer  接口,就是这么简单,它不需要对不属于自己的Javadoc更多的解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
net.sf.serfj.serializers;
 
/ **
  *为序列化接口。
  *
  * @作者爱德华多·亚涅斯
  * /
公共 接口 ObjectSerializer {
     / **
      *序列化一个对象,该实现需要的格式。
      *
      * @参数对象
      *对象序列化。
      * @返回与序列化的对象的String。
      * /
     公共 字符串序列化(Object对象);
 
     / **
      *从实施要求的格式反序列化一个对象
      * Java对象。
      *
      * @参数字符串
      *反序列化对象的字符串表示形式。
      * @返回一个对象。
      * /
     公共 对象的反序列化(字符串字符串);
 
     / **
      *将在响应中使用的内容类型。
      * /
     公共 字符串的getContentType();
}

下载文件有一个net.serfj.serializers.FileSerializer,供应的任何文件,“应用程序/ octect流”的内容类型。您也可以扩展类并重写FileSerializer.getContentType()方法定义你自己的文件的序列化。例如,一个序列化服务的MP3文件可以是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
net.sf.serfj.serfj_sample.serializers;
 
进口 net.sf.serfj.serializers.FileSerializer;
 
/ **
  *串行的MP3音频文件。<BR>
  * /
公共 Mp3Serializer 扩展 FileSerializer {
     / **
      *将在响应中使用的内容类型。
      * /
     公共 字符串的getContentType(){
         返回 “audio/mpeg3” ;
     }
}

类的名称必须与序列化是为扩展名,其次是资源的名称,并且必须以  串行器

  • XmlBankSerializer:新的实现序列化库控制器的响应XML。
  • JsonBookSerializer:新的实现序列化图书控制器的回应到JSON。
  • PdfBookSerializer:一个实现序列化图书控制器的响应为PDF(从net.sf.serfj.FileSerializer延长)。

另一种选择是有内'package.hierarchy.serializers'包中的序列化。那么这个类的名称必须与序列化是为扩展名,而且必须以  串行器。这种方式可以实现通用串行器为每一个模型:

  • package.hierarchy.serializers.XmlSerializer:新的实现序列化到XML的任何回应。
  • package.hierarchy.serializers.JsonSerializer:新的实现序列化到JSON任何反应。
  • package.hierarchy.serializers.PdfSerializer:一个实现序列化到PDF(从net.sf.serfj.FileSerializer延长)的任何回应。

4。配置

该框架试图遵循的理念  约定优于配置,所以使用它几乎不需要配置它。当然这需要进行配置,但只有一点点。但是,如果开发人员想要得到它运行的更好,他们可以为了避免SerfJ做预测,以找到一些资源,建立了几个配置属性。

SerfJ只有一个配置文件  serfj.properties  ,有是在  / config中  的目录内  的类路径。它只需要一个  main.package  属性生效。此属性必须指向该软件包SerfJ将寻找控制器和序列化,但它并不意味着所有的控制器和串行必须在那个包,顺便框架查找资源在下一节解释。

4.1配置属性

  • main.package:主包的地方寻找类(控制器,串行)。默认值是  net.sf.serfj
  • views.directory:目录来寻找网页。默认值为  意见
  • package.style:该方法的框架会寻找资源。有四个可能的值:  功能/功能,  FUNCTIONAL_BY_MODEL / functional_by_model,  型号/型号  或  关闭。如果该值为  OFF,那么它是相同的,因为它是未声明。
  • alias.controllers.package:用作控制器封装别名。它追加到  main.package  属性值时包款式  功能  或  FUNCTIONAL_BY_MODEL。默认值是控制器
  • alias.serializers.package:作为序列化封装别名。它追加到  main.package  属性值时包款式  功能  或  FUNCTIONAL_BY_MODEL。默认值是序列化
  • suffix.controllers:后缀附加到控制器的类名。默认值是  关闭,所以没有后缀使用。
  • suffix.serializers:后缀追加到串行的类名。默认值是  序列化

在这里,您有一个配置文件的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#主包的地方寻找类(控制器,序列化)
main.package = net.sf.serfj.test
 
#与JSP,HTML等目录..
views.directory =的src /测试/ web应用/ WEB-INF /意见
 
#包的风格。
#有3种款式:
#功能/功能
#在同一个包按功能类别所有
#net.sf.serfj.controllers.Bank
#net.sf.serfj.controllers.Order
#net.sf.serfj.serializers.JsonBankSerializer
#net.sf.serfj.serializers.XmlOrderSerializer
#FUNCTIONAL_BY_MODEL / functional_by_model
#类通过模型和功能
#net.sf.serfj.bank.controllers.Bank
#net.sf.serfj.bank.serializers.JsonSerializer
#net.sf.serfj.order.controllers.Order
#net.sf.serfj.order.serializers.JsonSerializer
#MODEL /型号
#在同一个包通过模型中的所有类
#net.sf.serfj.bank.Bank
#net.sf.serfj.bank.JsonSerializer
#net.sf.serfj.order.Order
#net.sf.serfj.order.JsonSerializer
#关/关/留空
#留空或不定义它。该库将尝试不同的方式找到
#类中的顺序如下:功能,FUNCTIONAL_BY_MODEL,型号
#这种方法效率较低,所以最好defininig一些之一。
#packages.style =
 
#你可以改变控制器的程序包的名称(如果有)。
#默认值是“控制器”。
#alias.controllers.package =控制器
#alias.controllers.package = CTRL
#alias.controllers.package = controllers.main
 
#您可以更改序列化'包的名称(如果有)。
#默认值是“序列化”。
#alias.serializers.package = utils的
#alias.serializers.package = utils.serializers
 
#使用后缀
#如果你不希望任何后缀设置为OFF /关的值
#对于控制器默认为“关”
#suffix.controllers =控制器
命名net.sf.serfj.bank.BankController代替net.sf.serfj.bank.Bank#控制器类必须
#对于序列化程序默认的是“串行”
#suffix.serializer =

5,寻找资源

有三种方式,其中SerfJ寻找资源,它们被命名为:

  • 功能。
  • 功能由模型。
  • 按产品型号。

如果没有人在配置文件中定义,那么框架使用的顺序来查找资源各一台。因此,如果开发者想告诉SerfJ如何必须寻找资源,他必须定义  packages.style  财产。

5.1功能风格

如果它正在寻找一个控制器,然后将合格的类名称将是:

main.package +“。” + alias.controllers.package +“。” +资本化利息(被单数(资源名称))+ suffix.controllers。

所以有这样的配置:

  • main.package:net.sf.serfj.tests
  • alias.controllers.package没有定义。默认值是  控制器
  • suffix.controllers:Ctrl键。默认值是一个空字符串。
  • 来源:银行

该框架将寻找下一个限定名的控制器:

net.sf.serfj.tests.controllers.BankCtrl

如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,文件等)。例如,具有这种配置:

  • main.package:net.sf.serfj.tests
  • alias.serializers.package没有定义。默认值是  序列化
  • suffix.serializers:没有定义。默认值是  序列化

寻找一个PDF序列化账目,限定类名称将是:

net.sf.serfj.tests.serializers.PdfAccountSerializer

寻找一个PDF序列化什么型号,限定类名称将是:

net.sf.serfj.tests.serializers.PdfSerializer

注:通用串行器只能够​​被功能性的风格中定义。

5.2功能由模型风格

在这种策略中,资源名称和被单数追加到  main.package  财产。如果它正在寻找一个控制器,然后将合格的类名称将是:

main.package +“。” +被单数(资源名称)+“。” + alias.controllers.package +“。” +资本化利息(被单数(资源名称))+ suffix.controllers。

所以有这个配置属性定义:

  • main.package:net.sf.serfj.tests
  • alias.controllers.package:CTRL
  • suffix.controllers:没有定义。默认值是一个空字符串。
  • 来源:银行

该框架将寻找下一个限定名的控制器:

net.sf.serfj.tests.bank.ctrl.Bank

如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,Base64的,等等)。例如,具有这种配置的属性定义如下:

  • main.package:net.sf.serfj.tests
  • alias.serializers.package:串行
  • suffix.serializers:没有定义。默认值是  序列化

寻找一个PDF序列化账目,限定类名称将是:

net.sf.serfj.tests.account.serial.PdfAccountSerializer

5.3按型号款式

在这种策略中,资源名称和被单数追加到  main.package  财产,但  别名  不使用。如果它正在寻找一个控制器,然后将合格的类名称将是:

main.package +“。” +被单数(资源名称)+“。” +资本化利息(被单数(资源名称))+ suffix.controllers。

所以有这个配置属性定义:

  • main.package:net.sf.serfj.tests
  • suffix.controllers:没有定义。默认值是一个空字符串。
  • 来源:银行

该框架将寻找下一个限定名的控制器:

net.sf.serfj.tests.bank.Bank

如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,Base64的,等等)。例如,具有这种配置:

  • main.package:net.sf.serfj.tests
  • suffix.serializers:没有定义。默认值是  序列化

寻找一个CSV序列化账目,限定类名称将是:

net.sf.serfj.tests.account.CsvAccountSerializer

6。SerfJ的客户

SerfJ提供了一个类  net.sf.serfj.client.Client  为了做REST请求。它有四个  公共  方法(GET,POST,PUT和DELETE)用来做要求。该接口是非常简单的,所以JavaDoc应该足够使用这个类。

中文对照:

参考手册(更新为SerfJ 0.4.0)

目录

1。架构

SerfJ提供了一个MVC架构,但它不会做任何事情的模型,其主要特点是控制器,这些控制器通过REST请求管理。

控制器指应用程序的资源,所以将消息发送到这些资源的方式是通过REST的请求。当一个请求被主的servlet(出席net.sf.serfj.RestServlet),资源(控制器)中搜索,并询问它是否能够回答该请求。在这种情况下,当执行一个动作(一个控制器的方法),和一个响应被提供给客户端。响应可以是一个网页,一个序列化的对象,或HTTP状态代码204,这意味着  没有任何内容

1.1 REST的网址

由于REST请求控制SerfJ的应用程序的流量,这是非常重要的阅读本节。然而,概念解释如下是简单的,所以一切都会很容易理解。

通过SerfJ支持的HTTP方法是:

  • GET:用于概念获取资源信息,网页等
  • POST:概念用于创建新的资源到应用程序中。
  • PUT:概念用于从应用程序更新的资源。
  • 删除:用于在概念上从应用程序中删除资源。

例如,如果你想呈现一个页面,有更新或创建资源的形式,你需要发送一个  GET  请求,而不是一个  PUT  请求。但提交按钮(其目的是更新一些信息)将发送一个  PUT  请求。

该模式对REST请求是:

  • /帐户?QUERY_STRING
  • /帐号/标识符?QUERY_STRING
  • /帐号/非STANDAR行动?QUERY_STRING
  • /帐号/标识符/编辑?QUERY_STRING
  • /帐号/标识符/ newResource?QUERY_STRING
  • /帐号/标识符/非STANDAR行动?QUERY_STRING

请注意,资源的名称必须是复数,且  标识符  必须以数字开头。但SerfJ能够解析与嵌套的资源的URL:

  • /银行/标识符/帐户?QUERY_STRING
  • /银行/标识符/帐号/标识符?QUERY_STRING
  • /银行/标识符/帐号/非STANDAR行动?QUERY_STRING
  • /银行/标识符/帐号/标识符/编辑?QUERY_STRING
  • /银行/标识符/帐号/标识符/ newResource?QUERY_STRING
  • /银行/标识符/帐号/标识符/非STANDAR行动?QUERY_STRING

如果你有一个扩展完成您的网址,那么结果将不会是一个页面,但序列化对象。因此,根据所使用的扩展,可以收到序列化为JSON,XML或使一个对象:

  • / accounts.xml?QUERY_STRING
  • /帐号/ identifier.json?QUERY_STRING
  • /帐号/非STANDAR-action.pdf?QUERY_STRING
  • /帐号/标识符/非STANDAR-action.txt?QUERY_STRING

1.2标准的URL

根据HTTP的方法中使用的相同的URL将调用不同的控制器的方法:

HTTP方法 网址 控制器的方法 视图 意思
GET /账户 指数() 指数 显示每个资源
POST /账户 创建() 创建 创建新的资源
GET /帐号/ 1 秀() 节目 显示一个资源ID为1
PUT /帐号/ 1 更新() 更新 ID为1更新资源
DELETE /帐号/ 1 删除() 删除 删除资源ID为1
GET / accounts/1/newResource newResource() 显示一个表单来创建新的资源
GET / accounts/1/edit 编辑() 编辑 显示一个表单,ID为1更新资源

2。控制器

控制器是在SerfJ主角,REST请求分派给他们,他们回答这些请求。答案可能是一个网页,一个序列化的对象,或没有(一个HTTP代码)。

有两种方法写一个控制器(会有更多的在未来SerfJ版本),延长  net.sf.serfj.RestController  类,甚至写一个JavaBean。最后一种情况是怪异的,因为控制器将无法做到像从请求中获取参数的一些行动,或重定向到另一个页面,或者对象发送到JSP页面。

目前,延长  RestController  类是写一个控制器的最佳方式。方法是参加请求musn't有参数,但可以返回对象并抛出异常。例如,如果我们需要一个控制器来参加请求  /账户,我们必须写一个类是这样的:

1
2
公共 账户 扩展 RestController {
}

2.1注释

有几个注解,告诉哪些HTTP方法是通过一个控制器的方法接受的框架。

  • @ GET:方法只接受GET请求。
  • @ POST:方法只接受POST请求。
  • @ PUT:方法只接受PUT请求。
  • @ DELETE:方法只接受DELETE请求。

此外,还有另外一个,  @ DoNotRenderPage  ,告诉该执行器的方法后,没有页面将被渲染的框架,但一个HTTP 204代码将得到解答。因为它返回一个对象的方法不会呈现一个页面,因此,它并不需要与被注解  @ DoNotRenderPage。然而,一个不返回任何东西(一个方法  无效  的方法),但开发商不希望呈现一个页面作为一个结果,也必须注明。

从请求中获取2.2参数

Obiously,我们写之前不会做任何事情的类,它不会回答任何请求。让我们写更多的东西。如果我们需要从一个帐户(PUT /账户/ 1)更新一些信息的方法,我们可以写一个这样的方法:

1
2
3
4
5
6
7
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         串 帐号ID = 这个 。的getId();
         / / 做一些事来更新帐户
     }
}

我们看到,该方法可以从与请求恢复帐户的标识符  的getId(字符串)  方法。让我们看看我们如何让别人标识符,如果要求有嵌套资源(PUT / banks/1/accounts/2)。

1
2
3
4
5
6
7
8
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         串 帐号ID = 这个 。的getId();
         串 bankId = 这个 。的getId( “ 银行” );
         / / 做一些事,从收到的银行更新帐户
     }
}

如果你把一些参数在请求中,该方法可以得到他们。PARAMS能在一个查询字符串,或在该请求。

1
2
3
4
5
6
7
8
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         串 帐号ID = 这个 。的getId();
         串 someInfo = 这个 getStringParam( “some_info_param_name” );
         / / 做一些事来更新帐户
     }
}

但怎么样receiveing​​是不是字符串对象?

1
2
3
4
5
6
7
8
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         串 帐号ID = 这个 。的getId();
         串 someInfo = 这个 getStringParam( “some_info_param_name” );
         平衡 余额=(平衡) getParam( “ 平衡” ));
     }
}

2.3参数发送到响应

好了,现在我们知道了如何从请求获取参数,但有时我们需要将对象发送到一个JSP,例如。显然,这些对象必须实现  java.io.Serializable接口

1
2
3
4
5
6
7
公共 账户 扩展 RestController {
     @ PUT
     公共 无效 updateAccount(){
         帐户 账户= / / 一些代码来得到一个帐户
         这个 。putParam( “my_object_param_name” , 户口);
     }
}

这将是非常常见的方法返回的对象。正如我们所看到的  第1.1节,这些方法必须调用与扩展下场休息的URL。该扩展会指向哪些序列必须使用作出反应的框架。SerfJ提供了三种不同的序列化(XML,JSON或Base64)三种不同的扩展名(。XML,。json的。Base64编码),但开发人员可以编写自己的序列化(见  第3节)。

例如,响应URL类似的方法  / accounts/1/balance.xml  可以写成两种方式。让我们来看看这样做的第一种方式:

1
2
3
4
5
6
7
公共 账户 扩展 RestController {
     @ GET
     公共 资产负债余额(){
         平衡 余额= 新的 平衡();
         返回 平衡;
     }
}

此方法将总是试图返回一个对象,该对象如何被序列取决于所使用的扩展。但可能是我们需要返回一个对象接收到一个扩展时,或在其他情况下渲染页面的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
公共 账户 扩展 RestController {
     @ GET
     公共 无效 余额(){
         平衡 余额= 新的 平衡();
         如果 这个 。getSerializer() != ) {
             这个 。连载(平衡);
         } 其他 {
             / / 这是可选的,我们需要它,只有当我们希望将对象发送到页
             这个 。putParam( “ 平衡” , 平衡);
             这个 。renderPage( “ 平衡” );
         }
     }
}

在这种情况下,如果存在序列的任何对象,该框架将它写在响应中。

2.4渲染网页

控制器的方法,他们的执行后总是会呈现一个页面,除非该方法有一个返回对象或者是标注了  @ DoNotRenderPage。该页面会尝试呈现必须是一个子目录,其名称是资源的名称,还必须在规定的目录下  views.directory  属性(默认情况下它的  观点)。页面必须具备的。的jsp,。的html或。htm扩展名。例如:

调节器 方法 视图
帐户 无效指数() views.directory /帐号/指数
帐户 无效的show() views.directory /帐号/节目
帐户 无效newResource() views.directory /帐号/新
银行 无效的编辑() views.directory /银行/编辑
汽车 无效更新() views.directory /车/更新
帐户 无效的create() views.directory /帐号/创建
帐户 无效删除() views.directory /帐号/删除
帐户 无效myMethod的() views.directory /帐号/ myMethod的
帐户 对象myMethod的() 返回一个序列化对象
帐户 @ DoNotRenderPage无效myMethod的() 返回一个HTTP 204代码

这就是框架呈现默认的页面,但有一些方法可以使其他网页。有三种方法来渲染页面:

  • renderPage() :渲染的默认页。
  • renderPage(字符串页):从相同的资源(帐户,银行等)呈现一个具体页面。传递给该方法的页面可以有一个延伸,或没有。如果它不具有扩展名,SerfJ将寻找STANDAR扩展名(。的jsp,。的html,。HTM)。
  • renderPage(字符串资源,弦乐页):渲染来自其他资源的页面。也就是说,账户的控制器能够使从银行或其他资源的网页。

2.5序列化

URL可能会结束与不同的扩展名。默认扩展名是  。的xml。json的。Base64并。文件。如果一个URL以一个扩展名结尾,该框架将试图在序列化格式的响应使用串行器(读指定的  第3条)。一些例子:

HTTP方法 网址 控制器的方法 视图 意思
GET / accounts.xml 指数() 不适用 发送的每个XML中占序列化
GET / accounts/1.xml 秀() 不适用 发送帐户1中的XML
GET / documents/1.file 秀() 不适用 用ID 1下载文件
GET / songs/1.mp3 玩() 不适用 下载一首MP3歌曲ID为1(你需要实现扩展FileSerializer一个Mp3Serializer)
正如你看到的,只有GET方法具有一定的意义当分机使用。

2.6文件服务

由于版本0.4.0可以使用扩展来提供文件  。文件  的请求。但你必须设置该文件的位置,以获得SerfJ阅读它。

1
2
3
4
5
6
7
@ GET
@ DoNotRenderPage
公共 无效 下载(){
     / / 设置文件位置
     这个 。getResponseHelper()setFile(。 文件( “path_to_a_file / avatar_sabreman.png” ));
     / / SerfJ将下载的文件
}

默认的实现设置内容类型  的应用程序/ octect流  ,所以如果你需要发送一个不同的使用相同的文件扩展名,则必须将内容以及文件类型:

1
2
3
4
5
6
7
8
@ GET
@ DoNotRenderPage
公共 无效 下载(){
     / / 设置文件位置
     这个 。getResponseHelper()setFile(。 文件( “path_to_a_file / avatar_sabreman.png” ));
     。getResponseHelper()的setContentType( “audio/mpeg3” );
     / / SerfJ将下载的文件
}

在另一方面,如果你想使用一个不同的扩展名等。MP3,。TXT,。PDF或等等,您必须实现自己的文件序列化。例如,对于mp3扩展的实现将是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
net.sf.serfj.serfj_sample.serializers;
 
进口 net.sf.serfj.serializers.FileSerializer;
 
/ **
  * 串行器支持MP3音频文件。<BR>
  * /
公共 Mp3Serializer 扩展 FileSerializer {
     / **
      * 内容类型将在响应中使用。
      * /
     公共 字符串的getContentType(){
         返回 “audio/mpeg3” ;
     }
}

2.7访问  的javax  资源

虽然SerfJ试图避 ​​免该控制器具有依赖关系  的javax.servlet  包,有时显影剂可以通过框架的功能限制,所以作为0.4.0版本,net.sf.serfj.RestController  有一种方法来access  javax.servlet.ServletContext ,  javax.servlet.http.HttpServletRequest  and javax.servlet.http.HttpServletResponse .

1
2
3
ServletContext的 上下文= 这个 getResponseHelper()的getContext();
HttpServletRequest的 要求= 这个 getResponseHelper()的GetRequest();
HttpServletResponse中 响应= 这个 getResponseHelper()的GetResponse();

3,串行器

当一个REST请求到达时,如果有查询字符串前申请延期,能够序列化的响应序列化搜索(读  第5节  ,以了解如何资源搜索)。SerfJ提供序列化的XML,JSON,基地64和文件(。xml的。json的。一个base64或。文件扩展名),但开发人员可以让自己拥有,并且可以使别人怎样对待 ​​不同的扩展名。

这很容易开发新的序列化器,你只需要实现  net.sf.serfj.serializers.ObjectSerializer  接口,就是这么简单,它不需要对不属于自己的Javadoc更多的解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
net.sf.serfj.serializers;
 
/ **
  * 接口串行器。
  *
  * @作家爱德华多·亚涅斯
  * /
公共 接口 ObjectSerializer {
     / **
      * 序列化一个对象,该实现需要的格式。
      *
      * @参数对象
      *            对象序列化。
      * @返回一个String与序列化的对象。
      * /
     公共 字符串序列化(Object对象);
 
     / **
      * 从实施要求的格式反序列化对象
      * Java对象。
      *
      * @参数字符串
      *            反序列化对象的字符串表示形式。
      * @返回一个对象。
      * /
     公共 对象的反序列化(字符串字符串);
 
     / **
      * 内容类型将在响应中使用。
      * /
     公共 字符串的getContentType();
}

下载文件有一个net.serfj.serializers.FileSerializer,供应的任何文件,“应用程序/ octect流”的内容类型。您也可以扩展类并重写FileSerializer.getContentType()方法定义你自己的文件的序列化。例如,一个序列化服务的MP3文件可以是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
net.sf.serfj.serfj_sample.serializers;
 
进口 net.sf.serfj.serializers.FileSerializer;
 
/ **
  * 串行器支持MP3音频文件。<BR>
  * /
公共 Mp3Serializer 扩展 FileSerializer {
     / **
      * 内容类型将在响应中使用。
      * /
     公共 字符串的getContentType(){
         返回 “audio/mpeg3” ;
     }
}

类的名称必须与序列化是为扩展名,其次是资源的名称,并且必须以  串行器

  • XmlBankSerializer:新的实现序列化库控制器的响应XML。
  • JsonBookSerializer:新的实现序列化图书控制器的回应到JSON。
  • PdfBookSerializer:一个实现序列化图书控制器的响应为PDF(从net.sf.serfj.FileSerializer延长)。

另一种选择是有内'package.hierarchy.serializers'包中的序列化。那么这个类的名称必须与序列化是为扩展名,而且必须以  串行器。这种方式可以实现通用串行器为每一个模型:

  • package.hierarchy.serializers.XmlSerializer:新的实现序列化到XML的任何回应。
  • package.hierarchy.serializers.JsonSerializer:新的实现序列化到JSON任何反应。
  • package.hierarchy.serializers.PdfSerializer:一个实现序列化到PDF(从net.sf.serfj.FileSerializer延长)的任何回应。

4。配置

该框架试图遵循的理念  约定优于配置,所以使用它几乎不需要配置它。当然这需要进行配置,但只有一点点。但是,如果开发人员想要得到它运行的更好,他们可以为了避免SerfJ做预测,以找到一些资源,建立了几个配置属性。

SerfJ只有一个配置文件  serfj.properties  ,有是在  / config中  的目录内  的类路径。它只需要一个  main.package  属性生效。此属性必须指向该软件包SerfJ将寻找控制器和序列化,但它并不意味着所有的控制器和串行必须在那个包,顺便框架查找资源在下一节解释。

4.1配置属性

  • main.package:主包的地方寻找类(控制器,串行)。默认值是  net.sf.serfj
  • views.directory:目录来寻找网页。默认值为  意见
  • package.style:该方法的框架会寻找资源。有四个可能的值:  功能/功能,  FUNCTIONAL_BY_MODEL / functional_by_model,  型号/型号  或  关闭。如果该值为  OFF,那么它是相同的,因为它是未声明。
  • alias.controllers.package:用作控制器封装别名。它追加到  main.package  属性值时包款式  功能  或  FUNCTIONAL_BY_MODEL。默认值是控制器
  • alias.serializers.package:作为序列化封装别名。它追加到  main.package  属性值时包款式  功能  或  FUNCTIONAL_BY_MODEL。默认值是序列化
  • suffix.controllers:后缀附加到控制器的类名。默认值是  关闭,所以没有后缀使用。
  • suffix.serializers:后缀追加到串行的类名。默认值是  序列化

在这里,您有一个配置文件的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 主包的地方寻找类(控制器,序列化)
main.package = net.sf.serfj.test
 
# 目录下的JSP,HTML等..
views.directory =的src /测试/ web应用/ WEB-INF /意见
 
# 包的风格。
# 有3种款式:
# 功能/功能
# 在同一个包按功能的所有类
# net.sf.serfj.controllers.Bank
# net.sf.serfj.controllers.Order
# net.sf.serfj.serializers.JsonBankSerializer
# net.sf.serfj.serializers.XmlOrderSerializer
# FUNCTIONAL_BY_MODEL / functional_by_model
# 通过类模型和功能
# net.sf.serfj.bank.controllers.Bank
# net.sf.serfj.bank.serializers.JsonSerializer
# net.sf.serfj.order.controllers.Order
# net.sf.serfj.order.serializers.JsonSerializer
# MODEL /型号
# 在同一个包通过模型中的所有类
# net.sf.serfj.bank.Bank
# net.sf.serfj.bank.JsonSerializer
# net.sf.serfj.order.Order
# net.sf.serfj.order.JsonSerializer
# 关/关/留空
# 保留为空或不定义它。该库将尝试不同的方式找到
# 类按以下顺序:功能,FUNCTIONAL_BY_MODEL,型号
# 这种方法效率较低,所以最好defininig一些之一。
#packages.style =
 
# 您可以更改控制器的包的名称(如果有)。
# 默认值是“控制器”。
#alias.controllers.package =控制器
#alias.controllers.package = CTRL
#alias.controllers.package = controllers.main
 
# 您可以更改序列化'包的名称(如果有)。
# 默认值是“序列化”。
#alias.serializers.package = utils的
#alias.serializers.package = utils.serializers
 
# 使用后缀
# 如果你不希望任何后缀设置为OFF /关的值
# 对于控制器默认为“关”
#suffix.controllers =控制器
# 命名net.sf.serfj.bank.BankController代替net.sf.serfj.bank.Bank控制器类必须
# 对于串行器默认是“串行”
#suffix.serializer =

5,寻找资源

有三种方式,其中SerfJ寻找资源,它们被命名为:

  • 功能。
  • 功能由模型。
  • 按产品型号。

如果没有人在配置文件中定义,那么框架使用的顺序来查找资源各一台。因此,如果开发者想告诉SerfJ如何必须寻找资源,他必须定义  packages.style 财产。

5.1功能风格

如果它正在寻找一个控制器,然后将合格的类名称将是:

main.package +“。” + alias.controllers.package +“。” +资本化利息(被单数(资源名称))+ suffix.controllers。

所以有这样的配置:

  • main.package:net.sf.serfj.tests
  • alias.controllers.package没有定义。默认值是  控制器
  • suffix.controllers:Ctrl键。默认值是一个空字符串。
  • 来源:银行

该框架将寻找下一个限定名的控制器:

net.sf.serfj.tests.controllers.BankCtrl

如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,文件等)。例如,具有这种配置:

  • main.package:net.sf.serfj.tests
  • alias.serializers.package没有定义。默认值是  序列化
  • suffix.serializers:没有定义。默认值是  序列化

寻找一个PDF序列化账目,限定类名称将是:

net.sf.serfj.tests.serializers.PdfAccountSerializer

寻找一个PDF序列化什么型号,限定类名称将是:

net.sf.serfj.tests.serializers.PdfSerializer

注:通用串行器只能够​​被功能性的风格中定义。

5.2功能由模型风格

在这种策略中,资源名称和被单数追加到  main.package  财产。如果它正在寻找一个控制器,然后将合格的类名称将是:

main.package +“。” +被单数(资源名称)+“。” + alias.controllers.package +“。” +资本化利息(被单数(资源名称))+ suffix.controllers。

所以有这个配置属性定义:

  • main.package:net.sf.serfj.tests
  • alias.controllers.package:CTRL
  • suffix.controllers:没有定义。默认值是一个空字符串。
  • 来源:银行

该框架将寻找下一个限定名的控制器:

net.sf.serfj.tests.bank.ctrl.Bank

如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,Base64的,等等)。例如,具有这种配置的属性定义如下:

  • main.package:net.sf.serfj.tests
  • alias.serializers.package:串行
  • suffix.serializers:没有定义。默认值是  序列化

寻找一个PDF序列化账目,限定类名称将是:

net.sf.serfj.tests.account.serial.PdfAccountSerializer

5.3按型号款式

在这种策略中,资源名称和被单数追加到  main.package  财产,但  别名  不使用。如果它正在寻找一个控制器,然后将合格的类名称将是:

main.package +“。” +被单数(资源名称)+“。” +资本化利息(被单数(资源名称))+ suffix.controllers。

所以有这个配置属性定义:

  • main.package:net.sf.serfj.tests
  • suffix.controllers:没有定义。默认值是一个空字符串。
  • 来源:银行

该框架将寻找下一个限定名的控制器:

net.sf.serfj.tests.bank.Bank

如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,Base64的,等等)。例如,具有这种配置:

  • main.package:net.sf.serfj.tests
  • suffix.serializers:没有定义。默认值是  序列化

寻找一个CSV序列化账目,限定类名称将是:

net.sf.serfj.tests.account.CsvAccountSerializer

6。SerfJ的客户

SerfJ提供了一个类  net.sf.serfj.client.Client  为了做REST请求。它有四个  公共  方法(GET,POST,PUT和DELETE)用来做要求。该接口是非常简单的,所以JavaDoc应该足够使用这个类。


评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值