input发送a.jax_Java EE 7 / JAX-RS 2.0 – REST上的CORS

input发送a.jax

Java EE REST应用程序在开箱即用的开发机器上通常可以很好地运行,在该机器上,所有服务器端资源和客户端UI都指向“ localhost”或127.0.0.1。 但是,当涉及跨域部署时(当REST客户端不再与托管REST API的服务器位于同一域时),则需要一些解决方法。 本文是关于Java EE 7 / JAX-RS 2.0 REST API时如何使跨域或更广称为跨域资源共享(又称为CORS)的。 本文无意讨论有关浏览器和其他与安全性相关的机制,您可能会在其他网站上找到它。 但是我们真正想要在这里实现的是再次使事情尽快运作。

问题是什么?

演示Java EE 7(JAX-RS 2.0)REST服务

在本文中,我将仅为演示目的而编写一个基于Java EE 7 JAX-RS 2.0的简单REST Web服务和客户端。

在这里,我将定义一个接口,以REST服务的url路径以及为HTTP响应接受的HTTP方法和MIME Type对其进行注释。

RESTCorsDemoResourceProxy.java的代码:

package com.developerscrappad.intf;import java.io.Serializable;
import javax.ejb.Local;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;@Local
@Path( "rest-cors-demo" )
public interface RESTCorsDemoResourceProxy extends Serializable {@GET@Path( "get-method" )@Produces( MediaType.APPLICATION_JSON )public Response getMethod();@PUT@Path( "put-method" )@Produces( MediaType.APPLICATION_JSON )public Response putMethod();@POST@Path( "post-method" )@Produces( MediaType.APPLICATION_JSON )public Response postMethod();@DELETE@Path( "delete-method" )@Produces( MediaType.APPLICATION_JSON )public Response deleteMethod();
}

RESTCorsDemoResource.java的代码:

package com.developerscrappad.business;import com.developerscrappad.intf.RESTCorsDemoResourceProxy;
import javax.ejb.Stateless;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.core.Response;@Stateless( name = "RESTCorsDemoResource", mappedName = "ejb/RESTCorsDemoResource" )
public class RESTCorsDemoResource implements RESTCorsDemoResourceProxy {@Overridepublic Response getMethod() {JsonObjectBuilder jsonObjBuilder = Json.createObjectBuilder();jsonObjBuilder.add( "message", "get method ok" );JsonObject jsonObj = jsonObjBuilder.build();return Response.status( Response.Status.OK ).entity( jsonObj.toString() ).build();}@Overridepublic Response putMethod() {JsonObjectBuilder jsonObjBuilder = Json.createObjectBuilder();jsonObjBuilder.add( "message", "get method ok" );JsonObject jsonObj = jsonObjBuilder.build();return Response.status( Response.Status.ACCEPTED ).entity( jsonObj.toString() ).build();}@Overridepublic Response postMethod() {JsonObjectBuilder jsonObjBuilder = Json.createObjectBuilder();jsonObjBuilder.add( "message", "post method ok" );JsonObject jsonObj = jsonObjBuilder.build();return Response.status( Response.Status.CREATED ).entity( jsonObj.toString() ).build();}@Overridepublic Response deleteMethod() {JsonObjectBuilder jsonObjBuilder = Json.createObjectBuilder();jsonObjBuilder.add( "message", "delete method ok" );JsonObject jsonObj = jsonObjBuilder.build();return Response.status( Response.Status.ACCEPTED ).entity( jsonObj.toString() ).build();}
}

RESTCorsDemoResource中的代码简单明了,但是请记住,这只是一个演示应用程序,在其业务逻辑中没有有效的目的。 RESTCorsDemoResource类实现在接口RESTCorsDemoResourceProxy中定义的方法签名。 它有几种方法可以通过特定的HTTP方法(例如GET,PUT,POST和DELETE)处理传入的HTTP请求,并且在方法结束时,在完成该过程后将返回一条简单的JSON消息。

