springcloud使用ajax,使用Hystrix构建SpringBoot_API Gateway解决Ajax跨域

好久没写东西分享最近看的东西了,一直看的比较杂什么都在看,但没有深层次的理解。也不拿不出手来分享,一般都是感觉项目用的上这个东西就去看,最后决定上不上。

最近在微信公众号,想做下前后端分离,但是遇到个问题就是前后端分离后Ajax调用存在跨域的风险,当然解决跨域的方法很多,包括使用jsonp返回的时候带上callback等等。由于一直在看Springboot,发现了Hystrix开源出来的hystrix dashboard可以监控服务,最后在加上SpringMVC中的@CrossOrigin。即完美的解决了跨域的问题,还能监控各个服务的调用情况。这里就不在介绍dashboard了,写的也很粗,有问题的地方可以多指教。

1.创建SpringBoot项目

8e3c1675ec41618e7cf01d53b1d9576b.png

2.引入Maven依赖包

org.springframework.boot

spring-boot-starter-web

com.netflix.hystrix

hystrix-core

1.5.12

com.netflix.hystrix

hystrix-metrics-event-stream

1.5.12

com.alibaba

fastjson

1.2.31

org.dom4j

dom4j

2.0.0

org.apache.httpcomponents

httpclient

3.创建SpringBoot启动类以及注册Hystrix Servlet

GatewayApplication.java

@SpringBootApplication

@RestController

public class GatewayApplication {

public static void main(String[] args) {

SpringApplication.run(GatewayApplication.class);

}

@RequestMapping("/")

public String index() {

return "Hello Word!";

}

}

HystrixConfig.java

@Configuration

public class HystrixConfig {

@Bean

public HystrixMetricsStreamServlet hystrixMetricsStreamServlet(){

return new HystrixMetricsStreamServlet();

}

@Bean

public ServletRegistrationBean registration(HystrixMetricsStreamServlet servlet){

ServletRegistrationBean registrationBean = new ServletRegistrationBean();

registrationBean.setServlet(servlet);

registrationBean.setEnabled(true);//是否启用该registrationBean

registrationBean.addUrlMappings("/hystrix.stream");

return registrationBean;

}

@Bean(initMethod="start")

public UrlConfigThread urlThread(){

UrlConfigThread urlConfig=new UrlConfigThread();

return urlConfig;

}

}

4.创建访问入口Controller

这里使用@CrossOrigin解决ajax跨域的问题,spring4.2增加的特性,并且区分get与post请求,以此来传递参数

HystrixController.java

@CrossOrigin

@RestController

@RequestMapping("/hystrix")

public class HystrixController {

@Autowired

private HystrixUtil hystrixUtil;

@RequestMapping(value = "/{ServiceName}/{ServiceMethod}", method = { RequestMethod.GET, RequestMethod.POST })

public ResultInfo HystrixData(@PathVariable String ServiceName,@PathVariable String ServiceMethod, HttpServletRequest request,HttpServletResponse response) throws InterruptedException, ExecutionException{

boolean isGet = request.getMethod().toLowerCase().equals("get");

Map Parameter=getParameter(request);

String url=UrlProperties.get(ServiceMethod);

ResultInfo info=new ResultInfo();

if(isGet){

info= hystrixUtil.execute(ServiceName, ServiceMethod,url,Parameter,"GET");

}else{

info= hystrixUtil.execute(ServiceName, ServiceMethod,url,Parameter,"POST");

}

return info;

}

/**

* 取出请求的参数

*/

public Map getParameter(HttpServletRequest request){

Enumeration param = request.getParameterNames();

Map map = new HashMap();

while(param.hasMoreElements()){

String key = param.nextElement();

String value = request.getParameter(key);

map.put(key, value);

}

return map;

}

}

5.创建HystrixUtil和CommandHttpCall

这里就是主要的走Hystrix的类,创建HystrixUtil转一次主要为了区分各个服务的名称

HystrixUtil.java

@Component

