work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

微服务实践 SpringBoot+Thrift+MyBatis+MySql+Redis

Posted on 2020-05-20 10:48  work hard work smart  阅读(762)  评论(0编辑  收藏  举报

一、创建工程mircosevice

整体工程结构

 

 这里主要介绍EdgeServcie服务通过Thrift调用用户服务

 Thrift在Window下安装可参考: Window下 分布式框架 thrift的安装

 

二、创建用户接口定义模块

1、创建用户接口定义模块 user-thrift-service-api

结构如下:

 

 

1) 创建thrift定义文件 user_service.thrift 

里面定义了用户模块需要提供的接口

获得用户信息,注册用户等接口

namespace java com.example.thrift.user

struct UserInfo{
    1:i32 id,
    2:string username,
    3:string password,
    4:string realName,
    5:string mobile,
    6:string email
}

service UserService{

    UserInfo getUserById(1:i32 id);

    UserInfo getUserByName(1:string username);

    void registerUser(1:UserInfo userInfo);

}

  

2) 创建生成java的shell脚本 gen-code.sh

生成的文件路径为 工程下的src/main/java

#!/usr/bin/env bash
thrift --gen java --out ../src/main/java user_service.thrift  

执行shell脚本.

生成的文件如UserInfo和UserService

 

 

 

3)  增加依赖

    <dependencies>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.13.0</version>
        </dependency>
    </dependencies>

  

 

三、创建用户模块(接口实现)

1、结构如下图所示

 

 

2、pom文件配置如下

springboot版本为1.5.9

增加user-thrift-service-api模块依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>user-thrift-service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.13.0</version>
        </dependency>

        <dependency>
            <groupId>com.example</groupId>
            <artifactId>user-thrift-service-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

  

3、application.properties 配置如下

service.name=user-thrift-server
service.port=7911

#数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/db_user
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

  

4、UserMapper

这里使用注解的方式操作数据库

@Mapper
public interface UserMapper {

    @Select("select id, username,password, realName , mobile, email  from user where id = #{id}")
    UserInfo getUserById(@Param("id") int id);

    @Select("select id, username,password, realName , mobile, email  from user where username = #{username}")
    UserInfo getUserByName(@Param("username") String username);

    @Insert("insert into user(username,password, realName , mobile, email values(#{u.username}, #{u.password}, #{u.realName},#{u.mobile},#{u.email} )")
    void registerUser(@Param("u") UserInfo userInfo);
}

  

5、接口实现类UserServiceImpl

@Service
public class UserServiceImpl implements UserService.Iface {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserInfo getUserById(int id) throws TException {
        return userMapper.getUserById(id);
    }

    @Override
    public UserInfo getUserByName(String username) throws TException {
        return userMapper.getUserByName(username);
    }

    @Override
    public void registerUser(UserInfo userInfo) throws TException {
        userMapper.registerUser(userInfo);
    }
}

  

6、启动Thrift服务

@Configuration
public class ThriftServer {

    @Value("${service.port}")
    private int servicePort;


    @Autowired
    private UserService.Iface userService;

    //运行Thrift服务
    @PostConstruct
    public void startThriftServer() {
        TProcessor processor = new UserService.Processor<>(userService);

        TNonblockingServerSocket socket = null;
        try {
             socket = new TNonblockingServerSocket(servicePort);
        } catch (TTransportException e) {
            e.printStackTrace();
        }

        TNonblockingServer.Args args = new TNonblockingServer.Args(socket);
        args.processor(processor);
        //传输方式: 贞传输
        args.transportFactory(new TFramedTransport.Factory());
        //二进制Protocol
        args.protocolFactory(new TBinaryProtocol.Factory());

        TServer server = new TNonblockingServer(args);
        server.serve();
        System.out.println("启动用户Thrift服务成功");
    }
}

  

 六、创建用户edge服务  user-edge-service

1、pom.xml

增加libthrift引用和user-thrift-service-api模块引用

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>user-edge-service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.13.0</version>
        </dependency>

        <dependency>
            <groupId>com.example</groupId>
            <artifactId>user-thrift-service-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

  

  

2、application.properties

service.name=user-edge-server
service.port=8082

thrift.user.ip=127.0.0.1
thrift.user.port=7911

# redis config
#spring.redis.host=localhost
spring.redis.port=6379
spring.redis.timeout=30000

  

3、redis配置如下

1)Redis配置

/**
 * Redis缓存配置类
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    //缓存管理器
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        //设置缓存过期时间
        cacheManager.setDefaultExpiration(10000);
        return cacheManager;
    }

    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(host);
        factory.setPort(port);
        factory.setTimeout(timeout);
        return factory;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
        StringRedisTemplate template = new StringRedisTemplate(factory);
        setSerializer(template);//设置序列化工具
        template.afterPropertiesSet();
        return template;
    }

    private void setSerializer(StringRedisTemplate template){
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
    }
}

  

2) Redis客户端

@Component
public class RedisClient {

    @Autowired
    private RedisTemplate redisTemplate;

    public <T> T get(String key) {
        return (T)redisTemplate.opsForValue().get(key);
    }

    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public void set(String key, Object value, int timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    public void expire(String key, int timeout) {
        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

}

  

4、用户服务

@Component
public class UserServiceProvider {

    @Value("${thrift.user.ip}")
    private String serverIp;

    @Value("${thrift.user.port}")
    private int serverPort;

    public UserService.Client getUserService(){
        TSocket socket = new TSocket(serverIp, serverPort,3000);
        TTransport transport = new TFramedTransport(socket);
        try {
            transport.open();
        } catch (TTransportException e) {
            e.printStackTrace();
            return  null;
        }
        TProtocol protocol = new TBinaryProtocol(transport);
        UserService.Client client = new UserService.Client(protocol);

        return  client;

    }
}

  

5、用户Controller

login接口

@Controller
public class UserController {

    @Autowired
    private UserServiceProvider usrServiceProvider;


    @Autowired
    private RedisClient redisClient;



    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public Response login(@RequestParam("username") String username,
                      @RequestParam("password") String password){

        //1、验证用户名密码
        UserInfo userInfo = null;
        try {
            userInfo = usrServiceProvider.getUserService().getUserByName(username);

        } catch (TException e) {
            e.printStackTrace();
            return  Response.getUserNameOrPwdError();
        }
        if(userInfo == null){
            return  Response.getUserNameOrPwdError();
        }

        if(!userInfo.getPassword().equalsIgnoreCase(md5(password))){
                return  Response.getUserNameOrPwdError();
        }

        //2、生成token
        String token = genToken();


        //3. 缓存用户
        redisClient.set(token, toDTO(userInfo), 3600);

        return new LoginResponse(token);

    }
}

 

通过获得用户服务,然后调用用户服务的getUserByName方法

userInfo = usrServiceProvider.getUserService().getUserByName(username);

 

6、测试

通过login接口,带上用户名和密码进行测试