Dropwizard中配置依赖注入(HK2)

前面我们介绍了如何使用Jersey完成增删改查接口的开发,如果您想了解,可以参考:

Dropwizard 中使用Jersey开发Restful接口(查询接口)

Dropwizard 中使用Jersey开发Restful接口(响应报文格式、新增) 

Dropwizard 中使用Jersey开发Restful接口(修改、删除)

本篇我们在前面的案例的基础上,实现持久层代码与资源层代码的分离,并使用依赖注入完成持久层对象的注入。

一、持久类编码

我们在db包下编写GoodsRepository类:

public class GoodsRepository {

    private static List goodsList = new ArrayList<>();
    static {
        goodsList.add(new Goods("1", "薯片"));
        goodsList.add(new Goods("2", "可口可乐"));
    }

    /**
     * 查询商品
     * @return
     */
    public List find() {
        return this.goodsList;
    }

    /**
     * 根据ID查询商品
     * @param id
     * @return
     */
    public Goods findById(String id) {
        for (Goods goods: goodsList) {
            if(goods.getId().equals(id)) {
                return goods;
            }
        }
        return null;
    }

    /**
     * 插入
     * @param goods
     */
    public void insert(Goods goods) {
        goodsList.add(goods);
    }

    /**
     * 更新
     * @param goods
     */
    public void update(Goods goods) {
        for (Goods g: goodsList) {
            if(g.getId().equals(goods.getId())) {
                g.setName(goods.getName());
                break;
            }
        }
    }

    /**
     * 删除
     * @param id
     */
    public void delete(String id) {
        for (Iterator it = goodsList.iterator(); it.hasNext(); ) {
            Goods goods = it.next();
            if(goods.getId().equals(id)) {
                it.remove();
                break;
            }
        }
    }
}

这里我们在持久类中完成了数据的增删改查功能

二、资源类改造

@Path("/goods")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class GoodsResource {

    private final GoodsRepository goodsRepository;

    @GET
    public Response find() {
        return Response.ok().entity(new ResponseResult(0, "成功", this.goodsRepository.find())).build();
    }

    @POST
    public Response add(Goods goods) {
        // 判断商品是否为空
        if(Objects.isNull(goods)) {
            return Response.ok().entity(new ResponseResult(502, "商品不能为空")).build();
        }

        // 判断商品编号是否为空
        if(Objects.isNull(goods.getId())
            || goods.getId().isBlank()) {
            return Response.ok().entity(new ResponseResult(502, "商品编号不能为空")).build();
        }

        // 判断商品名称是否为空
        if(Objects.isNull(goods.getName())
            || goods.getName().isBlank()) {
            return Response.ok().entity(new ResponseResult(502, "商品名称不能为空")).build();
        }

        // 根据商品编号查询商品
        Goods hadGoods = this.goodsRepository.findById(goods.getId());
        if(Objects.nonNull(hadGoods)) {
            return Response.ok().entity(new ResponseResult(502, "商品编号已经存在")).build();
        }

        // 添加商品
        this.goodsRepository.insert(goods);
        return Response.ok().entity(new ResponseResult(0, "成功", goods)).build();
    }

    @PUT
    @Path("/{id}")
    public Response update(@PathParam("id") String id, Goods goods) {
        // 查询商品
        Goods hadGoods = this.goodsRepository.findById(id);

        // 判断商品是否存在
        if(Objects.isNull(hadGoods)) {
            return Response.ok().entity(new ResponseResult(404, "商品不存在")).build();
        }

        // 修改商品名称
        goods.setId(id);
        this.goodsRepository.update(goods);
        return Response.ok().entity(new ResponseResult(0, "成功", goods)).build();
    }

    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") String id) {
        // 查询商品
        Goods hadGoods = this.goodsRepository.findById(id);

        // 判断商品是否存在
        if(Objects.isNull(hadGoods)) {
            return Response.ok().entity(new ResponseResult(404, "商品不存在")).build();
        }

        // 删除商品
        this.goodsRepository.delete(id);
        return Response.ok().entity(new ResponseResult(0, "成功", hadGoods)).build();
    }
}

