AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题

问题[spring](coding)

Martin Hope
Gutter Overflow
Asked: 2025-04-22 12:15:11 +0800 CST

我们可以在 Spring 中定义一个以 /actuator 开头的端点吗?哪一个会优先?

  • 0

如果我们为“localhost:8080/actuator/health”定义自己的请求映射,它会被注册吗?它会调用 Spring 执行器吗?

spring
  • 1 个回答
  • 73 Views
Martin Hope
samsamsamsmasma
Asked: 2025-04-15 15:18:05 +0800 CST

为什么在Spring Kafka中最后一条记录的成功决定了Kafka事务提交?

  • 5

我正在使用带有 KafkaTransactionManager 和 DefaultErrorHandler 的 Spring Kafka 3.0.5。

在我的消费者配置中:

确认模式设置为 BATCH

监听器类型为@KafkaListener(基于记录)

事务已启用(KafkaTransactionManager)

重试配置为 DefaultErrorHandler.setRetryListeners(...) 和 10 次重试

在对一批消息进行测试时,我观察到了以下情况:

如果轮询批次中的最后一条记录失败,则整个事务将回滚,并且偏移量不会提交 - 正如预期的那样。

如果最后一条记录成功,即使批次中的先前记录失败但重试成功,整个事务也会提交,并且消费者滞后变为 0。

这意味着批次中最后一条记录的最终结果似乎决定了事务是否被提交。

问题:

这是预期的行为吗——最后一条记录的结果决定了事务提交?

这在 Spring Kafka 或 Kafka 自己的事务行为中是否有记录?

有没有办法让每个记录的事务提交更加明确,或者将其与最终记录状态分离?

如能提供任何说明或文档链接,我们将不胜感激。

spring
  • 1 个回答
  • 41 Views
Martin Hope
Adr4m
Asked: 2025-04-15 07:01:28 +0800 CST

从命令行运行 jooq-codegen-maven 时,jOOQ 代码生成配置不正确

  • 8

我在生成 jooq 类时遇到了问题。我使用的是 jooq 3.20.3,带有 maven 和一个在后台运行的数据库。

我的配置是这样的:

<build>
    <plugins>
        <plugin>
            <groupId>org.jooq</groupId>
            <artifactId>jooq-codegen-maven</artifactId>
            <version>${jooq.version}</version>
            <executions>
                <execution>
                    <id>jooq-codegen</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <jdbc>
                            <driver>org.postgresql.Driver</driver>
                            <url>jdbc:postgresql://localhost:5432/my_db</url>
                            <user>my_user</user>
                            <password>my_password</password>
                        </jdbc>
                        <generator>
                            <database>
                                <name>org.jooq.meta.postgres.PostgresDatabase</name>
                            </database>

                            <target>
                                <packageName>com.example.domain</packageName>
                                <directory>src/main/java_generated</directory>
                            </target>
                        </generator>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

我不确定哪些是必需的,哪些是可选的。另外,我使用了“入门指南”中提供的 jooq 配置。当然,my_db等的值是我的数据库的值(稍后我会使用一些环境变量)。

但每次运行时mvn jooq-codegen:generate都会出现以下错误:

[ERROR] Incorrect configuration of jOOQ code generation tool
[ERROR] 
The jOOQ-codegen-maven module's generator configuration is not set up correctly.
This can have a variety of reasons, among which:
- Your pom.xml's <configuration> contains invalid XML according to jooq-codegen-3.20.1.xsd
- There is a version or artifact mismatch between your pom.xml and your commandline

但我没有发现错误

spring
  • 1 个回答
  • 127 Views
Martin Hope
David
Asked: 2025-04-07 02:55:58 +0800 CST

Spring Boot 安全捕获 GlobalExceptionHandler 拒绝访问

  • 6

例如,当用户即将访问管理员页面时,我想捕获 spring boot 访问被拒绝异常。

我的 GlobalExceptionHandler (@ControllerAdvice) 中有这个异常处理程序

    @ExceptionHandler(AccessDeniedException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public String handleAccessDenied(AccessDeniedException e, Model model) {
        model.addAttribute("errorMessage", e.getMessage());
        return "error";
    }

我尝试使用 CustomAccessDeniedHandler:

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        throw accessDeniedException;
    }
}

在我的 SecurityConfig 中我将其添加到我的 filterChain 中:

