Guice 集成Redis/Mysql(简易mvc框架Demo)

最近在针对一个开源A/B Test系统做二次开发,这个系统使用的是google 开源的轻量级依赖注入框架Guice。

1、Guice简介

Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IOC)。Guice非常小而且快。Guice是一个非常干净的依赖注入框架,框架除了依赖注入功能之外,没有任何其它非相关模块功能。

2、依赖注入方式

首先要引入JAR包

 
            com.google.inject
            guice
            4.0
        
  • 字段直接注入
    @Inject
    UserService userService;
//注意,并不是说实现注入的service,一定是要在Module中和接口绑定,只是使用接口的方式更加优雅,
//像RedisClientTemplate这种工具性质的类,可以直接注入 
    @Inject
    RedisClientTemplate redisClientTemplate;
  • 配件文件注入
//配置文件参数读取并注入,当使用Names.bindProperties把配置文件中的内容绑定加载后,就可以直接
// @Inject @Named("redis.timeout") 注入使用了,相当的方便
        Names.bindProperties(binder(), PropertyUtil.loadFile(file, getClass()));
  • @Named名称指令来指定依赖注入实现(一个接口,多个实现类,这个非常实用
    @Inject
    @Named("user")
    UserService userService;

    @Inject
    @Named("worker")
    UserService workerService;
  • 构造器注入
 @Inject
public UserApi(UserService userService)
 {
     this.userService = userService;
 }

3、Demo

git地址 https://github.com/kzhang09/GuiceLearning.git

  • pom.xml


    4.0.0

    guice
    guice-learning
    1.0-SNAPSHOT

    
        
            com.google.inject
            guice
            4.0
        

        
            org.projectlombok
            lombok
            1.16.10
        

        
            mysql
            mysql-connector-java
            5.1.38
            runtime
        

        
            org.mybatis
            mybatis
            3.4.5
        

        
            com.alibaba
            druid
            1.1.9
        

        
            org.mybatis
            mybatis-guice
            3.10
        

        
            com.intuit.autumn
            autumn-service
            1.0.20160714060618
        

        
            com.intuit.autumn
            autumn-web
            1.0.20160714060618
        

        
            com.intuit.autumn
            autumn-api
            1.0.20160714060618
        
        
            javax.ws.rs
            jsr311-api
            1.1.1
        
    
            redis.clients
            jedis
            3.0.1
            jar
        
    

  • 项目启动入口Main


import api.ApiModule;
import com.google.inject.Inject;
import com.intuit.autumn.service.ServiceManager;
import mapper.MysqlModule;
import service.UserService;
import static com.intuit.autumn.web.WebServices.getEnabledWebServices;

public class Main {


    private Main() {
    }

    @Inject
    UserService userService;

    public static void main(String[] args) throws Exception {
        ServiceManager serviceManager = new ServiceManager()
//加载module类,实现注入
                .addModules(MysqlModule.class,  ApiModule.class)
//加载http服务
                .addServices(getEnabledWebServices());

        //项目启动
        serviceManager.start();
    }

}

  • Api 接口
package api;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import po.User;
import service.UserService;

import javax.annotation.Resource;
import javax.ws.rs.*;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;


@Path("/api")
@Produces(APPLICATION_JSON)
@Singleton
public class UserApi
{
//两种方式注入都可以,直接注入更简单点
    @Inject
    UserService userService;
    @Inject
    RedisClientTemplate redisClientTemplate;
//  @Inject
//  public UserApi(UserService userService)
//  {
//      this.userService = userService;
//  }

    @GET
    @Path("/users/{userId}")
    @Produces(APPLICATION_JSON)
    public Response getAssignment(
            @PathParam("userId")
            final int userId
            ) {
        try {
            System.out.println(userService.getUser());

redisClientTemplate.setex("guice_test",10,"OK");
System.out.println(redisClientTemplate.get("guice_test"));
            return Response.ok(userService.getUser()).build();
        } catch (Exception exception) {
            throw exception;
        }

    }
}

api module

package api;

import com.google.inject.AbstractModule;
import service.ServiceModule;

public class ApiModule extends AbstractModule
{
    @Override protected void configure()
    {
        install(new com.intuit.autumn.api.ApiModule());
//把下层serviceModule 注入,当然也可以在 main中直接注入 .addModules(MysqlModule.class,  ApiModule.class,ServiceModule.class);
// 这种注入有个好处,当多模块开发时,可以只在需要的地方注入
        install(new ServiceModule());
    }
}
  • Service类
package service;

import po.User;
import java.util.List;

public interface UserService
{
    List getUser();
    User getUserByName(String userName);
    User getUserByAge(int age);
}
package service.impl;

import com.google.inject.Inject;
import mapper.UserMapper;
import po.User;
import service.UserService;
import java.util.List;

public class UserServiceImpl implements UserService
{
    //注入
    @Inject
    UserMapper userMapper;

    @Override public List getUser()
    {
        return userMapper.getUsers();
    }

    @Override public User getUserByName(String userName)
    {
        return userMapper.getUserByName(userName);
    }

    @Override public User getUserByAge(int age)
    {
        return userMapper.getUserByAge(age);
    }
}

Service Module

package service;

import com.google.inject.AbstractModule;
import service.impl.UserServiceImpl;

public class ServiceModule extends AbstractModule
{
    @Override protected void configure()
    {
        //service服务注入,同时绑定接口UserService 和 实现类UserServiceImpl;
//这样就可以在别的地方直接使用接口注入了;比如     @Inject UserService userService;
        bind(UserService.class).to(UserServiceImpl.class);
    }
}

  • 集成mybatis
package mapper;

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.mybatis.guice.MyBatisModule;
import org.mybatis.guice.datasource.druid.DruidDataSourceProvider;
import util.PropertyUtil;

public class MysqlModule extends AbstractModule
{
    private String file = "mysql.properties";
    
    @Override
    protected void configure() {
//配置文件参数读取并注入,当使用Names.bindProperties把配置文件中的内容bind加载后,就可以直接
// @Inject @Named("redis.timeout") 注入使用了,相当的方便
        Names.bindProperties(binder(), PropertyUtil.loadFile(file, getClass()));

        //mysql数据库注入
        this.install(new MyBatisModule() {
            @Override
            protected void initialize() {
                bindDataSourceProviderType(DruidDataSourceProvider.class);
                bindTransactionFactoryType(JdbcTransactionFactory.class);
                // 通过属性配置完成映射,即属性的命名是遵从驼峰命名法的,数据列名遵从下划线命名
                // 会自动把 列名user_name 映射成实体userName;
                // 使用这个,同时使用注解,可以完全去除xml配置了
                mapUnderscoreToCamelCase(true);
                //类名,通常是使用下面通过包名来加载Mapper.class文件
                addMapperClass(UserMapper.class);
                //包名
                //addMapperClasses("mapper");
                //必须要有,不然会报错
                environmentId("dev");
            }

        });
    }
}

Mapper 类

package mapper;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import po.User;
import java.util.List;

public interface UserMapper
{
    @Select("SELECT * FROM user WHERE user_name = #{userName}")
    User getUserByName(@Param("userName") String userName);

    @Select("SELECT * FROM user WHERE age = #{arg0}")
    User getUserByAge(int age);

    @Select("SELECT * FROM user ")
    List getUsers();
}
  • 实体PO
package po;

import lombok.Data;

@Data
public class User
{
    private String  userName;

    private int age;
}
  • 集成Redis
    RedisModule
package redis;


import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.name.Names;
import util.PropertyUtil;

public class RedisModule extends AbstractModule
{
    private String file = "redis.properties";
    @Override protected void configure()
    {
        System.out.println("installing module: {}"+ RedisModule.class.getSimpleName());
        Names.bindProperties(binder(), PropertyUtil.loadFile(file, getClass()));

        //绑定redis数据源
        bind(RedisDataSource.class).toProvider(RedisClientProvider.class).in(Scopes.SINGLETON);
    }
}

RedisClientTemplate

package redis;

import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.*;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class RedisClientTemplate {

    private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);

    @Inject
    private RedisDataSource     redisDataSource;

    public void disconnect() {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        shardedJedis.disconnect();
    }

    /**
     * 设置单个值
     *
     * @param key
     * @param value
     * @return
     */
    public String set(String key, String value) {
        String result = null;

        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
         
        try {
            result = shardedJedis.set(key, value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
              
        } finally {
            redisDataSource.returnResource(shardedJedis);
        }
        return result;
    }

    /**
     * 获取单个值
     *
     * @param key
     * @return
     */
    public String get(String key) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }

         
        try {
            result = shardedJedis.get(key);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
              
        } finally {
            redisDataSource.returnResource(shardedJedis);
        }
        return result;
    }