资源类改造后不再进行数据上的处理了,数据上的处理全部放在了持久类中,资源类通过调用持久类中的方法完成数据上的处理。

三、依赖注入

上面,我们虽然完成了持久类、资源类的编写;但资源类中的goodsRepository变量未初始化实例,当然可以通过new的方式进行创建实例,但是这样就增加了类之间的依赖;所以这里我们使用依赖注入的方式将GoodsRepository实例注入到资源对象中。

1、定义配置类

NamedProperty类:用于定义注入对象的属性

        value代表的是注入的对象

        id代表的是注入的对象的名称

        clazz代表的是注入的对象的类型

public class NamedProperty {
    private final String id;
    private final T value;
    private final Class clazz;

    public NamedProperty(String id, T value, Class clazz) {
        this.id = id;
        this.value = value;
        this.clazz = clazz;
    }

    public String getId() {
        return id;
    }

    public T getValue() {
        return value;
    }

    public Class getClazz() {
        return clazz;
    }
}

DependencyInjectionConfiguration接口:用于定义依赖注入的配置

public interface DependencyInjectionConfiguration {

    /**
     * 获取单例类列表
     * @return
     */
    List> getSingletons();

    /**
     * 获取注入对象的属性列表
     * @return
     */
    List> getNamedProperties();
}

2、依赖注入配置

项目配置类(我这里的是HorseConfiguration;项目搭建完成默认是trueConfiguration)实现上面定义的DependencyInjectionConfiguration接口

public class HorseConfiguration extends Configuration implements DependencyInjectionConfiguration {
    @Override
    public List> getSingletons() {
        final List> result = new ArrayList();
        result.add(GoodsRepository.class);
        result.add(GoodsResource.class);
        return result;
    }

    @Override
    public List> getNamedProperties() {
        return new ArrayList<>();
    }
}

在GoodsRepository、GoodsResource使用注入注解:

@Singleton
public class GoodsRepository {
}
@Singleton
public class GoodsResource {

    private final GoodsRepository goodsRepository;

    @Inject
    public GoodsResource(GoodsRepository goodsRepository) {
        this.goodsRepository = goodsRepository;
    }
}

@Singleton:代表的是单例

@Inject:代表的是注入对象

3、项目主类修改

实现依赖注入捆绑包:

public class DependencyInjectionBundle implements ConfiguredBundle {

    @Override
    public void run(DependencyInjectionConfiguration configuration, Environment environment) {
        environment.jersey()
                .register(new AbstractBinder() {
                    @Override
                    protected void configure() {
                        for (Class singletonClass: configuration.getSingletons()) {
                            // 绑定单例
                            bindAsContract(singletonClass).in(Singleton.class);
                        }

                        for (NamedProperty namedProperty: configuration.getNamedProperties()) {
                            // 注入对象
                            bind((Object) namedProperty.getValue()).to((Class) namedProperty.getClazz()).named(namedProperty.getId());
                        }
                    }
                });
    }
}

修改主类(我这里的是HorseApplication;项目搭建完成默认是trueApplication)

@Override
public void run(final HorseConfiguration configuration,
                    final Environment environment) {
    // 注册资源
    environment.jersey().register(GoodsResource.class);

    // 依赖注入
    DependencyInjectionBundle dependencyInjectionBundle = new DependencyInjectionBundle();
    dependencyInjectionBundle.run(configuration, environment);
}

四、项目启动测试

查询所有的商品

请求方式:GET

请求地址:http://localhost:8080/goods

响应结果如下:

{
    "code": 0,
    "msg": "成功",
    "data": [
        {
            "id": "1",
            "name": "薯片"
        },
        {
            "id": "2",
            "name": "可口可乐"
        }
    ]
}

你可能感兴趣的:(Dropwizard,restful,后端,java)