基于ICEREST+MongoDB-Plugin开发一个简单的增删查改

简介

ICEREST是一个非常轻量级只有200k左右的RESTful路由框架,通过ICEREST你可以处理url的解析,数据的封装,Json的输出,和传统的方法融合,请求的参数便是方法的参数,方法的返回值便是请求的返回值,同时我们希望ICEREST是一个能让人倍感呵护的框架。

官网地址:http://icerest.cc


MongoDB-Plugin是用于帮助JAVA开发者更容易使用MongoDB而开发的的插件

官方地址:https://github.com/T-baby/Mon...


本文代码已开源在GitHub:https://github.com/T-baby/ICE...

教程目标:教会大家基于ICEREST+MongoDB-Plugin开发一个简单的增删查改应用。

首先我们来看下这个demo的文件结构

基于ICEREST+MongoDB-Plugin开发一个简单的增删查改_第1张图片

相信大家一眼就能看出这是一个maven项目,在component文件夹中包含了两个验证器、一个bean类、一个model类。

首选我们为这个项目添加好依赖,在pom.xml中添加。

    
      junit
      junit
      4.10
      test
    


    
    
      ch.qos.logback
      logback-classic
      1.1.2
    

    
      com.alibaba
      fastjson
      1.2.7
    



    
      javax.servlet
      javax.servlet-api
      3.1.0
    


    
    
      com.cybermkd
      ICEREST
      1.0.1.2
    

    
      com.cybermkd
      ICEREST-PLUGIN
      1.0.0
    

    
      com.cybermkd
      MongodbPlugin
      1.0.6.3
    

添加完以后在config文件夹中创建AppConfig类:


public class AppConfig extends Config {
    /**
     * Config constant
     * 配置常量,目前只能配置render,其他全局配置会自动读取根目录下的application.properties文件,建议用默认
     */
    public void configConstant(ConstantLoader constantLoader) {
        //通过后缀来返回不同的数据类型  你可以自定义自己的 render,一般无需配置
        //如:public class FreemarkerRender extends Render{}
        //目前支持json,text,file三种输出
        //constantLoader.addRender("ftl", new FreemarkerRender());
        constantLoader.setDefaultForward("/"); //单页应用会用到,用来跳过对/的拦截
    }

    /**
     * Config resource
     * 配置Resource路由的扫描目录,ICEREST是自动绑定路由的
     */
    public void configResource(ResourceLoader resourceLoader) {

        resourceLoader.addIncludePackages("com.cybermkd.component");
    }

    /**
     * Config plugin
     * 配置插件
     */
    public void configPlugin(PluginLoader pluginLoader) {

        MongoIceRestPlugin mongoIcePlugin = new MongoIceRestPlugin();

        mongoIcePlugin.add("127.0.0.1", 27017);

        mongoIcePlugin.setDatabase("item");

        pluginLoader.add(mongoIcePlugin);

    }

    /**
     * Config interceptor applied to all actions.
     * 全局拦截,会在进入路由后,执行方法前执前
     */
    public void configInterceptor(InterceptorLoader interceptorLoader) {
        //权限拦截器
        //interceptorLoader.add(new SecurityInterceptor(2, new MyAuthenticateService()));
        //Resource层事务的拦截器 @Transaction
        //interceptorLoader.add(new TransactionInterceptor());
    }

    /**
     * Config handler
     * 全局的拦截,会在进入路由前执行
     */
    public void configHandler(HandlerLoader handlerLoader) {
        //跨域
        handlerLoader.add(new CORSHandler("GET,POST,PUT,DELETE"));
    }


    /**
     * Call back after ICEREST start
     */
    public void afterStart() {
        //ICEREST启动前执行的操作
    }

    /**
     * Call back before ICEREST stop
     */
    public void beforeStop() {
        //ICEREST停止前执行的操作
    }
}

config这里没有什么好说的,基本都已经写在了代码的注释。

我们现在罗列下我们需要开发的功能,我们要开发的是一个记录待办事项的工具要实现以下功能:

  • 增加事项

  • 删除事项

  • 修改事项

  • 获取所有事项

一个事项中包含了id、内容和创建时间。所以我们可以建一个bean类:


public class ItemBean extends MongoValidate {

    @NotNull(message = "content can't be empty")
    @NotBlank(message = "content can't be empty")
    @Length(min = 1, max = 120, message = "content is too long or too short")
    private String content;

    private String creat_time;

    @NotNull(message = "id can't be empty")
    @NotBlank(message = "id can't be empty")
    private String id;