不要忘了下面的web.xml ,当路径检测到“ / rest-api / * ”(例如http:// <host>:<port>)时,该web.xml会告诉应用服务器将其视为任何传入HTTP请求的REST API调用。 / AppName / rest-api / get-method /)。

web.xml中的内容:

javax.ws.rs.core.Application1javax.ws.rs.core.Application/rest-api/*

部署方式

让我们将以上内容打包到一个名为RESTCorsDemo.war的war文件中,并将其部署到与Java EE 7兼容的应用服务器中。 在我这方面,我正在使用默认设置在Glassfish 4.0上运行此程序,该默认设置位于具有公共域的计算机上developerscrappad.com

部署后,REST服务的URL应如下所示:

方法 REST URL
RESTCorsDemoResourceProxy.getMethod() http://developerscrappad.com/RESTCorsDemo/rest-api/rest-cors-demo/get-method/
RESTCorsDemoResourceProxy.postMethod() http://developerscrappad.com/RESTCorsDemo/rest-api/rest-cors-demo/post-method/
RESTCorsDemoResourceProxy.putMethod() http://developerscrappad.com/RESTCorsDemo/rest-api/rest-cors-demo/put-method/
RESTCorsDemoResourceProxy.deleteMethod() http://developerscrappad.com/RESTCorsDemo/rest-api/rest-cors-demo/delete-method/

HTML REST客户端

在本地计算机上,我将创建一个简单HTML页面,以通过以下方式调用已部署的REST服务器资源:

rest-test.html的代码:

<!DOCTYPE html>
<html><head><title>REST Tester</title><meta charset="UTF-8"></head><body><div id="logMsgDiv"></div><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script><script type="text/javascript">var $ = jQuery.noConflict();$.ajax( {cache: false,crossDomain: true,dataType: "json",url: "http://developerscrappad.com:8080/RESTCorsDemo/rest-api/rest-cors-demo/get-method/",type: "GET",success: function( jsonObj, textStatus, xhr ) {var htmlContent = $( "#logMsgDiv" ).html( ) + "<p>" + jsonObj.message + "</p>";$( "#logMsgDiv" ).html( htmlContent );},error: function( xhr, textStatus, errorThrown ) {console.log( "HTTP Status: " + xhr.status );console.log( "Error textStatus: " + textStatus );console.log( "Error thrown: " + errorThrown );}} );$.ajax( {cache: false,crossDomain: true,dataType: "json",url: "http://developerscrappad.com:8080/RESTCorsDemo/rest-api/rest-cors-demo/post-method/",type: "POST",success: function( jsonObj, textStatus, xhr ) {var htmlContent = $( "#logMsgDiv" ).html( ) + "<p>" + jsonObj.message + "</p>";$( "#logMsgDiv" ).html( htmlContent );},error: function( xhr, textStatus, errorThrown ) {console.log( "HTTP Status: " + xhr.status );console.log( "Error textStatus: " + textStatus );console.log( "Error thrown: " + errorThrown );}} );$.ajax( {cache: false,crossDomain: true,dataType: "json",url: "http://developerscrappad.com:8080/RESTCorsDemo/rest-api/rest-cors-demo/put-method/",type: "PUT",success: function( jsonObj, textStatus, xhr ) {var htmlContent = $( "#logMsgDiv" ).html( ) + "<p>" + jsonObj.message + "</p>";$( "#logMsgDiv" ).html( htmlContent );},error: function( xhr, textStatus, errorThrown ) {console.log( "HTTP Status: " + xhr.status );console.log( "Error textStatus: " + textStatus );console.log( "Error thrown: " + errorThrown );}} );$.ajax( {cache: false,crossDomain: true,dataType: "json",url: "http://developerscrappad.com:8080/RESTCorsDemo/rest-api/rest-cors-demo/delete-method/",type: "DELETE",success: function( jsonObj, textStatus, xhr ) {var htmlContent = $( "#logMsgDiv" ).html( ) + "<p>" + jsonObj.message + "</p>";$( "#logMsgDiv" ).html( htmlContent );},error: function( xhr, textStatus, errorThrown ) {console.log( "HTTP Status: " + xhr.status );console.log( "Error textStatus: " + textStatus );console.log( "Error thrown: " + errorThrown );}} );</script></body>
</html>

在这里,我将jQuery的ajax对象用于带有已定义选项的REST Services调用。 rest-test.html的目的是使用适当的HTTP方法调用REST服务URL,并获取响应作为JSON结果以供以后处理。 我不会在这里详细介绍,但是如果您想了解更多有关$ .ajax调用选项的信息,可以访问jQuery的文档站点 。

当我们运行rest-test.html时会发生什么?

当我在Firefox浏览器上运行rest-test.html文件时,配备了Firebug插件 ,以下是我得到的屏幕截图。

屏幕快照:Firebug控制台选项卡结果

屏幕快照:Firebug控制台选项卡结果

屏幕截图:Firebug的“ Net”选项卡结果

屏幕截图:Firebug的“ Net”选项卡结果

如您所见,当我在控制台选项卡上选中时,“ / rest-api / rest-cors-demo / get-method / ”和“ / rest-api / rest-cors-demo / post-method / ”返回了正确的HTTP状态,但我可以绝对确定该方法未在远程Glassfish应用服务器上执行,REST服务调用只是被绕过,在rest-test.html客户端上,它直接进入了$ .ajax错误回调。 当我如图所示检查Firebug网络选项卡时,“ / rest-api / rest-cors-demo / put-method / ”和“ / rest-api / rest-cors-demo / delete-method / ”如何处理?在其中一个屏幕截图中,浏览器通过触发OPTIONS作为HTTP方法而不是PUT和DELETE发送了预检请求。 这种现象与服务器端和浏览器的安全有关。 我在页面底部还编译了与此相关的其他一些网站。

如何使CORS在Java EE 7 / JAX-RS 2.0(通过拦截器)中工作

为了在客户端和服务器端REST资源上进行跨域调用或简称为CORS,我创建了两个JAX-RS 2.0拦截器类,一个实现了ContainerRequestFilter ,另一个实现了ContainerResponseFilter 。

ContainerResponseFilter中的其他HTTP标头

浏览器将需要一些其他的HTTP标头来响应它,以进一步验证服务器端资源是否允许跨域/跨域资源共享以及它允许​​的安全级别或限制级别。 这些标头在启用CORS时开箱即用。

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, DELETE, PUT

这些额外的HTTP标头集可以通过将其包含在实现ContainerResponseFilter的类中而包含在返回到浏览器时的HTTP响应中。

**但请注意:拥有“访问控制允许来源:*”将允许接受所有呼叫,而与客户端的位置无关。 有多种方法可以进一步限制此限制,因为您只希望服务器端仅允许来自特定域的REST服务调用。 请查看页面底部的相关文章。

RESTCorsDemoResponseFilter.java的代码:

package com.developerscrappad.filter;import java.io.IOException;
import java.util.logging.Logger;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;@Provider
@PreMatching
public class RESTCorsDemoResponseFilter implements ContainerResponseFilter {private final static Logger log = Logger.getLogger( RESTCorsDemoResponseFilter.class.getName() );@Overridepublic void filter( ContainerRequestContext requestCtx, ContainerResponseContext responseCtx ) throws IOException {log.info( "Executing REST response filter" );responseCtx.getHeaders().add( "Access-Control-Allow-Origin", "*" );responseCtx.getHeaders().add( "Access-Control-Allow-Credentials", "true" );responseCtx.getHeaders().add( "Access-Control-Allow-Methods", "GET, POST, DELETE, PUT" );}
}

处理浏览器预检请求HTTP方法:选项

实现ContainerResponseFilterRESTCorsDemoResponseFilter类仅解决了部分问题。 我们仍然必须处理浏览器对PUT和DELETE HTTP方法的飞行前请求。 大多数流行的浏览器的基础飞行前请求机制都以某种方式工作,即它们使用OPTIONS作为HTTP方法发送一个请求,只是为了测试水域。 如果服务器端资源确认请求的路径URL,并允许接受PUT或DELETE HTTP方法进行处理,则服务器端通常将必须发送HTTP Status 200(OK)响应(或任何20x HTTP Status)返回到浏览器,然后浏览器将实际请求作为HTTP方法PUT或DELETE发送给浏览器。 但是,此机制必须由开发人员手动实现。 因此,我以RESTCorsDemoRequestFilter的名称实现了一个新类, 该类实现了以下针对此机制显示的ContainerRequestFilter

RESTCorsDemoRequestFilter.java的代码:

package com.developerscrappad.filter;import java.io.IOException;
import java.util.logging.Logger;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;@Provider
@PreMatching
public class RESTCorsDemoRequestFilter implements ContainerRequestFilter {private final static Logger log = Logger.getLogger( RESTCorsDemoRequestFilter.class.getName() );@Overridepublic void filter( ContainerRequestContext requestCtx ) throws IOException {log.info( "Executing REST request filter" );// When HttpMethod comes as OPTIONS, just acknowledge that it accepts...if ( requestCtx.getRequest().getMethod().equals( "OPTIONS" ) ) {log.info( "HTTP Method (OPTIONS) - Detected!" );// Just send a OK signal back to the browserrequestCtx.abortWith( Response.status( Response.Status.OK ).build() );}}
}

结果

之后, RESTCorsDemoResponseFilterRESTCorsDemoRequestFilter包含在应用程序中并进行部署。 然后,我再次在浏览器上重新运行rest-test.html 。 结果,JAX-RS 2.0应用程序很好地处理了来自不同位置的具有不同HTTP方法GET,POST,PUT和DELETE的所有HTTP请求。 下面的屏幕截图是我的浏览器成功执行的HTTP请求。 Firebug控制台和NET Tab的这些结果是预期的:

屏幕快照:Firebug控制台选项卡

屏幕快照:Firebug控制台选项卡

屏幕截图:Firebug的“ Net”选项卡

屏幕截图:Firebug的“ Net”选项卡

最后的话

在拦截诸如启用CORS之类的方案的REST相关请求和响应时,JAX-RS 2.0拦截器非常方便。 如果您正在为Java项目使用REST库的特定实现,例如Jersey或RESTEasy ,请检查如何具体实现请求和响应拦截器,应用上述技术,您应该可以获得相同的结果。 相同的原理几乎相同。

好吧,希望本文能帮助您解决Java EE 7 / JAX-RS 2.0 REST项目上的跨域或CORS问题。

感谢您的阅读。

相关文章:

  • http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
  • http://www.html5rocks.com/zh-CN/tutorials/cors/
  • http://www.w3.org/TR/cors/
  • https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS

翻译自: https://www.javacodegeeks.com/2014/11/java-ee-7-jax-rs-2-0-cors-on-rest.html

input发送a.jax

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339373.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用C/C++开发《Photoshop》图像处理软件

今晚课题【长按识别图中二维码】

javaone_代理的JavaOne 2014观察

javaone我今年无法参加JavaOne&#xff0c;但很高兴看到一些在线资源涵盖了JavaOne 2014的活动。在本文中&#xff0c;我总结了JavaOne 2014的一些观察结果&#xff0c;并提供了指向提供这些观察结果的参考的链接。提供有关这些观察的更多背景细节。 列出的观察结果没有特别的顺…

java怎么兼容switch_java – Switch语句给出了不兼容类型错误

我正在尝试编译,我收到此错误&#xff1a;enigma/Rotor.java:30: incompatible types found : java.lang.String required: int switch(name){1 error为什么我收到此错误&#xff1f;我如何解决它&#xff1f;它在包中,我似乎无法弄明白.这是代码&#xff1a;String label;Roto…

基于java的心理健康_基于SSM的JAVA心理健康网

今天记录的项目是心理健康网的规划与设计&#xff0c;这个项目是这么回事&#xff1a;心理健康是关系到人才质量的重要问题。随着网络时代的发展,传统的大学生心理健康教育教学方式和课程资源远不能解决当代大学生的心理问题。本文通过对学生心理健康网的规划与设计进行研究。首…

C/C++打造《百万级人脸识别系统》

今晚课题【长按识别图中二维码】

rhq监控软件_RHQ指标的WildFly子系统

rhq监控软件对于RHQ-Metrics&#xff0c;我已经开始为WildFly 8编写一个子系统&#xff0c;该子系统能够在WildFly内收集度量&#xff0c;然后以固定的时间间隔&#xff08;当前为每分钟&#xff09;将其发送到RHQ-Metrics服务器。 下一张图是该发件人连续运行1.5天时结果的可…

java中content啥意思_JSTL标签中的body-content标签体内容输出格式的介绍

我们在JSTL标签中看到“JSP”这种类型的定义&#xff0c;但是不知道它是什么意思&#xff0c;其实它的意思就是定义了一个JSTL标签内部是否允许使用JSP表达式&#xff0c;先来了解什么是JSTL标签体&#xff0c;请看代码&#xff1a;//中间即为JSTL标签体再来看看什么是jsp表达式…

打造最强加密工具之《绝密信息传递》

今晚课题【长按识别图中二维码】

jooq sql_用jOOQ用Java编写SQL

jooq sqljOOQ是“数据库优先”类型的安全SQL API&#xff0c;使您可以直观地用Java编写SQL&#xff0c;就像Java编译器本身支持SQL语言一样。 所有数据库模式&#xff0c;表&#xff0c;列&#xff0c;过程和其他对象均作为Java对象提供&#xff0c;可以直接在jOOQ SQL API中使…

C/C++打造经典推箱子小游戏

今晚课题【长按识别图中二维码】

php mysql crud demo_基于php和mysql的简单的dao类实现crud操作功能_PHP教程

代码如下:public function SimpleDao() {if ($this->_con null) {$this->_con mysql_connect("localhost", "root", "123456");if ($this->_con FALSE) {echo("connect to db server failed.");$this->_con null;retu…

di容器_DI容器是代码污染者

di容器尽管依赖项注入 &#xff08;aka&#xff0c;“ DI”&#xff09;是一种在OOP中组成对象的自然技术&#xff08;在Martin Fowler引入该术语之前就已知道&#xff09;&#xff0c;但Spring IoC &#xff0c; Google Guice &#xff0c; Java EE6 CDI &#xff0c; Dagger和…

C/C++高级算法之绘制曼德布洛特集

今晚课题【长按识别图中二维码】

python mysql 连接6_寒假学习进度-6(Python连接MySQL数据库)

Python连接mysql和操作软件&#xff1a;pycharm开始在pycharm下面的Terminal中安装mysql时提醒pip版本不够&#xff0c;所以需要先升级一下pippython -m pip install --upgrade pip升级完pip之后就可以下载mysqlpip install mysql下载完成后在setting中查看进行代码测试#!/usr/…

intellij 快捷键_IntelliJ中的键盘快捷键

intellij 快捷键我上周参加了Hadi Hariri在JavaOne上的演讲。 他介绍了很多我不知道的IntelliJ键盘快捷键。 非常有用的谈话。 我在下面列出了一些最有用的。 Cmd-1&#xff1a;将焦点移到“项目”窗口 在此输入任何类名&#xff08;包括使用Camel Case&#xff0c;例如HW来查…

C/C++中*和的用法详解

C中&和*的用法一直是非常让人头疼的难点&#xff0c;课本博客上讲这些知识点一般都是分开讲其用法的&#xff0c;没有详细的总结&#xff0c;导致我在这方面的知识结构格外混乱&#xff0c;在网上找到了一篇英文文章简单总结了这两个符号的一些用法&#xff0c;都是一些比较…

java 实现按规则自增功能_java运算符详解 - osc_74vaali6的个人空间 - OSCHINA - 中文开源技术交流社区...

java基础(2)--运算符详解自增自减规则自增自减就是常用的 a a 或者 a a;前者是后缀式&#xff0c;先把a赋值给a,再加一&#xff1b;后者是后缀式&#xff0c;先加一&#xff0c;在赋值给a;而且a,a并不是原子操作&#xff0c;在当线程环境下并不会出错&#xff0c;当放在多线程…

jsf 单元测试_构建和测试JSF.next

jsf 单元测试JSF 2.3专家组正在努力确定哪些功能将成为即将发布的版本的一部分。 JSF团队一直在努力改善CDI的一致性。 JSF 2.3代码库中已经有许多新功能可以开始测试。 我将尝试使本文保持最新状态&#xff0c;并添加最新功能。 有关最新参考&#xff0c;请参阅Manfred的博客。…

C++ 异常的详细介绍

C 异常的详解程序有时会遇到运行阶段错误&#xff0c;导致程序无法正常执行下去。c异常为处理这种情况提供了一种功能强大的而灵活的工具。异常是相对比较新的C功能&#xff0c;有些老编译器可能没有实现。另外&#xff0c;有些编译器默认关闭这种特性&#xff0c;我们可能需要…