//......
//太长了,剩余的见git上的源码
}

RedisClientProvider

package redis;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedisPool;
import java.util.Arrays;
import java.util.Objects;

public class RedisClientProvider implements Provider
{

    @Inject
    @Named("redis.database")
    private Integer database;
    @Inject
    @Named("redis.host")
    private String host;
    @Inject
    @Named("redis.port")
    private Integer port;
    @Inject
    @Named("redis.password")
    private String password;
    @Inject
    @Named("redis.pool.max.active")
    private Integer maxActive;
    @Inject
    @Named("redis.pool.max.idle")
    private Integer maxIdle;
    @Inject
    @Named("redis.pool.max.wait")
    private Integer maxWait;
    @Inject
    @Named("redis.pool.min.idle")
    private Integer minIdle;
    @Inject
    @Named("redis.timeout")
    private Integer timeout;

    private ShardedJedisPool getJedisPool() {
        if (Objects.isNull(shardedPool)) {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(this.maxActive);
            config.setMaxWaitMillis(this.maxWait);
            config.setMaxIdle(this.maxIdle);
            config.setMinIdle(this.minIdle);

            JedisShardInfo info = new JedisShardInfo(this.host, this.port.intValue(),
                    this.timeout.intValue());
            if (this.password != null && !this.password.isEmpty()) {
                info.setPassword(password);
            }
            shardedPool = new ShardedJedisPool(config, Arrays.asList(new JedisShardInfo[]{info}));
        } else {
            return shardedPool;
        }
        return shardedPool;
    }

