Skip to content

Commit

Permalink
update: SSE 适配 spring-boot 和 solon
Browse files Browse the repository at this point in the history
  • Loading branch information
mySingleLive committed Dec 20, 2024
1 parent e923e16 commit 2b27382
Show file tree
Hide file tree
Showing 19 changed files with 458 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4662,7 +4662,7 @@ public Object getAttachment(String name) {
}


/**
/**
* 根据名称获取该请求中的附件
* <p>Attachment 是和请求绑定的附件属性值,这些值不能通过网络请求传递到远端服务器。</p>
* <p>不同请求的附件相互独立,即使名称相同,也互不影响。</p>
Expand All @@ -4679,8 +4679,17 @@ public <R> R getAttachment(String name, Class<R> clazz) {
}
return clazz.cast(result);
}



/**
* 根据名称获取或添加该请求中的附件
* <p>当该请求中附件名所对应的附件值不存在时,会调用回调函数添加一个附件值</p>
*
* @param name 附件名
* @param supplier 附件值回调函数
* @return 附件值
* @param <R> 附件值类型
* @since 1.6.1
*/
public <R> R getOrAddAttachment(String name, Supplier<R> supplier) {
Object obj = getAttachment(name);
if (obj == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.sse.EventSource;

import java.io.InputStream;

/**
* Forest SSE 拦截器
*
* @since 1.6.1
*/
public interface SSEInterceptor extends Interceptor {
public interface SSEInterceptor extends Interceptor<InputStream> {

/**
* 监听打开回调函数:在开始 SSE 数据流监听的时候调用
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
import com.dtflys.forest.sse.EventSource;
import com.dtflys.forest.test.model.Contact;

public class MySSEInterceptor implements SSEInterceptor {
import java.io.InputStream;

public class MySSEInterceptor implements SSEInterceptor {

@Override
public void onSuccess(Object data, ForestRequest request, ForestResponse response) {
public void onSuccess(InputStream data, ForestRequest request, ForestResponse response) {
StringBuilder builder = (StringBuilder) request.getOrAddAttachment("text", StringBuilder::new);
builder.append("MySSEInterceptor onSuccess\n");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.dtflys.forest.solon.test.sse;

import com.dtflys.forest.annotation.BaseRequest;
import com.dtflys.forest.annotation.ForestClient;
import com.dtflys.forest.annotation.Get;
import com.dtflys.forest.http.ForestSSE;

@ForestClient
@BaseRequest(baseURL = "http://localhost:{port}")
public interface MySSEClient {

@Get("/sse")
ForestSSE testSSE();

@Get(url = "/sse", interceptor = MySSEInterceptor.class)
ForestSSE testSSE_withInterceptor();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.dtflys.forest.solon.test.sse;

import com.dtflys.forest.annotation.SSEDataMessage;
import com.dtflys.forest.annotation.SSEName;
import com.dtflys.forest.annotation.SSEValue;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.interceptor.SSEInterceptor;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

import java.io.InputStream;

@Component
public class MySSEInterceptor implements SSEInterceptor {

@Inject
private TestComp testComp;

@Override
public void onSuccess(InputStream data, ForestRequest request, ForestResponse response) {
StringBuilder builder = (StringBuilder) request.getOrAddAttachment("text", StringBuilder::new);
builder.append("onSuccess\n");
}

@Override
public void afterExecute(ForestRequest request, ForestResponse response) {
StringBuilder builder = (StringBuilder) request.getOrAddAttachment("text", StringBuilder::new);
builder.append("afterExecute\n");
}

@SSEDataMessage
public void onData(ForestRequest request, @SSEName String name, @SSEValue String value) {
StringBuilder builder = (StringBuilder) request.getOrAddAttachment("text", StringBuilder::new);
builder.append("Receive name=" + name + "; value=" + value + "; comp=" + testComp.getValue() + "\n");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.dtflys.forest.solon.test.sse;


import org.noear.solon.annotation.Component;

@Component
public class TestComp {

public String getValue() {
return "test";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.dtflys.forest.solon.test.sse;

import com.dtflys.forest.annotation.BindingVar;
import com.dtflys.forest.http.ForestSSE;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.noear.solon.annotation.Inject;
import org.noear.solon.test.SolonJUnit4ClassRunner;
import org.noear.solon.test.SolonTest;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@RunWith(SolonJUnit4ClassRunner.class)
@SolonTest(env = "sse")
public class TestSSE {

@Rule
public MockWebServer server = new MockWebServer();

@Inject
private MySSEClient sseClient;

@BindingVar("port")
public Integer getPort() {
return server.getPort();
}

@Test
public void testSSE() {
server.enqueue(new MockResponse().setResponseCode(200).setBody(
"data:start\n" +
"data:hello\n"
));

StringBuilder builder = new StringBuilder();

sseClient.testSSE()
.addOnData((eventSource, name, value) -> {
builder.append("Receive ").append(name).append(": ").append(value).append("\n");
})
.listen();

assertThat(builder.toString()).isEqualTo(
"Receive data: start\n" +
"Receive data: hello\n"
);
}


@Test
public void testSSE_withInterceptor() {
server.enqueue(new MockResponse().setResponseCode(200).setBody(
"data:start\n" +
"data:hello\n"
));

ForestSSE sse = sseClient.testSSE_withInterceptor().listen();

assertThat(sse.getRequest().getAttachment("text").toString()).isEqualTo(
"onSuccess\n" +
"afterExecute\n" +
"Receive name=data; value=start; comp=test\n" +
"Receive name=data; value=hello; comp=test\n"
);
}

}
7 changes: 7 additions & 0 deletions forest-solon-plugin/src/test/resources/app-sse.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

forest:
enabled: true
max-connections: 300
max-route-connections: 300
connect-timeout: 3000
max-retry-count: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.dtflys.forest.springboot.test.sse;

import com.dtflys.forest.annotation.BaseRequest;
import com.dtflys.forest.annotation.Get;
import com.dtflys.forest.http.ForestSSE;

@BaseRequest(baseURL = "http://localhost:{port}")
public interface MySSEClient {

@Get("/sse")
ForestSSE testSSE();

@Get(url = "/sse", interceptor = MySSEInterceptor.class)
ForestSSE testSSE_withInterceptor();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.dtflys.forest.springboot.test.sse;

import com.dtflys.forest.annotation.SSEDataMessage;
import com.dtflys.forest.annotation.SSEName;
import com.dtflys.forest.annotation.SSEValue;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.interceptor.SSEInterceptor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;

@Component
public class MySSEInterceptor implements SSEInterceptor {

@Resource
private TestComp testComp;

@Override
public void onSuccess(InputStream data, ForestRequest request, ForestResponse response) {
StringBuilder builder = (StringBuilder) request.getOrAddAttachment("text", StringBuilder::new);
builder.append("onSuccess\n");
}

@Override
public void afterExecute(ForestRequest request, ForestResponse response) {
StringBuilder builder = (StringBuilder) request.getOrAddAttachment("text", StringBuilder::new);
builder.append("afterExecute\n");
}

@SSEDataMessage
public void onData(ForestRequest request, @SSEName String name, @SSEValue String value) {
StringBuilder builder = (StringBuilder) request.getOrAddAttachment("text", StringBuilder::new);
builder.append("Receive name=" + name + "; value=" + value + "; comp=" + testComp.getValue() + "\n");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.dtflys.forest.springboot.test.sse;


import org.springframework.stereotype.Component;

@Component
public class TestComp {

public String getValue() {
return "test";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.dtflys.forest.springboot.test.sse;

import com.dtflys.forest.annotation.BindingVar;
import com.dtflys.forest.http.ForestSSE;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@RunWith(SpringRunner.class)
@ActiveProfiles("sse")
@SpringBootTest(classes = TestSSE.class)
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.dtflys.forest.springboot.test.sse"})
public class TestSSE {

@Rule
public MockWebServer server = new MockWebServer();

@Resource
private MySSEClient sseClient;

@BindingVar
public Integer getPort() {
return server.getPort();
}

@Test
public void testSSE() {
server.enqueue(new MockResponse().setResponseCode(200).setBody(
"data:start\n" +
"data:hello\n"
));

StringBuilder builder = new StringBuilder();

sseClient.testSSE()
.addOnData((eventSource, name, value) -> {
builder.append("Receive ").append(name).append(": ").append(value).append("\n");
})
.listen();

assertThat(builder.toString()).isEqualTo(
"Receive data: start\n" +
"Receive data: hello\n"
);
}


@Test
public void testSSE_withInterceptor() {
server.enqueue(new MockResponse().setResponseCode(200).setBody(
"data:start\n" +
"data:hello\n"
));

ForestSSE sse = sseClient.testSSE_withInterceptor().listen();

assertThat(sse.getRequest().getAttachment("text").toString()).isEqualTo(
"onSuccess\n" +
"afterExecute\n" +
"Receive name=data; value=start; comp=test\n" +
"Receive name=data; value=hello; comp=test\n"
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

forest:
enabled: true
max-connections: 300
max-route-connections: 300
connect-timeout: 3000
max-retry-count: 0
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@


<!-- 日志输出级别 -->
<logger name="com.dtflys.forest" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>

<root level="ERROR">
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.dtflys.forest.springboot3.test.sse;

import com.dtflys.forest.annotation.BaseRequest;
import com.dtflys.forest.annotation.Get;
import com.dtflys.forest.http.ForestSSE;

@BaseRequest(baseURL = "http://localhost:{port}")
public interface MySSEClient {

@Get("/sse")
ForestSSE testSSE();

@Get(url = "/sse", interceptor = MySSEInterceptor.class)
ForestSSE testSSE_withInterceptor();
}
Loading

0 comments on commit 2b27382

Please sign in to comment.