.exceptionHandling(eh -> eh.accessDeniedHandler(customAccessDeniedHandler))

现在我的终端出现“访问被拒绝”:org.springframework.security.authorization.AuthorizationDeniedException:访问被拒绝

我想用我的 GlobalExceptionHandler 捕获此异常(尝试使用 ExceptionHandler 中的 AuthorizationDeniedException)

注意:我不使用 JWT

我错过了什么?

spring
  • 1 个回答
  • 23 Views
Martin Hope
PAA
Asked: 2025-04-05 23:28:11 +0800 CST

原因:java.lang.IllegalArgumentException:如果有多个作业,则必须指定作业名称 - Spring Batch

  • 6

我正在将 Spring Boot Batch App 从版本 2.7.1 迁移到 3.2.10,并收到以下错误。文档没有建议如何解决该问题。有人可以提出建议吗?

错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobLauncherApplicationRunner' defined in class path resource [org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.class]: Job name must be specified in case of multiple jobs
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.13.jar:6.1.13]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.13.jar:6.1.13]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.2.10.jar:3.2.10]
    at com.example.demo.Application.main(Application.java:11) ~[classes/:na]
Caused by: java.lang.IllegalArgumentException: Job name must be specified in case of multiple jobs
    at org.springframework.util.Assert.isTrue(Assert.java:111) ~[spring-core-6.1.13.jar:6.1.13]
    at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.afterPropertiesSet(JobLauncherApplicationRunner.java:115) ~[spring-boot-autoconfigure-3.2.10.jar:3.2.10]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802) ~[spring-beans-6.1.13.jar:6.1.13]
    ... 15 common frames omitted


Process finished with exit code 1

ChilJob配置.java

package com.example.demo;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class ChildJobConfiguration {
    @Autowired
    private JobRepository jobRepository;
    @Autowired
    private PlatformTransactionManager transactionManager;


    @Bean
    public Step step1a() {
        return new StepBuilder("step1a", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("\t>>This is step 1a");

                    return RepeatStatus.FINISHED;
                }, transactionManager).build();
    }

    @Bean
    public Job childJob() {
        return new JobBuilder("childJob", jobRepository)
                .start(step1a())
                .build();
    }
}

父作业配置.java

package com.example.demo;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.JobStepBuilder;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class ParentJobConfiguration {

    @Autowired
    private JobRepository jobRepository;
    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private Job childJob;

    @Autowired
    private JobLauncher jobLauncher;

    @Bean
    public Step step1() {
        return new StepBuilder("step1", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    System.out.println(">> This is step 1");
                    return RepeatStatus.FINISHED;
                }, transactionManager).build();
    }

    @Bean
    public Job parentJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        Step childJobStep = new JobStepBuilder(new StepBuilder("childJobStep", jobRepository))
                .job(childJob)
                .launcher(jobLauncher)
                .build();

        return new JobBuilder("parentJob", jobRepository)
                .start(step1())
                .next(childJobStep)
                .build();
    }
}

主应用程序

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

应用程序.属性

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.schema=schema-mysql.sql

spring.batch.job.names=parentJob
spring
  • 1 个回答
  • 35 Views
Martin Hope
D-Dᴙum
Asked: 2025-02-26 23:15:43 +0800 CST

与手动创建适配器相比,sourcePollingChannelAdapterSpec 中似乎忽略了 sendTimeout

  • 6

当我创建IntegrationFlow设置时sendTimeout(),值SourcePollingChannelAdapterSpec被忽略,导致轮询线程阻塞。如果我以编程方式创建,则不会SourcePollingChannelAdapter发生这种情况。例如,以编程方式使用@Configuration类:

@Configuration
public class JdbcPollingConfig {

    @Bean
    protected MessageChannel jdbcInboundChannel() {
        return new QueueChannel(1);
    }