public class HystrixUtil {

public ResultInfo execute(String ServiceName, String ServiceMethod,String url, Map Parameter,String RequestType) throws InterruptedException, ExecutionException {

Setter setter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(ServiceName));//被调用服务

setter.andCommandKey(HystrixCommandKey.Factory.asKey(ServiceMethod));//被调用服务的一个被调用方法

setter.andCommandPropertiesDefaults( HystrixCommandProperties.Setter()

.withCircuitBreakerRequestVolumeThreshold(2)

.withCircuitBreakerSleepWindowInMilliseconds(60 * 1000).

withFallbackEnabled(true).

withExecutionIsolationThreadInterruptOnTimeout(true).withExecutionTimeoutInMilliseconds(5000));

/* 使用HystrixThreadPoolKey工厂定义线程池名称*/

/*当对同一业务依赖做隔离时使用CommandGroup做区分,

* 但是对同一依赖的不同远程调用如(一个是redis 一个是http),

* 可以使用HystrixThreadPoolKey做隔离区分.

* 最然在业务上都是相同的组,但是需要在资源上做隔离时,s

* 可以使用HystrixThreadPoolKey区分

* */

return new CommandHttpCall(setter, url, Parameter,RequestType).execute();//同步执行

//Future future = new CommandHttpCal(setter, url).queue();//异步执行

//return future.get();//需要时获取

}

}

CommandHttpCall.java

public class CommandHttpCall extends HystrixCommand{

private final String url;

private Map Parameter;

private String RequestType;

private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CommandHttpCall.class);

public CommandHttpCall(Setter setter,String url,Map Parameter,String RequestType) {

super(setter);

this.url=url;

this.Parameter=Parameter;

this.RequestType=RequestType;

}

@Override

protected ResultInfo run() throws Exception {

System.out.println("服务正被调用,当前线程:'{}'"+ Thread.currentThread().getName());

ResultInfo info = new ResultInfo(200,"ok");

if(RequestType.equals("GET")){

info=new GetHttpClient(url,Parameter).execute();

}else if(RequestType.equals("POST")){

info=new PostHttpClient(url,Parameter).execute();

}

/*Request request = new Request.Builder().url(url).build();

System.out.println(JSON.toJSONString(new OkHttpClient().newCall(request).execute().body().toString()));

info.setObj(JSON.toJSONString(new OkHttpClient().newCall(request).execute().body().toString()));*/

return info;

}

@Override

protected ResultInfo getFallback() {

return new ResultInfo(500,"服务异常,请稍后重试!");

}

}

到这里基本就是主要的代码了,为了能更灵活的使用它,增加了线程调用解析XML中配置的最终跳转的url

6.创建gateway_url.xml

http://192.168.0.56

host节点作为访问的IP加端口域名也是可以的  items下item就是各个服务的路径    ServiceMethod作为key取对应的targeturl

7.创建UrlConfigThread和UrlProperties

使用线程去扫面并放到map中避免造成重复解析url

UrlConfigThread.java

public class UrlConfigThread extends Thread{

@Override

public void run() {

// TODO Auto-generated method stub

String host = "";

try {

SAXReader reader = new SAXReader();

Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream("gateway_url.xml"));

Element root = document.getRootElement();

//先获取host

host = root.elementText("host").trim();

//获取全部的路由

Element items= root.element("items");

for(Iterator it=items.elementIterator();it.hasNext();){

Element element = (Element) it.next();

String ServiceMethod = element.attribute("ServiceMethod").getText();

String targeturl = element.attribute("targeturl").getText();

/*UrlConfig config = new UrlConfig();

config.setServiceMethod(ServiceMethod);

config.setTargeturl(targeturl);*/

UrlProperties.put(ServiceMethod, host+targeturl);

}

} catch (Exception e) {

}

}

}

UrlProperties.java

public class UrlProperties {

private static final Map urlconfig = new HashMap();

private UrlProperties(){}

public static void put(String key,String url){

UrlProperties.urlconfig.put(key, url);

}

public static String get(String key){

return UrlProperties.urlconfig.get(key);

}

}

8.下载dashboard与启动

下载jar或者war看你自己了,启动hystrix-dashboard和刚刚创建的项目

5328200cba4e2724df36be6c1abbf12a.png

输入localhost:8001/hystrix.stream,之后点击"Add Stream",最后点击"Monitor Stream"即可。

7baee5dbcb7446df410e2cdc9f15acfa.png

至此项目的创建已经完成了,注意我在CommandHttpCall中区分了get和post,这里由于存在多种可能行比如你的post需要提交json参数而非key--value或者form表单等,http的代码我就不贴了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值