概念
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
httpClient使用
第一步:编写配置文件 HttpClient.properties
#最大连接数
http.maxTotal = 1000
#并发数
http.defaultMaxPerRoute = 20
#创建连接的最长时间
http.connectTimeout=5000
#从连接池中获取到连接的最长时间
http.connectionRequestTimeout=500
#数据传输的最长时间
http.socketTimeout=5000
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true
第二步:写httpClient配置类 HttpClientConfig
package com.jt.config;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* 获取httpClient主要参数配置类
* @author wangcheng
*/
@Configuration
@PropertySource("classpath:/properties/httpClient.properties")
public class HttpClientConfig {
/**最大链接数*/
@Value("${http.maxTotal}")
private Integer maxTotal;
/**最大并发链接数*/
@Value("${http.defaultMaxPerRoute}")
private Integer defaultMaxPerRoute;
/**链接最大时间*/
@Value("${http.connectTimeout}")
private Integer connectionTimeout;
/**链接获取最长时间*/
@Value("${http.connectionRequestTimeout}")
private Integer connectionRequestTimeout;
/**数据传输最长时间*/
@Value("${http.socketTimeout}")
private Integer socketTimeout;
/**提交时检查连接是否可用*/
@Value("${http.staleConnectionCheckEnabled}")
private Boolean staleConnectionCheckEnabled;
/**定义链接池*/
@Bean("httpClientConnectionManager")
public PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager(){
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotal);
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return connectionManager;
}
/**定义httpClient创建者*/
@Bean("httpClientBuilder")
public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager poolingHttpClientConnectionManager){
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
return httpClientBuilder;
}
/**注入httpClientBuilder,获取httpClient*/
@Bean
public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder){
return httpClientBuilder.build();
}
/**创建requestConfig创建者*/
@Bean(name = "builder")
public RequestConfig.Builder getBuilder(){
RequestConfig.Builder builder = RequestConfig.custom();
builder.setConnectTimeout(connectionTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout)
.setSocketTimeout(socketTimeout)
.setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
return builder;
}
/**
* 注入requestConfigBuilder获取requestConfig对象
* @param builder
* @return
*/
@Bean
public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder){
return builder.build();
}
}
第三步:写httpClient服务类 HttpClientService
package com.jt.service;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Map;
/**
* @author wangcheng
*/
@Service
public class HttpclientService {
@Autowired
private CloseableHttpClient httpClient;
@Autowired
private RequestConfig requestConfig;
public String doGet(String url, Map<String,String> params,String charset){
if(StringUtils.isEmpty(charset)){
charset = "UTF-8";
}
if (params != null){
url +="?";
for (Map.Entry<String,String> param : params.entrySet()) {
String key = param.getKey();
String value = param.getValue();
url = url + key + "=" +value +"&";
}
url = url.substring(0,url.length()-1);
}
HttpGet httpGet = new HttpGet(url);
//定义超时时间
httpGet.setConfig(requestConfig);
String result = null;
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200){
result = EntityUtils.toString(response.getEntity(),charset);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
return result;
}
/**
* 重载方法
* @param url
* @return
*/
public String doGet(String url){
return doGet(url,null,null);
}
/**
* 重载方法
* @param url
* @param params
* @return
*/
public String doGet(String url,Map<String,String> params){
return doGet(url,params,null);
}
}
第四步:调用httpClient服务,进行访问
package com.jt.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import com.jt.util.HttpClientService;
import com.jt.util.ObjectMapperUtil;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private HttpClientService httpClient;
@Override
public Item findItemById(Long itemId) {
String url = "http://www.jd.com/web/item/findItemById/"+itemId;
String itemJson = httpClient.doGet(url);
//将json数据转化为对象,对象转json get方法
//json转对象调用 set方法
System.out.println(itemJson);
return ObjectMapperUtil.toObject(itemJson, Item.class);
}
@Override
public ItemDesc findItemDescById(Long itemId) {
String url ="http://www.jd.com/web/item/findDescById/"+itemId;
String itemDescJson = httpClient.doGet(url);
System.out.println(itemDescJson);
return ObjectMapperUtil.toObject(itemDescJson, ItemDesc.class);
}
}
Dubbo使用
第一步:在公共模块中定义Dubbo接口
package com.jt.dubbo;
import com.jt.pojo.User;
/**
* @author wangcheng
*/
public interface DubboUserService {
/**
* web页面实现注册服务接口
* @param user
* @return
*/
int saveUser(User user);
/**
* web页面输入信息,sso实现登陆接口
* @param user
* @return
*/
String doLogin(User user);
}
第二步:编写服务提供者,提供者基本上是属于业务实现,是上一步接口的具体实现类以及相关业务处理
package com.jt.jtsso.dubbo;
import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.dubbo.DubboUserService;
import com.jt.jtsso.dao.UserDao;
import com.jt.pojo.User;
import com.jt.utils.ObjectMapperUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import redis.clients.jedis.ShardedJedis;
import java.util.Date;
/**
* @author wangcheng
*/
@Service(timeout = 3000)
public class DubboUserServiceImpl implements DubboUserService {
@Autowired
private UserDao userDao;
@Autowired
private ShardedJedis shardedJedis;
@Override
public int saveUser(User user) {
//对密码进行加密 利用digestUtils工具类进行加密
String password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setEmail(user.getPhone())
.setPassword(password)
.setCreated(new Date())
.setUpdated(user.getCreated());
int row = userDao.insert(user);
return row;
}
/**
* 1.先查询数据库,看用户是否存在
* 2.将用户信息保存到redis中
* 3.返回页面token
* @param user
* @return
*/
@Override
public String doLogin(User user) {
String password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
QueryWrapper<User> queryWrapper = new QueryWrapper<User>(user);
User userDB = userDao.selectOne(queryWrapper);
String token = null;
//用户存在
if (userDB != null){
String tokenTemp = "JT_TICKET" + System.currentTimeMillis() + userDB.getUsername();
//将tokenTemp转化十六进制数据,脱敏
tokenTemp = DigestUtils.md5DigestAsHex(tokenTemp.getBytes());
userDB.setPassword("123456,你猜对了嘛?");
String userDBJson = ObjectMapperUtils.toJSON(userDB);
shardedJedis.setex(tokenTemp,7*24*3600,userDBJson);
token = tokenTemp;
}
return token;
}
}
服务提供者相关的配置
server:
port: 8093
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/jdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#mybatis-plus
mybatis-plus:
type-aliases-package: com.jd.pojo
mapper-locations: classpath:/mppers/*.xml
configuration:
map-underscore-to-camel-case: true
#配置日志信息
logging:
level:
com.jt: debug
#dubbo配置信息
dubbo:
scan:
base-packages: com.jd
application:
name: provider-user
registry:
address: zookeeper://49.235.87.70:2181?backup=49.235.87.70:2182,49.235.87.70:2183
protocol:
name: dubbo
port: 20880
第三步:编写服务消费者,服务消费者是调用接口的服务,通过调用接口进行业务实现。
服务消费者配置:
server:
port: 8092
spring: #定义springmvc视图解析器
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
resources:
static-locations: classpath:/META-INF/resources/
#dubbo相关配置
dubbo:
scan:
base-packages: com.xx
application:
name: consumer-user
registry:
address: zookeeper://49.235.87.70:2181?backup=49.235.87.70:2182,49.235.87.70:2183
调用接口:
package com.xx.controller;
/**
* @author wangcheng
*/
@Controller
@RequestMapping("/user")
@Slf4j
public class UserController {
@Reference(timeout = 3000,check = false)
private DubboUserService dubboUserService;
/**
* restful风格进行页面跳转
* @param moduleName
* @return
*/
@RequestMapping("/{moduleName}")
public String pageController(@PathVariable String moduleName){
return moduleName;
}
/**
* 用户注册,通过dubbo调用sso向数据库插入数据
* @param user
* @return
*/
@RequestMapping("/doRegister")
@ResponseBody
public SysResult doUserRegister(User user){
//dubbo远程调用jt-sso服务实现用户注册
dubboUserService.saveUser(user);
return SysResult.success();
}
@RequestMapping("/doLogin")
@ResponseBody
public SysResult doUserLogin(User user, HttpServletResponse response){
//用户第一次登陆
String token = dubboUserService.doLogin(user);
if (StringUtils.isEmpty(token)){
log.info("用户不存在,登陆失败");
return SysResult.fail();
}
//用户存在将token封装到cookie,实现用户一定时间内免登录
Cookie cookie = new Cookie("JT_TICKET",token);
//设置cookie存活时间
cookie.setMaxAge(7*24*3600);
cookie.setPath("/");
//cookie共享
cookie.setDomain("xx.com");
response.addCookie(cookie);
return SysResult.success();
}
}
总结:dubbo适合在项目内部使用,实现不同模块服务之间的互相调用,而httpClient适合不同项目之间的远程服务调用