    @Bean
    public ThreadPoolTaskScheduler jdbcTaskExecutor() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(1);
        taskScheduler.initialize();
        return taskScheduler;
    }

    @Bean
    protected JdbcPollingChannelAdapter jdbcPollingChannelAdapter(final DataSource dataSource) {
        final JdbcPollingChannelAdapter adapter =
                new CustomJdbcPollingChannelAdapter(dataSource, "select dp_id, dp_payload from data_packets");
        return adapter;
    }

    @Bean
    protected SourcePollingChannelAdapter sourcePollingChannelAdapter(
            final JdbcPollingChannelAdapter adapter,
            final MessageChannel jdbcInboundChannel,
            final ThreadPoolTaskScheduler jdbcTaskExecutor) {
        final SourcePollingChannelAdapter spcAdapter = new SourcePollingChannelAdapter();
        spcAdapter.setSource(adapter);
        spcAdapter.setOutputChannel(jdbcInboundChannel);
        spcAdapter.setSendTimeout(500); // Sets the send-to-channel timeout - throws exception on timeout though.
        spcAdapter.setTaskScheduler(jdbcTaskExecutor);
        spcAdapter.setTrigger( new PeriodicTrigger(Duration.ofSeconds(2L)));
        return spcAdapter;
    }

}

请注意,该类CustomJdbcPollingChannelAdapter是我自己的,它只是进行了扩展,以便我可以doReceive()使用一些日志调用来覆盖该方法:

@Log4j2
public class CustomJdbcPollingChannelAdapter extends JdbcPollingChannelAdapter {
    public CustomJdbcPollingChannelAdapter(DataSource dataSource, String selectQuery) {
        super(dataSource, selectQuery);
    }

    public CustomJdbcPollingChannelAdapter(JdbcOperations jdbcOperations, String selectQuery) {
        super(jdbcOperations, selectQuery);
    }

    @Override
    protected Object doReceive() {
        log.info("Jdbc Polling.");
        return super.doReceive();
    }
}

在配置了通道队列的情况下,此配置会按预期抛出异常,因为没有通道的消费者jdbcInboundChannel。对比一下使用和IntegrationFlow配置:

@Configuration
public class JdbcDSLConfig {

    @Bean
    public QueueChannelSpec jdbcInboundChannel() {
        return MessageChannels.queue(1);
    }

    @Bean
    public MessageSource<Object> jdbcMessageSource(final DataSource dataSource) {
        return new CustomJdbcPollingChannelAdapter(dataSource, "select dp_id, dp_payload from data_packets");
    }

    @Bean
    public ThreadPoolTaskExecutor jdbcExecutor() {
        final ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(1);
        taskExecutor.setMaxPoolSize(1);
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Bean
    public IntegrationFlow jdbcInboundFlow(final MessageSource<Object> jdbcMessageSource,
                                           final QueueChannelSpec jdbcInboundChannel,
                                           @Qualifier("jdbcExecutor") final ThreadPoolTaskExecutor jdbcExecutor) {
        return IntegrationFlow.from(jdbcMessageSource,
                        c -> c.poller(Pollers
                                .fixedDelay(2000)
                                .sendTimeout(1) // this has no effect.
                                .taskExecutor(jdbcExecutor)))
                .channel(jdbcInboundChannel)
                .get();

    }
}

即使在配置中设置了 sendTimeout,此配置也会在数据库的第二次轮询时阻塞。

spring
  • 1 个回答
  • 15 Views
Martin Hope
Draaksward
Asked: 2025-02-19 22:47:25 +0800 CST

Spring Integrations。向 MQTT 发送消息

  • 6

作为学习曲线的一部分,我正在尝试使用 Spring Integrations 向 Mosquitto MQTT 发布一条消息。我已经设置了一个配置(主要来自我通过谷歌搜索找到的部分,但 Listener 部分运行良好):

@Configuration
@RequiredArgsConstructor
@IntegrationComponentScan
public class MqttConfig {
private final MqttProperties properties;
    private final ObjectMapper objectMapper;

    private List<String> sensorTopics;

    @PostConstruct
    void init() {
        sensorTopics = properties.getSensors().stream()
                .map(MqttProperties.Sensor::getTopic)
                .toList();
    }

