Java控制器层_控制器层(Controllers)

业务逻辑代码通常位于模型(model)层。客户端(比如浏览器)无法直接调用其中的代码,所以模型对象提供的功能,必须作为资源以URI方式暴露给外部。

客户端使用HTTP协议来操作这些资源,从而调用了内部的业务逻辑。但是,这种从资源到模型之间的映射是单向的:我们可以根据需要提供不同粒度的资源,可以虚拟出一些资源,还可以给某些资源起别名...

Controller层就是专门做这件事的:在模型层与传输层之间搭起一座桥梁。它使用与模型层同一种语言,以便访问和修改模型对象,但同时它又跟HTTP接口一样,是面向请求(Request)和响应(Response)的。

Controller层减少了HTTP与模型层之间的“阻抗不匹配”。

注意

不同的模型方案使用了不同的策略。有一些可以让我们直接访问模型对象,比如EJB或者Corba协议,它们使用RPC(远程过程调用)。这种交互方式与web很难兼容。

另一些技术如SOAP,尝试通过Web来访问模型层,但它也是一种PRC风格的协议,只是以HTTP为传输协议。它也不是一种程序协议。

Web的理念在根本上与面向对象不同,所以我们需要一个层来协调。

Controller综述

一个Controller就是一个位于 controllers 包中的类,其继承于 play.mvc.Controller :

示例:

package controllers;

import models.Client;

import play.mvc.Controller;

public class Clients extends Controller {

public static void show(Long id) {

Client client = Client.findById(id);

render(client);

}

public static void delete(Long id) {

Client client = Client.findById(id);

client.delete();

}

}

Controller中每一个public static方法都被称为一个action。它的签名形如:

public static void action_name(params...);

你可以在action的方法签名中定义各种参数。Play会自动从相应的HTTP参数中,取出对应的值赋过去(并进行恰当的转换),这一点非常方便。

通常一个action不需要返回值。当我们在action中调用了一个能产生“结果”的方法后,action就退出了。在本例中, render(…) 就是一个显示一个模板的可产生结果的方法。

获取HTTP参数

HTTP请求中可包含数据,这些数据可位于:

URI路径中: 如 /clients/1541, 1541就是一个动态产生的参数.

Query String: /clients?id=1541.

request body: 如果提交了一个HTML表彰,将request body中将包含以 x-www-urlform-encoded 方式转换过的数据。

对于这些情况,Play都可以取得数据,并生成一个 Map 。Key是参数名,来源于:

在conf/routes文件中定义的规则中的动态参数名

Query String中的name=value

通过表单提交的数据的name.

使用参数map

在所有的Controller类中都可以直接使用 params 这个对象。它是在 play.mvc.Controller 中定义的。这个对象中,包含了当前请求的所有数据。

示例:

public static void show() {

String id = params.get("id");

String[] names = params.getAll("names");

}

你还可以转换参数值的类型:

public static void show() {

Long id = params.get("id", Long.class);

}

其实,还有更好的办法来转换 :)

直接利用action方法的参数类型定义来转换

我们可以直接从action方法的参数定义中,直接拿到对应的参数值。方法中的参数名必须跟http传过来的参数名相同。

比如,对于如下的URL:

/clients?id=1451

我们可以定义一个包含 id 参数的action:

public static void show(String id) {

System.out.println(id);

}

我们还可以使用其它的类型,play会自动进行转换:

public static void show(Long id) {

System.out.println(id);

}

如果同一个参数有多个值,还可以把它声明为数组:

public static void show(Long[] id) {

for(String anId : id) {

System.out.println(anid);

}

}

甚至集合:

public static void show(List id) {

for(String anId : id) {

System.out.println(anid);

}

}

这一功能非常方便,其它的框架都很少提供(有一些提供了,但要求每个参数前都要加一个annotation,不太方便)。

内部原理是,Play会对每个action进行扫描,得到其参数信息(包括类型与参数名)。能过反射很容易得到参数类型,但得不到参数名,因为javac在编译java代码时,会忽略参数名信息。而Play内置了eclipse的编译器,并在编译时打开相关选项以记录参数名信息,所以才能成功取到。

异常

如果action方法中定义的某个参数,在http请求中找不到对应的数据,则将会把它设为默认值(对象类型设为null,基础数字类型设为0,boolean类型设为false)。如果找到了,但是其值无法转换为指定的Java类型,则会将这一错误记录在validation对象中,并使用默认值代替。

HTTP to Java 高级绑定

简单类型

Java中所有基础和常用类型,都可以自动绑定:

int, long, boolean, char, byte, float, double, Integer, Long, Boolean, Char, String, Byte, Float,Double.

注意如果某个参数HTTP请求中没有提供,或者自动转换失败,则Object类型会被设为null,而基础类型会被设为它们的默认值。

Date

如果一个日期格式如下,则它可以自动转换并绑定:

yyyy-MM-dd’T’hh:mm:ss’Z'

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值