    public String getContent() {
        return content;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getCreat_time() {
        return creat_time;
    }

    public void setCreat_time(String creat_time) {
        this.creat_time = creat_time;
    }
}

为什么我们使用者mongodb却要要建bean类呢?在实际开发中经常会有同时数个人开发同一个项目,mongodb允许每一行的结构都不一样但这对于协同开发来说缺是噩梦。

所以为了方便协同工作建议使用bean类来约束数据的结构。

相信大家会看到@NotNull这样的注释,有什么用呢?在Mongodb Plugin 1.0.5后已经结合了hibernate的校验功能,遵循JSR 303规范。

具体使用见:http://www.cybermkd.com/mongo...

如果bean继承了MongoValidate这个类,就可以在创建bean对象的后用validation方法校验全部属性或者用validation(String... keys)校验某个属性。通过errorMessage获取错误信息。

之所以没命名为getErrorMessage是因为fastjson在反序列化的时候会自动处理带有getXXX的方法的变量。我们实际使用中又不需要errorMessage。

紧接着我们需要创建一个Model来操作数据库。MongoDB-Plugin的使用文档见:http://www.cybermkd.com/mongo...

public class ItemModel {

    private static String collectionName = "storehouse";

    public List get() {
        return new MongoQuery().use(collectionName).findAll();
    }

    public List get(String id) {
        return new MongoQuery().use(collectionName).byId(id).find();
    }

    public boolean save(ItemBean bean) {
        System.out.println(JSON.toJSONString(bean));
        bean.setId(null);  //以免万一清空id
        return new MongoQuery().use(collectionName).set(bean).save() > 0;
    }

    public boolean put(ItemBean bean) {
        MongoQuery query = new MongoQuery().use(collectionName).byId(bean.getId());
        /*因为在controller是直接获取整个对象的(在查询的时候为了大家方便会自动将_id变为id,但是mongodb实际存的还是_id),
        / 为了避免将id插入进去,特意清空。*/
        bean.setId(null);
        return query.modify(bean).update() > 0;
    }

    public boolean delete(ItemBean bean) {
        return new MongoQuery().use(collectionName).byId(bean.getId()).delete() > 0;
    }

}

我们现在能操作数据了,在插入事项的时候我们需要校验内容的长度,当删除、更新的时候我们需要校验这个事项是否存在,所以我们需要分别建两个校验器:

public class ContentValidator extends Validator {
    @Override
    public ValidResult validate(Params params, RouteMatch routeMatch) {

        ItemBean item = params.getObject(ItemBean.class);

        return new ValidResult().mongoValid(item, "content");
    }
}

在ICEREST 1.0.1以上的版本已经融入了MongoDB-Plugin的校验功能,可以直接在拦截器中用new ValidResult().mongoValid(对象,属性名)校验,如果不加后面的属性名则是校验所有属性。通过params.getObject就可以将获取到的参数直接转为某个对象,这个对象属性中没有的值全部抛弃。

在bean中的message注释的文本,如果在校验器中校验发现传的值是有问题的就会将这个message直接放入ValidResult中,格式如下:

{
"error":"",
"errorMessage":""
}
public class IdValidator extends Validator {
    @Override
    public ValidResult validate(Params params, RouteMatch routeMatch) {
        ItemBean item = params.getObject(ItemBean.class);

        ValidResult result = new ValidResult();


        result.mongoValid(item, "id");

        if (result.isError()) {
            return result;
        }

        ItemModel m = new ItemModel();

        try {
            if (m.get(params.get("id")).isEmpty()) {
                throw new RuntimeException();
            }
        } catch (RuntimeException e) {
            result.addError("error", "100");
            result.addError("errorMessage", "id is error.");
        }

        return result;

    }
}

在IdValidator中相信大家会发现一个try catch,在mongodb java driver中如果传来的id是随便乱写的那么会报错,我们利用这一点建个try catch拦截错误,只要mongodb driver 抛出错误就代表id是错的。

@API("/v1/item")
public class ItemController extends Resource {

    ItemModel m = new ItemModel();

    @GET()
    public WebResult get() {
        return render(m.get());
    }

    @POST(valid = {ContentValidator.class})
    public WebResult post() {
        ItemBean bean = getParams().getObject(ItemBean.class);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        bean.setCreat_time(df.format(new Date()));
        return render(m.save(bean));
    }

    @PUT(valid = {IdValidator.class, ContentValidator.class})
    public WebResult put() {
        return render(m.put(getParams().getObject(ItemBean.class)));
    }

    @DELETE(valid = {IdValidator.class})
    public WebResult delete() {
        return render(m.delete(getParams().getObject(ItemBean.class)));
    }

    private WebResult render(Object obj) {
        JSONObject json = new JSONObject();
        json.put("result", obj);
        return new WebResult(HttpStatus.OK, JSON.toJSONString(json));
    }


}

在controller类中,我们先利用@API声明路径,用@GET等注释声明请求类型。用render封装了下返回的结果。

就这样一个简单的待办事项api就完成了呢~

你可能感兴趣的:(mongodb,spring,mvc,java)