用注解和pojo支撑起来的轻量级REST框架--T2
Written by Tony@tokyo
1. 前言
T2是以java5注解为支撑的轻量级Web框架。
T2不是简单的form提交,而对Ajax请求,RIA客户端等多种多样的前台技术的支持。
T2的目标:
² 无论什么类型的客户端都可以访问的Web服务器端框架
² 提供尽量简约,轻量级,易于维护和可扩展的架构
² 支持无状态,Rest风格的技术架构
² 提供plugin接口,可轻易扩展业务层架构
T2架构草图
T2的homepage: http://code.google.com/p/t-2/
1. T2的sample code
T2的运行需要的JRE和Web容器
JRE:1.6以上
Web容器:实现了Servlet2.5和JSP2.0的JavaEE标准
T2运行时必要的jar文件
T2.jar
Commons.jar Apache的共通类库
slf4j-api.jar logging用类库
T2必要的设定
Web.xml中的设定
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<filter>
<filter-name>t2</filter-name>
<filter-class>org.t2framework.t2.filter.T2Filter</filter-class>
<init-param>
<param-name>t2.rootpackage</param-name>
<param-value>sample.page</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>t2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
http请求由T2Filter接受,这里是T2框架的入口
[t2.rootpackage]指定了所有后台页面程序的根目录,Web容器启动以后,到这个目录下面,将所有@Page注解的Java程序实例化。
T2框架本身有自带的IOC管理器—SimpleContainerAdapter。
当然也可以通过以下配置,将instances的管理交由专业框架。
<init-param>
<param-name>t2.container.adapter</param-name>
<param-value>org.t2framework.t2.adapter.S2Adapter</param-value>
</init-param>
<!-- 設定ファイルの読み込み -->
<init-param>
<param-name>t2.config</param-name>
<param-value>app.dicon</param-value>
</init-param>
接受http请求的后台类
@Page("/helloworld")
public class HelloPage {
@Default
public Navigation index() {
String message ="HelloWorld";
return SimpleText.out(message);
}
}
以上,@Page用来声明这个后台类对外公开的URL。@Default声明默认的http请求的处理函数。
假设,Web工程的contentroot是/sample的话,上面的后台类能够用以下url访问
http://localhost:8080/sample/helloworld
T2框架可执行的SampleCode可以由以下取得
http://code.google.com/p/t-2/wiki/Samples
3. T2的运行原理
T2的MVC
T2的核心在于,一个url对应一个Page类。
Page类和View分离,达到可以自由更换View层技术。
Page类中,http request的接受,http response的组装,Token的获得,Session的获得,业务层service的对象的组装都可以由注解来完成。
比如,拿官方的sample举例
@RequestScope
@Page("login")
public class LoginPage {
private static Logger logger = Logger.getLogger(LoginPage.class);
protected LoginService loginService;
/**
*
* {@.en }
*
* <br />
*
* @param request
* @return
*/
@Default
public Navigation index(final HttpServletRequest request) {
TokenUtil.saveToken(request, Constants.TOKEN_KEY);
String token = TokenUtil.getToken(request, Constants.TOKEN_KEY);
request.setAttribute(Constants.TOKEN_KEY, token);
return Forward.to("WEB-INF/pages/login.jsp");
}
/**
*
* {@.en }
*
* @param context
* @return
* @since 0.5.1
*/
@Ajax
@POST
@ActionParam
public Navigation login(WebContext context) {
final String contextPath = context.getRequest().getContextPath();
final Map<String, String> map = CollectionsUtil.newHashMap();
String next;
if (TokenUtil.isTokenValid(context.getRequest().getNativeResource(),
Constants.TOKEN_KEY) == false) {
map.put("errorMessage", Functions.nls("login_token_invalid"));
next = "/login";
} else {
final String user = context.getRequest().getParameter("user");
final String pass = context.getRequest().getParameter("pass");
if (StringUtil.isEmpty(user)) {
map.put("errorMessage", Functions.nls("login_userid_empty"));
next = "/login";
} else if (StringUtil.isEmpty(pass)) {
map.put("errorMessage", Functions.nls("login_password_empty"));
next = "/login";
} else {
final boolean logined = loginService.login(user, pass, 0);
if (logined == false) {
logger.debug("Login error");
map.put("errorMessage", Functions.nls("login_auth_failed"));
next = "/login";
} else {
context.getSession().setAttribute(Constants.AUTH_KEY,
System.currentTimeMillis());
next = "/employee/list";
}
}
}
map.put("url", contextPath + next);
return Json.convert(map);
}
整个类最高层有两个注解,@RequestScope和@Page
@RequestScope声明本页面所有的变量只能存续在一次请求中
Index方法上的@Default声明了它是初期化函数
HttpServletRequest的变量是由框架组装实例化。
Login方法上的@Ajax,@POST,@ActionParam。分别声明了该方法支持Ajax请求,接受post方法请求,用来检查本方法和form的名字是否统一
前台JSP中提交的form如下
<form action="${t:url('/login')}" method="post">
<div class="x">
<span id="error" class="err">${message}</span>
<c:if test="${message != null}"><br /></c:if>
<span id="errorMessage" class="m">${t:nls('login_init_message')}</span>
<br/>
<fieldset id="loginFieldset" class="loginfieldset" title="${t:nls('login_init_message')}">
<legend>Login</legend>
<table>
<tr>
<td class="z">${t:nls('login_userid')}</td>
<td class="v">
<input type="text" id="user" name="user" maxlength="32" style="width: 100px;"/>
</td>
</tr>
<tr>
<td class="z">${t:nls('login_password')}</td>
<td class="v">
<input type="password" id="pass" name="pass" style="width: 100px;"/>
</td>
<td>
</tr>
<tr>
<td colspan="2" align="right">
<input type="submit" id="login" name="login" value="${t:nls('login_loginbutton')}" class="submit"/>
</td>
<td></td>
</tr>
</table>
</fieldset>
</div>
</form>
Form中定义的
t:url('/login')是用到了T2自定义的标签,简单说来就是将请求发给了Login.java的login函数。
T2的扩展
作为一个高扩展的框架,T2提供了注解自定义,函数拦截,入口参数封装等等扩展接口。
Navigation
Navigation是用来forward,redirect画面的接口。可以自定义扩展,比如在画面跳转之前,将数据封装成json等等。
ContainerAdapter
用来连接DI容器的适配器,可以自定义到任意到现有的DI框架。
Plugin
XXXPlugin这种class可以用来拦截http请求,封装参数对象等等。具体说起来就是在T2Filter将请求转发给XXXPage之前就加以处理
AnnotationResolverCreator
可以用来生成和解释自定义的标签
FormResolver
用来自定义form参数解释器。
#以上#
分享到:
相关推荐
本项目帮助你在spring-boot中使用Netty来开发WebSocket服务器,并像spring-websocket的注解开发一样简单
2、mybatis:轻量级,基于xml的模式感觉不利于封装,代码量不小,基于xml维护也麻烦(个人观点, 现在注解模式貌似也挺不错),感觉mybatis更适合存在dba角色的年代,可以远离代码进行sql调优,复杂的查询拼装起来...
非常好的 轻量级分布式 RPC 框架 学习资料 根据以上技术需求,我们可使用如下技术选型: Spring:它是最强大的依赖注入框架,也是业界的权威标准。 Netty:它使 NIO 编程更加容易,屏蔽了 Java 底层的 NIO 细节。 ...
hibernate 注解案例
#HyberbinData和HyberbinServlet可以只选其一使用 1.数据库中表名和POJO类的名称一致,只允许首字母大写,且必需大写。 2.数据库中表的字段和POJO类中的字段名称一致,全部小写。 3.POJO类中的成员变量类型必需...
maven-guvnor-install-pojo-plugin-1.1.0.17-sources.jar
maven-guvnor-install-pojo-plugin-1.1.0.16-sources.jar
maven-guvnor-install-pojo-plugin-1.1.0.15-sources.jar
maven-guvnor-install-pojo-plugin-1.1.0.14-sources.jar
maven-guvnor-install-pojo-plugin-1.1.0.13-sources.jar
maven-guvnor-install-pojo-plugin-1.1.0.12-sources.jar
maven-guvnor-install-pojo-plugin-1.1.0.11-sources.jar
Java JSOUP 标注方案,不用自己费劲解析了
java注解源码级框架描述 ORMAN 是一个简约轻量级的 Java 框架,它可以处理您常见的数据库使用,而无需编写 SQL 和大量jar依赖项。 它是用纯 Java 编写的,因此您可以非常轻松地在您的小型数据库消耗Java项目或...
分享一个使用SpringMVC4 Rest 和Jackson的@JsonView注解集成的实例。@JsonView用来过滤JSON响应。Spring4.1开始直接支持@JsonView注解。要使用@JsonView,首先我们需要定义视图,我们可以定义多个视图。一个视图定义...
Aspect Cache是一个针对Spring Boot,基于AOP注解方式的轻量级缓存,目前支持EHCache,Redis缓存方式。数据类型支持POJO、Map和List数据类型,同时支持自定义缓存key解析,也支持自定义的缓存处理方式,或者扩展支持...
MyMVC框架说明 本框架起源于课堂教学实践,目的...框架对表单使用用户自定义类进行了封装,用户需要强制类型转换为具体类型拆出数据。 整体上MyMVC Frame 博文链接:https://sun-pursuer.iteye.com/blog/223293
eclipse 配置 hibernate tools 反向生成 pojo类 注解
SSM笔记-POJO,测试POJO,SpringMVC会根据请求参数名和POJO类的属性名自动匹配为对应对象填充值
将数据发送回Rest Client本演示使用的Maven依赖关系spring-webmvc-MVC和REST集成jackson-databind-json转换器javax.servlet-api-配置分派器Servlet初始化程序服务器使用的服务器是TomCat-9.0api端点/ spring-rest-...