有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用JAXR和Resteasy、Angular和Wildfly10处理COR

我在wildfly 10上有一个resteasy Web服务,与我的angular客户端在同一台机器上

  • 获取请求工作
  • Put和delete被调用了2次,据我所知,这是因为飞行前的请求已经完成。一个curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i可以很好地处理它,而无需执行两次请求。相反,当使用angular client调用时,restWebService会被调用两次

我试图添加一个corsFilter,但它不仅帮助我获取请求,而且没有帮助我解决问题

package com.solarity.app; // {{ groupId}}.app

import com.solarity.rest.CompanyRestService;
import com.solarity.rest.PersonRestService;
import org.jboss.resteasy.plugins.interceptors.CorsFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

@ApplicationPath("/")
public class InitApplication extends Application {

    /**
    * 
    */
    Set<Object> singletons;
    HashSet<Class<?>> webServiceClasses;

    public InitApplication() {
        super();
        webServiceClasses = new HashSet<>();
        webServiceClasses.add(PersonRestService.class);
        webServiceClasses.add(CompanyRestService.class);


        singletons = new LinkedHashSet<>();
        singletons.add(this.getCorsFilter());

    }

    @Override
    public Set<Class<?>> getClasses() {
        return webServiceClasses;
    }

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }

    private CorsFilter getCorsFilter() {
        CorsFilter result = new CorsFilter();
        result.getAllowedOrigins().add("http://localhost:4200");

        return result;
    }
}

我试图在我的Web服务中实现一个选项方法,但没有成功

package com.solarity.rest; // Note your package will be {{ groupId }}.rest

import com.solarity.entities.CompanyEntity;
import com.solarity.entities.PersonEntity;
import com.solarity.service.CompanyService;
import com.solarity.service.PersonService;
import com.solarity.util.ResponseUtil;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
* 
*
*/
@Path("/company")
public class CompanyRestService {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    private CompanyService companyService = new CompanyService();



    @GET // This annotation indicates GET request
    @Path("/")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAll() {
        Object response = null;
        String errMsg = null;
        int responseStatus = -1;
        try {
            this.logger.debug("companyServcfindAll----------------debug");
            this.logger.warn("companyServcfindAll----------------WARN");
            response = companyService.findAll();
        } catch (Exception e) {
            errMsg = "Error getting all persons";
            logger.error(errMsg, e);
        }
        return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.GET);
    }


    /**
    * curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i
    *
    * @param id
    * @return
    */
    @DELETE
    @Path("/{param}")
    public Response delete(@PathParam("param") Integer id){
        Object response = null;
        String errMsg = null;
        int responseStatus = -1;
        try {
            logger.debug("Deleting entity", id);
            companyService.delete(id);
            responseStatus = HttpStatus.SC_OK;
        } catch (Exception e) {
            errMsg = "Error Deleting Entity:" + id;
            logger.error(errMsg, e);
            response = errMsg;
            responseStatus = HttpStatus.SC_METHOD_FAILURE;
        }

        return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.DELETE);
    }

    /**
    * Not working
    * @return
    */
    @OPTIONS
    @Path("{path : .*}")
    public Response options() {
        return Response.ok("")
                .header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
                .header("Access-Control-Allow-Credentials", "true")
                .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
                .header("Access-Control-Max-Age", "1209600")
                .build();
    }

}//end Class

这是我的回答课

package com.solarity.util;

import org.apache.http.HttpStatus;

import javax.ws.rs.core.Response;

public class ResponseUtil {


    /**
    *
        Built to counter a Angular cross-reference problem
            Adapted for Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/dlssResteasy1-1.0-SNAPSHOT/person/getPersonsAsJSON. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
            source answer https://stackoverflow.com/questions/23450494/how-to-enable-cross-domain-requests-on-jax-rs-web-services?answertab=votes#tab-top

        More Documentation about CORS on https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS


    * @param param the object to send if errorMsg is null
    * @param errorMsg if not null sends an error code with error Message
    * @param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
    * @return an altered response which is customized
    */
    public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
        Response result = null;
        int rStatus = responseStatus;
        if (errorMsg != null && responseStatus <= 0) {
            rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
        } else if (errorMsg == null && responseStatus <= 0){
            rStatus = HttpStatus.SC_OK;
        }
        if ( errorMsg == null ) {
            result = Response
                    .status(rStatus)
                    .entity(param)
                    .build();
        }else{
            result = Response.status(rStatus)
                    .entity(errorMsg)
                    .build();
        }
        return result;
    }

}

