繁体   English   中英

在 Spring Boot 中的控制器中自动装配通用(T)服务

[英]Autowiring Generic(T) Service in Controller within Spring Boot

我对如何在 Spring Boot 2.5.0 中将通用服务自动连接到控制器有点困惑。

这是代码:
主控制器:

@RestController
@RequestMapping("/classifiers")
public class ClassifierController<T> {
    protected static final Logger LOG = LoggerFactory.getLogger(UserController.class);
    public final T classifierService;
    protected final JwtTokenFilter jwtTokenFilter;
    protected final JwtTokenUtil jwtTokenUtil;
    
    public ClassifierController(final JwtTokenFilter jwtTokenFilter,
                                final JwtTokenUtil jwtTokenUtil,
                                final T classifierService) {
        this.jwtTokenFilter = jwtTokenFilter;
        this.jwtTokenUtil = jwtTokenUtil;
        this.classifierService = classifierService;
    }
}

扩展控制器:


@RestController
@RequestMapping("/ss01dictionary")
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class SS01WasteDictionaryController
      extends ClassifierController<DictionaryService> {
    
    @Autowired
    public SS01WasteDictionaryController(JwtTokenFilter jwtTokenFilter,
                                         JwtTokenUtil jwtTokenUtil,
                                         DictionaryService classifierService) {
        super(jwtTokenFilter, jwtTokenUtil, classifierService);
    }
    
    @RequestMapping(value = "/list", method = GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity<?> getData(@RequestParam(value = "page", defaultValue = "0") int page,
                                                     @RequestParam(value = "size", defaultValue = "20") int pageSize) {
        PageRequest pageable = PageRequest.of(page, pageSize);
        Page<Dictionary> dictionaryDTOList = classifierService.getAllDictionaryValues(pageable);
        return ResponseEntity.status(HttpStatus.OK).body(dictionaryDTOList);
    }
...

主要文摘服务:


@Service
public abstract class ClassifierService {
    public final JdbcTemplate jdbcTemplate;
    
    public ClassifierService(final JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    
    protected abstract Integer count();
}

字典服务:

@Service
public class DictionaryService
      extends ClassifierService {
    public DictionaryService(JdbcTemplate jdbcTemplate) {
        super(jdbcTemplate);
    }
    
    public Page<DictionaryDTO> getAllDictionaryValues(Pageable page) {
        List<DictionaryDTO> result = jdbcTemplate.query(GET_SQL + " LIMIT " + page.getPageSize() + " OFFSET " + page.getOffset(),
                                                                 new DictionaryRowMapper());
        return new PageImpl<>(result, page, count());
    }

我做错了什么? 我想要具有一些抽象方法和通用控制器的通用服务。 如何自动装配 T 服务,以便我可以使用特定服务中特定控制器的方法?

如果你想在超级抽象类中抽象出控制器和服务的公共内容,那么你必须将该类标记为抽象并将这个条件在层次结构中移到较低的位置。 系统正确地抱怨它无法找到类型 T 的服务,因为该名称没有任何可搜索的内容。 如果你创建一个名为T的类,这个问题很可能会得到解决。 现在,如何在这里使用泛型定义。 这是我如何尝试做到的。

  • 首先创建一个抽象的服务类说AbstractService
  • 如果需要,可以通过限定符单独创建此服务的具体实现者。
  • 创建一个抽象控制器并告诉它需要一个类,它是AbstractService的子类。
  • 在子控制器中注入所需的服务并将其传递给您正在执行的超类。

代码如下:

package in.silentsudo.autowiregenericservicecontroller.service;

public abstract class AbstractTransporterService {

    final public String supportedVersion() {
        return "1.0";
    }

    public abstract String transport();
}

实施例1

package in.silentsudo.autowiregenericservicecontroller.service;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
@Qualifier("audioTransporterService")
public class AudioTransporterService extends AbstractTransporterService {
    @Override
    public String transport() {
        return "transporting audio details";
    }
}

实施例2

package in.silentsudo.autowiregenericservicecontroller.service;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
@Qualifier("videoTransporterService")
public class VideoTransporterService extends AbstractTransporterService {
    @Override
    public String transport() {
        return "transporting video details";
    }
}

控制器如下 AbstractController

package in.silentsudo.autowiregenericservicecontroller.controller;

import in.silentsudo.autowiregenericservicecontroller.service.AbstractTransporterService;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

public abstract class AbstractController<S extends AbstractTransporterService> {
    private final S service;

    public AbstractController(S service) {
        this.service = service;
    }

    public S getService() {
        return service;
    }


    @RequestMapping(path = "/version")
    public Map<String, String> controllerVersion() {
        return Map.of("type", getClass().getName(), "v", service.supportedVersion());
    }
}

实施例1

package in.silentsudo.autowiregenericservicecontroller.controller;

import in.silentsudo.autowiregenericservicecontroller.service.AudioTransporterService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path = "/audio")
public class AudioController extends AbstractController<AudioTransporterService> {


    public AudioController(AudioTransporterService service) {
        super(service);
    }

    @GetMapping
    public String get() {
        return getService().transport();
    }
}

实施例2

package in.silentsudo.autowiregenericservicecontroller.controller;

import in.silentsudo.autowiregenericservicecontroller.service.VideoTransporterService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path = "/video")
public class VideoController extends AbstractController<VideoTransporterService> {

    public VideoController(VideoTransporterService service) {
        super(service);
    }

    @GetMapping
    public String get() {
        return getService().transport();
    }
}

@RestController注释信息不会在运行时传递。 所以最好不要用同样的Service注释超类

还有路径

  • http://localhost:8080/audio/version
  • http://localhost:8080/video/version

正在工作,因为他们正在扩展具有/version方法的超类

源代码https://gitlab.com/spring-boot-cloud-samples/autowire-generic-service-controller

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM