我们在学习一个比较新的框架的时候我们首先要做的是我们去它的官方网站去查看提供的开发文档可是这个矿建是我看见的矿建中文档最少的一个他妈的它,文档太少了官方就有一个例子:
官方地址:http://serfj.sourceforge.net/index.html
SerfJ提供了一个MVC架构,但它不会做任何事情的模型,其主要特点是控制器,这些控制器通过REST请求管理。
控制器指应用程序的资源,所以将消息发送到这些资源的方式是通过REST的请求。当一个请求被主的servlet(出席net.sf.serfj.RestServlet),资源(控制器)中搜索,并询问它是否能够回答该请求。在这种情况下,当执行一个动作(一个控制器的方法),和一个响应被提供给客户端。响应可以是一个网页,一个序列化的对象,或HTTP状态代码204,这意味着 没有任何内容。
由于REST请求控制SerfJ的应用程序的流量,这是非常重要的阅读本节。然而,概念解释如下是简单的,所以一切都会很容易理解。
通过SerfJ支持的HTTP方法是:
例如,如果你想呈现一个页面,有更新或创建资源的形式,你需要发送一个 GET 请求,而不是一个 PUT 请求。但提交按钮(其目的是更新一些信息)将发送一个 PUT 请求。
该模式对REST请求是:
请注意,资源的名称必须是复数,且 标识符 必须以数字开头。但SerfJ能够解析与嵌套的资源的URL:
如果你有一个扩展完成您的网址,那么结果将不会是一个页面,但序列化对象。因此,根据所使用的扩展,可以收到序列化为JSON,XML或使一个对象:
根据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更新资源 |
控制器是在SerfJ主角,REST请求分派给他们,他们回答这些请求。答案可能是一个网页,一个序列化的对象,或没有(一个HTTP代码)。
有两种方法写一个控制器(会有更多的在未来SerfJ版本),延长 net.sf.serfj.RestController 类,甚至写一个JavaBean。最后一种情况是怪异的,因为控制器将无法做到像从请求中获取参数的一些行动,或重定向到另一个页面,或者对象发送到JSP页面。
目前,延长 RestController 类是写一个控制器的最佳方式。方法是参加请求musn't有参数,但可以返回对象并抛出异常。例如,如果我们需要一个控制器来参加请求 /账户,我们必须写一个类是这样的:
1
2
|
公共
类
账户
扩展
RestController {
}
|
有几个注解,告诉哪些HTTP方法是通过一个控制器的方法接受的框架。
此外,还有另外一个, @ DoNotRenderPage ,告诉该执行器的方法后,没有页面将被渲染的框架,但一个HTTP 204代码将得到解答。因为它返回一个对象的方法不会呈现一个页面,因此,它并不需要与被注解 @ DoNotRenderPage。然而,一个不返回任何东西(一个方法 无效 的方法),但开发商不希望呈现一个页面作为一个结果,也必须注明。
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(
“ 平衡”
));
}
}
|
好了,现在我们知道了如何从请求获取参数,但有时我们需要将对象发送到一个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(
“ 平衡”
);
}
}
}
|
在这种情况下,如果存在序列的任何对象,该框架将它写在响应中。
控制器的方法,他们的执行后总是会呈现一个页面,除非该方法有一个返回对象或者是标注了 @ 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代码 |
这就是框架呈现默认的页面,但有一些方法可以使其他网页。有三种方法来渲染页面:
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) |
由于版本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”
;
}
}
|
虽然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();
|
当一个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”
;
}
}
|
类的名称必须与序列化是为扩展名,其次是资源的名称,并且必须以 串行器:
另一种选择是有内'package.hierarchy.serializers'包中的序列化。那么这个类的名称必须与序列化是为扩展名,而且必须以 串行器。这种方式可以实现通用串行器为每一个模型:
该框架试图遵循的理念 约定优于配置,所以使用它几乎不需要配置它。当然这需要进行配置,但只有一点点。但是,如果开发人员想要得到它运行的更好,他们可以为了避免SerfJ做预测,以找到一些资源,建立了几个配置属性。
SerfJ只有一个配置文件 serfj.properties ,有是在 / config中 的目录内 的类路径。它只需要一个 main.package 属性生效。此属性必须指向该软件包SerfJ将寻找控制器和序列化,但它并不意味着所有的控制器和串行必须在那个包,顺便框架查找资源在下一节解释。
在这里,您有一个配置文件的例子:
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 =
|
有三种方式,其中SerfJ寻找资源,它们被命名为:
如果没有人在配置文件中定义,那么框架使用的顺序来查找资源各一台。因此,如果开发者想告诉SerfJ如何必须寻找资源,他必须定义 packages.style 财产。
如果它正在寻找一个控制器,然后将合格的类名称将是:
main.package +“。” + alias.controllers.package +“。” +资本化利息(被单数(资源名称))+ suffix.controllers。
所以有这样的配置:
该框架将寻找下一个限定名的控制器:
net.sf.serfj.tests.controllers.BankCtrl
如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,文件等)。例如,具有这种配置:
寻找一个PDF序列化账目,限定类名称将是:
net.sf.serfj.tests.serializers.PdfAccountSerializer
寻找一个PDF序列化什么型号,限定类名称将是:
net.sf.serfj.tests.serializers.PdfSerializer
注:通用串行器只能够被功能性的风格中定义。
在这种策略中,资源名称和被单数追加到 main.package 财产。如果它正在寻找一个控制器,然后将合格的类名称将是:
main.package +“。” +被单数(资源名称)+“。” + alias.controllers.package +“。” +资本化利息(被单数(资源名称))+ suffix.controllers。
所以有这个配置属性定义:
该框架将寻找下一个限定名的控制器:
net.sf.serfj.tests.bank.ctrl.Bank
如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,Base64的,等等)。例如,具有这种配置的属性定义如下:
寻找一个PDF序列化账目,限定类名称将是:
net.sf.serfj.tests.account.serial.PdfAccountSerializer
在这种策略中,资源名称和被单数追加到 main.package 财产,但 别名 不使用。如果它正在寻找一个控制器,然后将合格的类名称将是:
main.package +“。” +被单数(资源名称)+“。” +资本化利息(被单数(资源名称))+ suffix.controllers。
所以有这个配置属性定义:
该框架将寻找下一个限定名的控制器:
net.sf.serfj.tests.bank.Bank
如果搜索的资源是一个序列,然后一个前缀用于类名。前缀是不可配置的,这将是该请求的延伸资本(XML,PDF,JSON,Base64的,等等)。例如,具有这种配置:
寻找一个CSV序列化账目,限定类名称将是:
net.sf.serfj.tests.account.CsvAccountSerializer
SerfJ提供了一个类 net.sf.serfj.client.Client 为了做REST请求。它有四个 公共 方法(GET,POST,PUT和DELETE)用来做要求。该接口是非常简单的,所以JavaDoc应该足够使用这个类。
中文对照:
SerfJ提供了一个MVC架构,但它不会做任何事情的模型,其主要特点是控制器,这些控制器通过REST请求管理。
控制器指应用程序的资源,所以将消息发送到这些资源的方式是通过REST的请求。当一个请求被主的servlet(出席net.sf.serfj.RestServlet),资源(控制器)中搜索,并询问它是否能够回答该请求。在这种情况下,当执行一个动作(一个控制器的方法),和一个响应被提供给客户端。响应可以是一个网页,一个序列化的对象,或HTTP状态代码204,这意味着 没有任何内容。
由于REST请求控制SerfJ的应用程序的流量,这是非常重要的阅读本节。然而,概念解释如下是简单的,所以一切都会很容易理解。
通过SerfJ支持的HTTP方法是:
例如,如果你想呈现一个页面,有更新或创建资源的形式,你需要发送一个 GET 请求,而不是一个 PUT 请求。但提交按钮(其目的是更新一些信息)将发送一个 PUT 请求。
该模式对REST请求是:
请注意,资源的名称必须是复数,且 标识符 必须以数字开头。但SerfJ能够解析与嵌套的资源的URL:
如果你有一个扩展完成您的网址,那么结果将不会是一个页面,但序列化对象。因此,根据所使用的扩展,可以收到序列化为JSON,XML或使一个对象:
根据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更新资源 |
控制器是在SerfJ主角,REST请求分派给他们,他们回答这些请求。答案可能是一个网页,一个序列化的对象,或没有(一个HTTP代码)。
有两种方法写一个控制器(会有更多的在未来SerfJ版本),延长 net.sf.serfj.RestController 类,甚至写一个JavaBean。最后一种情况是怪异的,因为控制器将无法做到像从请求中获取参数的一些行动,或重定向到另一个页面,或者对象发送到JSP页面。
目前,延长 RestController 类是写一个控制器的最佳方式。方法是参加请求musn't有参数,但可以返回对象并抛出异常。例如,如果我们需要一个控制器来参加请求 /账户,我们必须写一个类是这样的:
1
2
|
公共
类
账户
扩展
RestController {
}
|
有几个注解,告诉哪些HTTP方法是通过一个控制器的方法接受的框架。
此外,还有另外一个, @ DoNotRenderPage ,告诉该执行器的方法后,没有页面将被渲染的框架,但一个HTTP 204代码将得到解答。因为它返回一个对象的方法不会呈现一个页面,因此,它并不需要与被注解 @ DoNotRenderPage。然而,一个不返回任何东西(一个方法 无效 的方法),但开发商不希望呈现一个页面作为一个结果,也必须注明。
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(
“ 平衡”
));
}
}
|
好了,现在我们知道了如何从请求获取参数,但有时我们需要将对象发送到一个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(
“ 平衡”
);
}
}
}
|
在这种情况下,如果存在序列的任何对象,该框架将它写在响应中。
控制器的方法,他们的执行后总是会呈现一个页面,除非该方法有一个返回对象或者是标注了 @ 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代码 |
这就是框架呈现默认的页面,但有一些方法可以使其他网页。有三种方法来渲染页面:
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) |
由于版本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”
;
}
}
|
虽然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();
|
当一个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
|