Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring4请求驱动的Bean创建_Java_Spring_Spring Mvc - Fatal编程技术网

Java Spring4请求驱动的Bean创建

Java Spring4请求驱动的Bean创建,java,spring,spring-mvc,Java,Spring,Spring Mvc,我正在使用Spring4(SpringBoot)实现RESTWS 基本思想是,我希望使用一个JSON负载,指定一个标识符(例如,社会保险号或其他),并在该标识符上运行多个子服务。 以下是一个示例有效负载: { "ssNumber" : "1111111111111111", "subServicesDetails" : [ { "subServiceName" : "Foo" , "requestParameters" : {} }, {

我正在使用Spring4(SpringBoot)实现RESTWS

基本思想是,我希望使用一个JSON负载,指定一个标识符(例如,社会保险号或其他),并在该标识符上运行多个子服务。 以下是一个示例有效负载:

{
    "ssNumber" : "1111111111111111",
    "subServicesDetails" :
    [
        { "subServiceName" : "Foo" , "requestParameters" : {} }, 
        { "subServiceName" : "Dummy", "requestParameters" : {} }
    ]
}
在我的代码中,我有多个“子服务”(
FooService
DummyService
)实现
子服务
接口:

package com.johnarnold.myws.service;

import com.johnarnold.myws.model.SubServiceDetails;

public interface SubService {

    public boolean service(String ssNumber, SubServiceDetails ssd);
}
下面是
FooService
代码。 软件包
com.johnanold.myws.service

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.johnarnold.myws.dao.FooDao;
import com.johnarnold.myws.model.Foo;
import com.johnarnold.myws.model.SubServiceDetails;

@Component
public class FooService implements SubService{
    private static Logger log = Logger.getLogger(FooService.class);

    @Autowired
    private FooDao dao;


    public FooService()
    {
        log.debug("FooService ctor");
    }


    public boolean service(String ssNumber, SubServiceDetails ssd)
    {
        log.debug("FooService service");

        Map <String, String> responseParameters = new HashMap<String, String>();
        try
        {
            Foo foo = dao.getFoo(ssNumber);
            if(foo.isCompromised())
            {
                responseParameters.put("listed", "true");
            }
            else
            {
                responseParameters.put("listed", "false");              
            }
            ssd.setResponseParameters(responseParameters);
            return true;
        }
        catch(Throwable ex)
        {
            log.error("Exception in service ", ex);
        }
        return false;
    }
}
为了完整起见,这里是控制器:

package com.johnarnold.myws.controller;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.log4j.Logger;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.johnarnold.myws.model.RawsPayload;
import com.johnarnold.myws.model.SubServiceDetails;
import com.johnarnold.myws.service.SubService;
import com.johnarnold.myws.service.SubServiceFactory;
import com.johnarnold.myws.web.ValidMessage;

@RestController
@RequestMapping("/raws/")
public class RawsController {
    private static final Logger logger = Logger.getLogger(RawsController.class);    

    //@Autowired
    //SubService [] subSvcs;

    @RequestMapping(value="/{version}/status", method=RequestMethod.GET)
    public ResponseEntity<ValidMessage> getServiceStatus()
    {
        return new ResponseEntity<>(new ValidMessage() , HttpStatus.OK);
    }

    /*
     * Main entry point - orchestrates all of the WS Sub Services
     */
    @RequestMapping(value="/{version}/raws", method=RequestMethod.PUT)
    public ResponseEntity<String> raws(@Valid @RequestBody RawsPayload rawsPayload, 
            HttpServletRequest request)
    {
        logger.info("Request received");


        System.out.println("payl " + rawsPayload);

        System.out.println("ssNumber=" + rawsPayload.getSsNumber());
        System.out.println("sub svcs details=" + rawsPayload.getSubServicesDetails().length);

        SubServiceDetails[] subServiceDetails = rawsPayload.getSubServicesDetails();

        for(SubServiceDetails ssd : subServiceDetails)
        {

            String subServiceNameStr = ssd.getSubServiceName();

            System.out.println("svcname=" + subServiceNameStr);
            System.out.println("svc req params=" + ssd.getRequestParameters());
            System.out.println("svc resp params=" + ssd.getResponseParameters());

            SubService subService = SubServiceFactory.createSubService(subServiceNameStr);
            // Probably wrap the below with some timings
            subService.service(rawsPayload.getSsNumber(), ssd);
        }


        //System.out.println("svcs are " + subSvcs + "size=" + subSvcs.length);


        return new ResponseEntity<>("foo" , HttpStatus.OK);
    }

}
我已经阅读了关于Spring4条件bean的StackOverflow的许多答案,但是这个功能似乎是针对上下文/配置类型信息,而不是请求消息内容(如本例所示)。 谁能给我指一下正确的方向吗。如有必要,我可以提供进一步的背景 KRgds
John解决此问题的两种可能方法:

  • 将所有子服务bean添加到Spring上下文中,然后使用。这是一种更好的方法(从架构的角度来看),但是如果您以前从未使用过这个概念,那么实现它可能需要更多的时间
如果您想坚持使用基本的Spring解决方案,下面有一个更简单的选择:

  • 将子服务bean作为列表注入到主服务中,然后从中进行选择。它看起来像这样:

    @Component
    public class SubServiceFactory implements BeanFactoryAware{
    
    private BeanFactory beanFactory;
    private static final String MY_SERVICE_SUFFIX = "Service";
    
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
    
    public <T> T getServiceImplementation(String name, Class<T> requiredType) {
        return beanFactory.getBean(name + MY_SERVICE_SUFFIX, requiredType);
    }
    }
    
    @Autowired
    Map<String, SubService> subServices;
    
    @Bean
    公共列表子服务(){
    列表=新的子服务();
    添加(新的AService());
    添加(新的BService());
    退货清单;
    }

然后


@john arnold首先,像这样包装所有服务,或者用@Service/@Component注释它们,并使用下面这样的显式名称:名称以
subServiceName
param的值开头,并在这里包含一个通用后缀“Service”,这一点很重要

@Bean("FooService")
public SubService fooService() {
    return new FooService();
}

@Bean("DummyService")
public SubService dummyService() {
    return new DummyService();
}
然后像这样改变你的工厂:

@Component
public class SubServiceFactory implements BeanFactoryAware{

private BeanFactory beanFactory;
private static final String MY_SERVICE_SUFFIX = "Service";

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    this.beanFactory = beanFactory;
}

public <T> T getServiceImplementation(String name, Class<T> requiredType) {
    return beanFactory.getBean(name + MY_SERVICE_SUFFIX, requiredType);
}
}
@Autowired
Map<String, SubService> subServices;
这将返回您的bean或异常(如果找不到)。如果您不想要异常,您可以捕获它并返回null,或者您可以仅为这些异常创建服务imp并返回该实例。你的选择

编辑:

作为一种快捷方式,您可以定义imp.bean,然后将其添加到rest端点

@Autowired
private Map<String, SubService> mySubServices;
@Autowired
私有地图订阅服务;

Spring将自动注入所有imp.ref,所以您可以只使用map的get()方法。但是我更喜欢第一个。

你不需要任何花哨的东西。只需实现实现服务接口的所有服务,使用
@Component
@service
对它们进行注释,然后像往常一样扫描它们

然后,无论您在何处必须选择一个具体的服务实现,都可以像这样自动连接服务的所有实现:

@Component
public class SubServiceFactory implements BeanFactoryAware{

private BeanFactory beanFactory;
private static final String MY_SERVICE_SUFFIX = "Service";

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    this.beanFactory = beanFactory;
}

public <T> T getServiceImplementation(String name, Class<T> requiredType) {
    return beanFactory.getBean(name + MY_SERVICE_SUFFIX, requiredType);
}
}
@Autowired
Map<String, SubService> subServices;
其中,
subServiceName
是您在JSON中接收的子服务的未大写名称(即,如果您正在接收
Foo
,这将是
Foo


约定是使用实现接口的类的未大写名称作为bean名称,即对于
FooService
类,bean名称将是
FooService
,这是您必须在地图中查找的关键。

非常有教育意义的答案
SubService fooSubService = subServices.get(subServiceName + "Service");