    @Bean
    public IntegrationFlow sensorDataFlow(HumilityAndTempSensorMessageHandler humilityAndTempSensorMessageHandler) {
        return IntegrationFlow.from(
                        new MqttPahoMessageDrivenChannelAdapter(
                                properties.getUrl(),
                                "iotBridge",
                                "#")
                )
                .filter(getSensorTopicFilter())
                .transform(getTempSensorTransformer())
                .handle(humilityAndTempSensorMessageHandler::handleMessage)
                .get();
    }

    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }


    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(new String[]{properties.getUrl()});
        options.setUserName(properties.getUsername());
        options.setPassword(properties.getPassword().toCharArray());
        factory.setConnectionOptions(options);
        return factory;
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler messageHandler =
                new MqttPahoMessageHandler("exoluse", mqttClientFactory());
        messageHandler.setAsync(true);
        messageHandler.setDefaultTopic("topic");
        return messageHandler;
    }

    @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
    public interface PublishGateway {
        void send(String message, @Header(MqttHeaders.TOPIC) String topic);
    }

    private GenericTransformer<String, TempSensorReading> getTempSensorTransformer() {
        return source -> {
            try {
                return objectMapper.readValue(source, TempSensorReading.class);
            } catch (Exception e) {
                System.out.println("failed to resolve input");
            }
            return null;
        };
    }

    private GenericHandler<String> getSensorTopicFilter() {
        return (payload, headers) -> {
            String topic = Optional.ofNullable(headers)
                    .map(item -> item.get("mqtt_receivedTopic"))
                    .map(String::valueOf)
                    .orElse(null);
            return sensorTopics.contains(topic);
        };
    }

我正在尝试传达一条信息:

@Service
//@RequiredArgsConstructor
@Slf4j
public class SocketGateway {

    @Autowired
    private MqttConfig.PublishGateway publishGateway;

    @PostConstruct
    void t() {
        // ${SHELLY_ID}/command/switch:0 -m toggle
        String topic = "xxx/command/switch:0";
        System.out.println(">>>>>> "+publishGateway);
        publishGateway.send("toggle", topic);
    }
}

我遇到了Dispatcher has no subscribers异常。

依赖版本:

    <dependency>
      <groupId>org.springframework.integration</groupId>
      <artifactId>spring-integration-mqtt</artifactId>
      <version>6.4.1</version>
    </dependency>

我做错什么了?

UPD:完整 pom

 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.2</version>
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>15</maven.compiler.source>
    <maven.compiler.target>15</maven.compiler.target>
    <javafx.version>17.0.1</javafx.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.28</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework.integration</groupId>
      <artifactId>spring-integration-mqtt</artifactId>
      <version>6.4.1</version>
    </dependency>

  </dependencies>
</project>

错误的完整堆栈跟踪:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'socketGateway': Invocation of init method failed
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:222) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:419) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1762) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:942) ~[spring-context-6.0.11.jar:6.0.11]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[spring-context-6.0.11.jar:6.0.11]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.2.jar:3.1.2]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-3.1.2.jar:3.1.2]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:436) ~[spring-boot-3.1.2.jar:3.1.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[spring-boot-3.1.2.jar:3.1.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-3.1.2.jar:3.1.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-3.1.2.jar:3.1.2]
    at org.draakz.iotbridge.Application.main(Application.java:9) ~[classes/:na]
Caused by: org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'application.mqttOutboundChannel'.
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:76) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.channel.AbstractMessageChannel.sendInternal(AbstractMessageChannel.java:373) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:327) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187) ~[spring-messaging-6.0.11.jar:6.0.11]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166) ~[spring-messaging-6.0.11.jar:6.0.11]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47) ~[spring-messaging-6.0.11.jar:6.0.11]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109) ~[spring-messaging-6.0.11.jar:6.0.11]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:151) ~[spring-messaging-6.0.11.jar:6.0.11]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:143) ~[spring-messaging-6.0.11.jar:6.0.11]
    at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:466) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.sendOrSendAndReceive(GatewayProxyFactoryBean.java:669) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:584) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:550) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:540) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.11.jar:6.0.11]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy83.send(Unknown Source) ~[na:na]
    at org.draakz.iotbridge.mqtt.publisher.SocketGateway.t(SocketGateway.java:26) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMethod.invoke(InitDestroyAnnotationBeanPostProcessor.java:457) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:401) ~[spring-beans-6.0.11.jar:6.0.11]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:219) ~[spring-beans-6.0.11.jar:6.0.11]
    ... 18 common frames omitted
Caused by: org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:139) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106) ~[spring-integration-core-6.1.2.jar:6.1.2]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72) ~[spring-integration-core-6.1.2.jar:6.1.2]
    ... 42 common frames omitted
spring
  • 1 个回答
  • 29 Views
Martin Hope
Daniel Pop
Asked: 2025-02-19 20:30:50 +0800 CST

安全范围之前的 Spring 验证约束

  • 5

