AJAXJS MVC 使用教程(下)
Posted sp42a
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AJAXJS MVC 使用教程(下)相关的知识,希望对你有一定的参考价值。
模板和返回响应数据
输出html
控制器处理完业务后会返回结果数据给前端:要么在前后端分离的情况下直接返回JSON数据,无须经过视图层;要么返回HTML则要在View层进行转化。传统Servlet做法是对request进行setAttribute()/getAttribute()
的操作,它实质是一个Map<String, Object>
的读写。MVC新框架下独立出来这个中介媒介map为ModelAndView
对象,用于存储页面所要显示的数据,穿梭于控制器与视图层之间。在控制器方法中加入ModelAndView参数即可,它本身就是HashMap
的子类。
以下例子是输出不同类似的数据到页面v中。
package com.demo.mvc;
import java.util.ArrayList;
import java.util.HashMap;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import com.ajaxjs.web.mvc.ModelAndView;
import com.ajaxjs.web.mvc.controller.IController;
@Path("/output")
public class OutputController implements IController {
@GET
public String jsp(ModelAndView mv) {
mv.put("showText", "测试字符串"); // 测试字符串
mv.put("showLong", 100000L); // 测试 long
mv.put("list", new ArrayList<Object>() { // 测试列表
private static final long serialVersionUID = 1L;
{
add("foo");
add(123456);
add(true);
}
});
mv.put("array", new String[] { "abc", "bar", "12345a" });// 测试数组
mv.put("map", new HashMap<String, Object>() {// //测试 Map
private static final long serialVersionUID = 1L;
{
put("key1", "FOO");
put("key2", "BAR");
put("key3", false);
}
});
return "/WEB-INF/jsp/output"; // 可以省略 .jsp 的扩展名
}
}
EL表达式+页面标签赋予了读取ModelAndView
的能力,在下面这个JSP中最终显示HTML出来。
<%@ page pageEncoding="UTF-8"%>
<%@taglib uri="/ajaxjs" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>输出 Model 数据</title>
</head>
<body>
<h4>测试字符串</h4>
<div>${showText}</div>
<h4>测试 long</h4>
<div>${showLong}</div>
<h4>测试列表</h4>
<c:foreach items="${list}">${item} <br /></c:foreach>
<h4>测试数组</h4>
<c:foreach items="${array}">${item} <br /></c:foreach>
<h4>测试 Map</h4>
<c:foreach items="${map}">
<div>${item.key} - ${item.value}</div>
</c:foreach>
</body>
</html>
输出JSON
控制器方法返回如“json::{"foo":"bar"}
”的字符串即可迅速输出JSON。不过为了避免手工拼接字符串,多数情况下采用BaseController下的实用工具方法toJson()
将Bean/Map/List
转换为 JSON 字符串。
@GET
@Path("jsonStr")
public String toJson() {
// 第二个参数为 true 表示自动附上 json:: 的前缀
return BaseController.toJson("{\\"foo\\":\\"bar\\"}", true);
}
@GET
@Path("jsonMap")
public String toJsonMap() {
return BaseController.toJson(new HashMap<String, Object>() {// //测试 Map
private static final long serialVersionUID = 1L;
{
put("key1", "FOO");
put("key2", "BAR");
put("key3", false);
}
});
}
@GET
@Path("jsonList")
public String toJsonList() {
return BaseController.toJson(new ArrayList<String>() { // 测试列表
private static final long serialVersionUID = 1L;
{
add("foo"); // 只能是特定的一种泛型,如String/Integer等等,不能是 Object
add("bar");
}
});
}
@GET
@Path("jsonBean")
public String toJsonBean() {
News news = new News();
news.setId(1000L);
news.setName("foo");
return BaseController.toJson(news);
}
MVC过滤器
过滤器的主要目的是拦截每次请求之前和之后的一些操作。有别于Servlet标准过滤器,这是MVC框架中重写的过滤器。为简化概念,框架中不单独另设AOP机制,但可把过滤器当作AOP的代替品。其发挥如下作用:初始化数据库连接、日志记录、权限校验等等。
如下例子中注解@MvcFilter
引入了数据库连接过滤器DataBaseFilter,通过过滤器before()
方法在list()
执行之前调用了数据库连接的逻辑。除此之外@Authority
也是过滤器注解,引入PrivilegeFilter
实现权限的校验,注解的value属性是创建PrivilegeFilter所必需的构造器参数。
@GET
@MvcFilter(filters = { DataBaseFilter.class })
@Authority(filter = PrivilegeFilter.class, value = RightConstant.ARTICLE_ONLINE)
public String list(@QueryParam(START) int start, @QueryParam(LIMIT) int limit) {
return page("article-list");
}
MvcFilter的filters属性是FilterAction接口派生类的数组,类型为Class<? extends FilterAction>[]
。当用户自定义过滤器时须实现FilterAction
接口,给出before(FilterContext ctx)
与after(FilterAfterArgs ctx)
的实现。接口FilterAction
源码如下。
package com.ajaxjs.web.mvc.filter;
/**
* 过滤器动作
*
* @author sp42 frank@ajaxjs.com
*/
public interface FilterAction {
/**
* 是异常但不记录到 FileHandler,例如密码错误之类的。放在 ModelAndView 中传递,例如
* model.put(NOT_LOG_EXCEPTION, true);
*/
public static final String NOT_LOG_EXCEPTION = "NOT_LOG_EXCEPTION";
/**
* 在 MVC 方法之前调用
*
* @return 是否要中止控制器方法的执行,true 表示为不中断
*/
public boolean before(FilterContext ctx);
/**
* 在 MVC 方法之后调用
*
* @param model 页面数据中间件
* @param request 请求对象
* @param response 响应对象
* @param method 方法对象
* @param isbeforeSkip 是否已经中止控制器方法的执行,也就是 before() 返回的值
* @return 是否要中止控制器方法默认返回的执行,一般返回 true 表示按原来的执行(大多数情况)
*/
public boolean after(FilterAfterArgs ctx);
}
FilterContext
/FilterAfterArgs
均是前置/后置方法所需的参数列表,用户可按需调用。值得注意是方法的boolean
类型返回值,决定了后续方法是否继续执行。前置方法before()
返回true
是一般正常情况,控制器方法会继续执行;若before()
返回false
或抛出异常会发生如下两件事:一、中止后续的过滤器执行;二、控制器方法不会执行。没有了控制器执行的结果,自然也不能按原流程返回结果给客户端。此时有两种分支可供用户选择:
- 后置方法
after()
参数中的FilterAfterArgs.isbeforeSkip
属性就是前置方法为false时的状态,用户在after()
实现中应判断isbeforeSkip
而给出相应的response响应。 - 如果想简单一点,可在
before()
中抛出异常,那样控制器也会接受到异常进而转化为response响应输出(可兼容HTML/JSON格式)。后者的做法更简单直接一点。本来多数情况下,若前置方法不能满足,则后面的未执行逻辑亦无须执行,除非有需要进行特定情况的处理。
框架中内建若干实用的过滤器供用户使用,如下表格所示,在com.ajaxjs.framework.filter.*
包和用户模块的com.ajaxjs.user.filter.*
。
以上是关于AJAXJS MVC 使用教程(下)的主要内容,如果未能解决你的问题,请参考以下文章