目录
实现目标图
详细代码实现
其中一个接口逻辑,thrift调用
redis 添加
辅助
登录功能
资源下载
前言:服务之间的调用是通过Thrift,那如何去调用呢?我们先要生成对应的客户端,返回值为 T
调用用户服务,对用户信息做基本操作;调用信息服务,来实现发短信和邮件;还要实现登陆功能,登陆是单点登陆,支持其他系统!
无状态redis缓存。
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
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);
}
}
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
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
@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. 缓存用户
}
}
org.springframework.boot
spring-boot-starter-data-redis
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);
}
}
#redis config
spring.redis.host=192.168.1.8
spring.redis.port=6379
spring.redis.timeout=30000
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);
}
}
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;
}
}
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;
}
}