下面是调试到FF的结果 enter image description here


共 (3) 个答案

  1. # 1 楼答案

    您可以在网络选项卡中查看Chrome DevTools的流量

  2. # 2 楼答案

    首先,有一个documentation about CORS我必须阅读才能理解,我无法避免,正如我所希望的那样

    两个来自Angular的电话

    我问题的部分答案实际上是Angular的两个电话

    我不明白,每次在httpclient.put()上对subscribe的调用完成时,调用就完成了

    HttpClient Documentation

    Calling the subscribe() method executes the observable, which is what initiates the DELETE request.

    所以我所做的是:

    1. 调用methodResult = httpclient.put('someUrl', someData, someHeader).subscribe({ data => { console.log('added') });
    2. 在该方法的调用方上,使用abovePutMethod.subscribe( data => { doSomeThingWithComponentRefresh })再次调用

    因此,只需拨打一次订阅电话就解决了我的两次呼叫问题


    对于CORS协议的其余部分

    棱角客户端

    //UrlHelper
    public static putHttpRequestOptions = {
        headers: new HttpHeaders({
        'Content-Type': 'application/json',
        })
    };
    
    //Function call somewhere
    const result = this.httpClient.put(url, jsonStringValues, UrlHelper.putHttpRequestOptions);
    

    Java Resteasy服务器

    // InitApplication extends Application
    
    public InitApplication() {
        super();
        webServiceClasses = new HashSet<>();
        webServiceClasses.add(PersonRestService.class);
        webServiceClasses.add(CompanyRestService.class);
    
    
        singletons = new LinkedHashSet<>();
        singletons.add(this.getCorsFilter());
    
    }
    
    private CorsFilter getCorsFilter() {
        CorsFilter result = new CorsFilter();
        result.getAllowedOrigins().add("*");
        result.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH");
        result.setCorsMaxAge(86400);//Max in FF 86400=24h https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
        //
        return result;
    }
    
    
    // RestWebService
    @PUT
    @Path("/")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response put(CompanyEntity entity ){
        Object response = null;
        String errMsg = null;
        int responseStatus = -1;
        try {
            logger.debug("Received entity", entity);
            companyService.persist(entity);
            responseStatus = HttpStatus.SC_CREATED;
        } catch (Exception e) {
            errMsg = "Error adding Entity:" + entity;
            logger.error(errMsg, e);
            response = errMsg;
            responseStatus = HttpStatus.SC_METHOD_FAILURE;
        }
    
        return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.PUT);
    }
    
    // Called on result of all RestWebServices (I'm sure there are better/best practices, feel free to comment me this section)
    /**
     * @param param the object to send if errorMsg is null
     * @param errorMsg if not null sends an error code with error Message
     * @param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
     * @return an altered response which is customized
     */
    public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
        Response result = null;
        int rStatus = responseStatus;
        if (errorMsg != null && responseStatus <= 0) {
            rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
        } else if (errorMsg == null && responseStatus <= 0){
            rStatus = HttpStatus.SC_OK;
        }
        String accessControlAllowMethods = "GET, POST, PUT, DELETE, OPTIONS, HEAD";
        if ( errorMsg == null ) {
            result = Response
                    .status(rStatus)
                    .header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
                    .header("Access-Control-Allow-Methods", accessControlAllowMethods)
                    .header("Access-Control-Max-Age", "1728000")
                    .entity(param)
                    .build();
        }else{
            result = Response.status(rStatus)
                    .header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
                    .header("Access-Control-Allow-Methods", accessControlAllowMethods)
                    .header("Access-Control-Max-Age", "1728000")
                    .entity(errorMsg)
                    .build();
        }
        return result;
    }
    
  3. # 3 楼答案

    • 观察选项请求和响应,并确保来自服务器的选项响应包含正确的信息。它告诉客户端服务器正在接受什么
    • 稍后观察真正的请求PUT GET POST等进入服务器。它有你想要的所有标题吗
    • 您不需要创建和修改路由选项。请参见此处的RFChttps://www.w3.org/TR/cors/

    向该线程添加选项请求和响应的副本(不是您创建的副本,而是您正在使用的包中的副本,如果您没有使用包,请查找一个),以查看配置有何问题

    同时添加下一个帖子、GET、PUT等,包括请求和响应