一、创建工程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接口,带上用户名和密码进行测试