我有一个使用 Spring Security OAuth2 保护的 Spring Boot 3.4 服务。

我的安全配置是标准的:

    @Bean
    public SecurityFilterChain oauth2FilterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(sm -> sm.sessionCreationPolicy(STATELESS))
                .exceptionHandling(eh -> eh.authenticationEntryPoint(handleException()));

        http.securityMatcher("/api/**")
                .authorizeHttpRequests(auth ->
                        auth.requestMatchers("/api/**").authenticated())
                .oauth2ResourceServer(resourceServer ->
                        resourceServer.jwt(jwt -> jwt.decoder(jwtDecoder())));

        return http.build();
    }

我的端点带有以下注释:@PreAuthorize(hasAuthority('SCOPE_MY_SCOPE'))。

此外,在我的 API 模型上,我使用 Jakarta Validation 3 进行验证(例如,在字段上使用注释@NotNull)。

鉴于此配置,我有以下场景:我使用没有所需范围的安全承载令牌发出无效请求。

服务器响应 400,因为验证约束失败。但是,我预计这个请求会返回 403;我认为 Spring 向未经授权调用我的端点的人公开了有关我的验证约束的不必要信息。如果我使用有效的请求,它确实会返回 403,所以问题在于检查的顺序:我希望先看到安全检查,然后是验证检查,但似乎情况正好相反。

spring
  • 2 个回答
  • 28 Views
Martin Hope
user12372439
Asked: 2025-02-12 02:25:37 +0800 CST

Spring 如何使服务类开放?我以为 Kotlin 默认是 final 的

  • 7

Kotlin 中的方法或类默认为 final。但是当我将 Service 类中的方法标记为 时@Transactional,我意识到服务类及其所有方法都是开放的。因为要使@Transactional方面发挥作用,服务类需要被代理,那么它必须是一个开放类,以便代理类可以扩展原始类。

(正如教程Kotlin 中的打开关键字所指出的,kotlin 默认是 final 的。

根据Spring文档AOP,因为我的服务类继承自抽象类而不是接口,所以代理是CGLIB代理。)

我是否误解了什么或者它是如何工作的?


@Service
class SomeService(...): SomeAbstractClass(...){
    @Transactional
    fun someMethod(...){...}
}
spring
  • 1 个回答
  • 40 Views
Martin Hope
FinnCoal
Asked: 2025-02-10 03:01:21 +0800 CST

Spring Boot - 如何/在哪里将 DTO 的外键转换为实体

  • 5

我正在使用 Spring Boot 创建一个 REST 服务,但在将 JSON 请求/DTO 转换为相应实体时遇到了麻烦,特别是当一个实体包含对另一个实体的引用时。例如,假设我们有这些对象:

data class BookEntity(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Int?,

    val name: String,

    @ManyToOne
    @JoinColumn(name = "author_id")
    val author: AuthorEntity,
)
data class AuthorEntity(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Int?,

    val name: String,
)
data class BookRequestDto(
    val name: String,
    val authorId: Int,
)

该应用程序具有控制器-服务-存储库层,据我所知,我应该在控制器层中执行 DTO -> 实体转换,然后将生成的实体传递给服务层。但是,为了将图书请求 DTO 转换为实体,我首先必须根据给定的从存储库中获取适当的 Author 实体authorId。我的问题是:我到底应该在哪里做这件事?

鉴于服务层应该只接受实体,看来我应该在控制器层中获取作者。但这意味着 Book 控制器需要访问 Author 服务层,我不确定这是否是好的做法。

这就是我的意思(使用明显的扩展函数来执行 DTO/实体转换)

@RestController
@RequestMapping(path = ["/books"])
class BookController(
    private val bookService: BookService,
    private val authorService: AuthorService,
) {
    @PostMapping
    fun createBook(@RequestBody bookDto: BookRequestDto): ResponseEntity<BookResponseDto> {
        val author = authorService.get(bookDto.authorId)
        val bookEntity = bookDto.toBookEntity(author = author)
        val createdBook = bookService.create(bookEntity)
        return ResponseEntity(createdBook.toBookResponseDto(), HttpStatus.CREATED)
    }
}

这是通常的做法吗?还是在控制器中混合多个服务是个坏主意?我显然必须在某个地方访问作者存储库,但我不知道最佳位置在哪里。有没有更好的方法?

spring
  • 1 个回答
  • 72 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve