Docker Kubernetes 微服务容器化实践(二) 2.1 微服务实战 thrift篇③--用户服务Service

目录

实现目标图

详细代码实现

其中一个接口逻辑,thrift调用

redis 添加

辅助

登录功能

资源下载

 


前言:服务之间的调用是通过Thrift,那如何去调用呢?我们先要生成对应的客户端,返回值为 T

  • 实现目标图

Docker Kubernetes 微服务容器化实践(二) 2.1 微服务实战 thrift篇③--用户服务Service_第1张图片

调用用户服务,对用户信息做基本操作;调用信息服务,来实现发短信和邮件;还要实现登陆功能,登陆是单点登陆,支持其他系统!

无状态redis缓存。

  • 详细代码实现

  1. 创建一个基于Maven的java模块user-edge-service,对外提供的是REST API,利用SpringBoot功能作为启动入口,如:Parent、Start-web等基础东西
    
    
        
            org.springframework.boot
            spring-boot-starter-parent
            1.5.3.RELEASE
        
        4.0.0
    
        com.imooc
        user-edge-service
        1.0-SNAPSHOT
    
    
        
            
                org.springframework.boot
                spring-boot-starter-web
            
            
                org.apache.thrift
                libthrift
                0.10.0
            
            
                com.imooc
                user-thrift-service-api
                1.0-SNAPSHOT
            
    
            
                com.imooc
                message-thrift-service-api
                1.0-SNAPSHOT
            
    
            
                org.springframework.boot
                spring-boot-starter-data-redis
            
            
                commons-lang
                commons-lang
                2.6
            
    
            
                org.springframework.boot
                spring-boot-starter-thymeleaf
            
    
    
        
    
        
            
                
                    org.apache.maven.plugins
                    maven-compiler-plugin
                    2.3.2
                    
                        1.7
                        1.7
                    
                
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                    
                        
                            
                                repackage
                            
                        
                    
                
            
        
    
    

     

  2. microservice/user-edge-service/src/main/java/com/imooc/user/ServiceApplication.java启动文件内容
    package com.imooc.user;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * Created by Michael on 2017/10/28.
     */
    @SpringBootApplication
    public class ServiceApplication {
    
        public static void main(String args[]) {
            SpringApplication.run(ServiceApplication.class, args);
        }
    }
    
  3. microservice/user-edge-service/src/main/resources/application.properties
    server.name=user-edge-service
    server.port=8082
    
    thrift.user.ip=user-service
    thrift.user.port=7911
    
    thrift.message.ip=message-service
    thrift.message.port=9090
    
    
    #redis config
    spring.redis.host=192.168.1.8
    spring.redis.port=6379
    spring.redis.timeout=30000
  4. user-edge-service/src/main/java/com/imooc/user/controller/UserController.java
    package com.imooc.user.controller;
    
    import com.imooc.thrift.user.UserInfo;
    import com.imooc.thrift.user.dto.UserDTO;
    import com.imooc.user.redis.RedisClient;
    import com.imooc.user.response.LoginResponse;
    import com.imooc.user.response.Response;
    import com.imooc.user.thrift.ServiceProvider;
    import org.apache.commons.lang.StringUtils;
    import org.apache.thrift.TException;
    import org.apache.tomcat.util.buf.HexUtils;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.security.MessageDigest;
    import java.util.Random;
    
    /**
     * Created by Michael on 2017/10/30.
     */
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private ServiceProvider serviceProvider;
    
        @Autowired
        private RedisClient redisClient;
    
        @RequestMapping(value="/login", method = RequestMethod.GET)
        public String login() {
            return "login";
        }
    
        @RequestMapping(value="/login", method = RequestMethod.POST)
        @ResponseBody
        public Response login(@RequestParam("username")String username,
                          @RequestParam("password")String password) {
    
            //1. 验证用户名密码
            UserInfo userInfo = null;
            try {
                userInfo = serviceProvider.getUserService().getUserByName(username);
            } catch (TException e) {
                e.printStackTrace();
                return Response.USERNAME_PASSWORD_INVALID;
            }
            if(userInfo==null) {
                return Response.USERNAME_PASSWORD_INVALID;
            }
            if(!userInfo.getPassword().equalsIgnoreCase(md5(password))) {
                return Response.USERNAME_PASSWORD_INVALID;
            }
    
            //2. 生成token
            String token = genToken();
    
            //3. 缓存用户
            redisClient.set(token, toDTO(userInfo), 3600);
    
            return new LoginResponse(token);
        }
    
        @RequestMapping(value = "/sendVerifyCode", method = RequestMethod.POST)
        @ResponseBody
        public Response sendVerifyCode(@RequestParam(value="mobile", required = false) String mobile,
                                       @RequestParam(value="email", required = false) String email) {
    
            String message = "Verify code is:";
            String code = randomCode("0123456789", 6);
            try {
    
                boolean result = false;
                if(StringUtils.isNotBlank(mobile)) {
                    result = serviceProvider.getMessasgeService().sendMobileMessage(mobile, message+code);
                    redisClient.set(mobile, code);
                } else if(StringUtils.isNotBlank(email)) {
                    result = serviceProvider.getMessasgeService().sendEmailMessage(email, message+code);
                    redisClient.set(email, code);
                } else {
                    return Response.MOBILE_OR_EMAIL_REQUIRED;
                }
    
                if(!result) {
                    return Response.SEND_VERIFYCODE_FAILED;
                }
            } catch (TException e) {
                e.printStackTrace();
                return Response.exception(e);
            }
    
            return Response.SUCCESS;
    
        }
    
        @RequestMapping(value="/register", method = RequestMethod.POST)
        @ResponseBody
        public Response register(@RequestParam("username") String username,
                                 @RequestParam("password") String password,
                                 @RequestParam(value="mobile", required = false) String mobile,
                                 @RequestParam(value="email", required = false) String email,
                                 @RequestParam("verifyCode") String verifyCode) {
    
            if(StringUtils.isBlank(mobile) && StringUtils.isBlank(email)) {
                return Response.MOBILE_OR_EMAIL_REQUIRED;
            }
    
            if(StringUtils.isNotBlank(mobile)) {
                String redisCode = redisClient.get(mobile);
                if(!verifyCode.equals(redisCode)) {
                    return Response.VERIFY_CODE_INVALID;
                }
            }else {
                String redisCode = redisClient.get(email);
                if(!verifyCode.equals(redisCode)) {
                    return Response.VERIFY_CODE_INVALID;
                }
            }
            UserInfo userInfo = new UserInfo();
            userInfo.setUsername(username);
            userInfo.setPassword(md5(password));
            userInfo.setMobile(mobile);
            userInfo.setEmail(email);
    
            try {
                serviceProvider.getUserService().regiserUser(userInfo);
            } catch (TException e) {
                e.printStackTrace();
                return Response.exception(e);
            }
    
            return Response.SUCCESS;
        }
    
        @RequestMapping(value="/authentication", method = RequestMethod.POST)
        @ResponseBody
        public UserDTO authentication(@RequestHeader("token") String token) {
    
            return redisClient.get(token);
        }
    
        private UserDTO toDTO(UserInfo userInfo) {
            UserDTO userDTO = new UserDTO();
            BeanUtils.copyProperties(userInfo, userDTO);
            return userDTO;
        }
    
        private String genToken() {
            return randomCode("0123456789abcdefghijklmnopqrstuvwxyz", 32);
        }
    
        private String randomCode(String s, int size) {
            StringBuilder result = new StringBuilder(size);
    
            Random random = new Random();
            for(int i=0;i

 

  • 其中一个接口逻辑,thrift调用

  1. 其中一个Ctrl,获取用户名密码需要调用Thrift接口,如何调用如2图片
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private ServiceProvider serviceProvider;
    
      
        @RequestMapping(value="/login", method = RequestMethod.POST)
        @ResponseBody
        public Response login(@RequestParam("username")String username,
                          @RequestParam("password")String password) {
    
            //1. 验证用户名密码
            UserInfo userInfo = null;
            try {
                userInfo = serviceProvider.getUserService().getUserByName(username);
            } catch (TException e) {
                e.printStackTrace();
                return Response.USERNAME_PASSWORD_INVALID;
            }
            if(userInfo==null) {
                return Response.USERNAME_PASSWORD_INVALID;
            }
            if(!userInfo.getPassword().equalsIgnoreCase(md5(password))) {
                return Response.USERNAME_PASSWORD_INVALID;
            }
    
            //2. 生成token
    
            //3. 缓存用户
    
        }
    }
    

     

  2. 构造thrift客户端连接(需要IP和端口号,传输方式,传输协议客户端要相同)初步代码,利用@Value("${XXXXX}")

Docker Kubernetes 微服务容器化实践(二) 2.1 微服务实战 thrift篇③--用户服务Service_第2张图片

  • redis 添加

  1. 启动redis
  2. pom文件 https://mvnrepository.com 搜索spring boot redis ,注意统一使用parent定义的版本去掉
    
    
        org.springframework.boot
        spring-boot-starter-data-redis
    
    
  3. microservice/user-edge-service/src/main/java/com/imooc/user/redis/RedisConfig.java
    package com.imooc.user.redis;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    
    /**
     * 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 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);
        }
    }
    

     

  4. 新增配置redis内容 application.properties
    #redis config
    spring.redis.host=192.168.1.8
    spring.redis.port=6379
    spring.redis.timeout=30000
  5. 新增microservice/user-edge-service/src/main/java/com/imooc/user/redis/RedisClient.java
    package com.imooc.user.redis;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by Michael on 2017/10/30.
     */
    @Component
    public class RedisClient {
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        public  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);
        }
    
    }
    
  6. 对于thrift自动生成UserInfo不适合存储到redis里面,我们创建一个userDTODocker Kubernetes 微服务容器化实践(二) 2.1 微服务实战 thrift篇③--用户服务Service_第3张图片Docker Kubernetes 微服务容器化实践(二) 2.1 微服务实战 thrift篇③--用户服务Service_第4张图片
  7.  user-thrift-service 启动 --> user-edge-service 启动 --> 利用PostMan测试Docker Kubernetes 微服务容器化实践(二) 2.1 微服务实战 thrift篇③--用户服务Service_第5张图片
  8.  查看redis是否写进去 get token方式

 

  • 辅助

  1. user-edge-service/src/main/java/com/imooc/user/response/LoginResponse.java
    package com.imooc.user.response;
    
    /**
     * Created by Michael on 2017/10/30.
     */
    public class LoginResponse extends Response {
    
        private String token;
    
        public LoginResponse(String token) {
            this.token = token;
        }
    
        public String getToken() {
            return token;
        }
    
        public void setToken(String token) {
            this.token = token;
        }
    }
    
  2. user-edge-service/src/main/java/com/imooc/user/response/Response.java

    package com.imooc.user.response;
    
    import java.io.Serializable;
    
    /**
     * Created by Michael on 2017/10/30.
     */
    public class Response implements Serializable {
    
        public static final Response USERNAME_PASSWORD_INVALID = new Response("1001", "username or password invalid");
    
        public static final Response MOBILE_OR_EMAIL_REQUIRED = new Response("1002", "mobile or email is required");
    
        public static final Response SEND_VERIFYCODE_FAILED = new Response("1003", "send verify code failed");
    
        public static final Response VERIFY_CODE_INVALID = new Response("1004", "verifyCode invalid");
    
    
        public static final Response SUCCESS = new Response();
    
    
    
        private String code;
        private String message;
    
        public Response() {
            this.code = "0";
            this.message = "success";
        }
        public Response(String code, String message) {
            this.code = code;
            this.message = message;
        }
    
        public static Response exception(Exception e) {
            return new Response("9999", e.getMessage());
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    

     

  • 登录功能

  1. 新增配置文件内容:消息模块
  2. 重构getService,switch 考虑不同情况
  3. 直接调用即可(跟登录相同)
  • 资源下载

  1. 下载此章节代码资源:https://download.csdn.net/download/sicily_winner/10948898
  2. 不想下载的请留邮箱

你可能感兴趣的:(thrift)