    @Override
    public RedisDataSource get() {
        return new RedisDataSource(getJedisPool());
    }
    private static ShardedJedisPool shardedPool;
}

RedisDataSource

package redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

public class RedisDataSource
{

    private static final Logger log = LoggerFactory.getLogger(RedisDataSource.class);

    private ShardedJedisPool shardedJedisPool;

    public RedisDataSource(ShardedJedisPool jedisPool)
    {
        this.shardedJedisPool = jedisPool;
    }

    public ShardedJedis getRedisClient() {
        try {
            ShardedJedis shardJedis = shardedJedisPool.getResource();
            return shardJedis;
        } catch (Exception e) {
            log.error("getRedisClent error", e);
        }
        return null;
    }

    public void returnResource(ShardedJedis shardedJedis) {
        shardedJedis.close();
    }
}
  • Uitl工具类
package util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class PropertyUtil
{

    /**
     * 读取配置文件属性
     */
    public static Properties loadFile(String prefix, Class cla) {
        String fileName = prefix;
        Properties prop = new Properties();
        InputStream in = null;
        try {
            in = cla.getResource("/" + fileName).openStream();
            prop.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return prop;
    }
}
  • 配置文件
    mysql.properties
#dev
#JDBC
JDBC.driverClassName=com.mysql.jdbc.Driver
JDBC.url=JDBC:mysql://x.x.x.x:3306/wasabi?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=true&zeroDateTimeBehavior=convertToNull
JDBC.username=readwrite
JDBC.password=readwrite

JDBC.initialSize=5
JDBC.maxWait=30000
JDBC.testWhileIdle=true
JDBC.testOnBorrow=true
JDBC.testOnReturn=false
JDBC.validationQuery=SELECT 1
JDBC.minEvictableIdleTimeMillis=300000
JDBC.timeBetweenEvictionRunsMillis=60000

web.properties

#http服务
application.http.enabled=true
#服务端口
application.http.port=8080

#api服务包名
application.jersey.provider.paths=api
application.jersey.pojo.enabled=true
application.jersey.wadl.enabled=false

redis.properties

redis.database=0
redis.host=x.x.x.x
redis.port=6379
redis.password=xxxx
#连接池最大连接数(使用负值表示没有限制)
redis.pool.max.active=10000
# 连接池中的最大空闲连接
redis.pool.max.idle=100
#连接池最大阻塞等待时间(使用负值表示没有限制)
redis.pool.max.wait=-1
# 连接池中的最小空闲连接
redis.pool.min.idle=0
# 连接超时时间(毫秒)
redis.timeout=0

demo结构

Guice 集成Redis/Mysql(简易mvc框架Demo)_第1张图片
image.png

你可能感兴趣的:(Guice 集成Redis/Mysql(简易mvc框架Demo))