From be9d328eee55817b989954e766985746a8c5373b Mon Sep 17 00:00:00 2001 From: Yan Date: Sat, 5 Apr 2025 17:18:37 +0800 Subject: [PATCH] v3.1.0 Added test-api, update-session/inspection response body --- pom.xml | 8 +- .../com/example/sbcamel/init/AppConfig.java | 6 ++ .../com/example/sbcamel/init/CamelRouter.java | 32 ++++--- .../example/sbcamel/mapper/SessionMapper.java | 33 ++++--- .../processor/InspectionProcessor.java | 92 +++++++++++++------ .../sbcamel/processor/TestProcessor.java | 54 +++++++++++ .../com/example/sbcamel/service/Session.java | 33 +++++++ .../sbcamel/service/SessionService.java | 11 ++- 8 files changed, 218 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/example/sbcamel/processor/TestProcessor.java diff --git a/pom.xml b/pom.xml index 4ef1caf..9253941 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.example camel-springboot-activemq6-example - 3.0.4 + 3.1.0 camel-springboot-activemq6-example @@ -18,6 +18,7 @@ 3.0.4 33.1.0-jre 3.14.0 + 1.19.1 @@ -139,6 +140,11 @@ org.apache.commons commons-lang3 + + org.jsoup + jsoup + ${jsoup.version} + diff --git a/src/main/java/com/example/sbcamel/init/AppConfig.java b/src/main/java/com/example/sbcamel/init/AppConfig.java index 03251e3..92fb308 100644 --- a/src/main/java/com/example/sbcamel/init/AppConfig.java +++ b/src/main/java/com/example/sbcamel/init/AppConfig.java @@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.example.sbcamel.processor.InspectionProcessor; +import com.example.sbcamel.processor.TestProcessor; import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider; @Configuration @@ -18,4 +19,9 @@ public class AppConfig { public InspectionProcessor inspectionProcessor() { return new InspectionProcessor(); } + + @Bean + public TestProcessor testProcessor() { + return new TestProcessor(); + } } diff --git a/src/main/java/com/example/sbcamel/init/CamelRouter.java b/src/main/java/com/example/sbcamel/init/CamelRouter.java index 025024c..d0f72ff 100644 --- a/src/main/java/com/example/sbcamel/init/CamelRouter.java +++ b/src/main/java/com/example/sbcamel/init/CamelRouter.java @@ -3,10 +3,8 @@ package com.example.sbcamel.init; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.bean.BeanConstants; -import org.apache.camel.component.bean.validator.BeanValidationException; import org.apache.camel.component.cxf.common.message.CxfConstants; import org.apache.camel.model.dataformat.JsonLibrary; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.JdbcTemplate; @@ -14,6 +12,7 @@ import org.springframework.stereotype.Component; import com.example.sbcamel.mapper.SessionMapper; import com.example.sbcamel.processor.InspectionProcessor; +import com.example.sbcamel.processor.TestProcessor; import com.example.sbcamel.service.SessionService; import jakarta.annotation.PostConstruct; @@ -21,8 +20,12 @@ import jakarta.ws.rs.core.Response; @Component public class CamelRouter extends RouteBuilder { + private static final String createSessionSql = "CREATE TABLE IF NOT EXISTS public.session (sessionId UUID not null, " + "username CHARACTER VARYING not null, password CHARACTER VARYING not null, PRIMARY KEY (sessionId))"; + private static final String addSelector1Sql = "ALTER TABLE IF EXISTS public.session ADD COLUMN IF NOT EXISTS selector1 CHARACTER VARYING NULL"; + private static final String addSelector2Sql = "ALTER TABLE IF EXISTS public.session ADD COLUMN IF NOT EXISTS selector2 CHARACTER VARYING NULL"; + private static final String addSelector3Sql = "ALTER TABLE IF EXISTS public.session ADD COLUMN IF NOT EXISTS selector3 CHARACTER VARYING NULL"; @Value("${app.queue-name}") private String queueName; @@ -33,26 +36,27 @@ public class CamelRouter extends RouteBuilder { @Autowired protected InspectionProcessor inspectionProcessor; + @Autowired + protected TestProcessor testProcessor; + @PostConstruct private void init() { org.apache.ibatis.logging.LogFactory.useSlf4jLogging(); jdbcTemplate.execute(createSessionSql); + jdbcTemplate.execute(addSelector1Sql); + jdbcTemplate.execute(addSelector2Sql); + jdbcTemplate.execute(addSelector3Sql); } @Override public void configure() throws Exception { - // very raw way, just to handle the validation responses - onException(BeanValidationException.class).handled(true) - .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(Response.Status.BAD_REQUEST.getStatusCode())) - .setBody(simple("${exchangeProperty.CamelExceptionCaught.getMessage()}")); - onException(jakarta.ws.rs.NotFoundException.class).handled(true) .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(Response.Status.NOT_FOUND.getStatusCode())) .setBody(simple("${exchangeProperty.CamelExceptionCaught.getMessage()}")); from("cxfrs:/api?resourceClasses=" + SessionService.class.getName() + "&bindingStyle=Default" + "&providers=jaxrsProvider&loggingFeatureEnabled=true").to("log:cxfrs?showAll=true") - .to("bean-validator:user").to("activemq6:queue:" + queueName).process(exchange -> { + .to("activemq6:queue:" + queueName).process(exchange -> { if (exchange.getMessage().getBody() != null && exchange.getMessage().getBody() instanceof byte[] && new String((byte[]) exchange.getMessage().getBody()).equals("null")) { if (exchange.getIn().getHeader(Exchange.HTTP_METHOD).equals("GET")) { @@ -66,14 +70,20 @@ public class CamelRouter extends RouteBuilder { exchange.getIn().getHeader(CxfConstants.OPERATION_NAME.toLowerCase()))) .to("log:activemq?showAll=true").transacted("propagationRequired").choice() .when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("updateSession")) - .to("mybatis:" + SessionMapper.class.getName() + ".updateSession?statementType=Update") + .to("mybatis:" + SessionMapper.class.getName() + ".updateSession?statementType=Update&outputHeader=X-UpdateResult") + .process(exchange -> { + exchange.getMessage().setBody(exchange.getIn().getBody()); + }) .when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("findSessions")) .to("mybatis:" + SessionMapper.class.getName() + ".findSessions?statementType=SelectList") .when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("findSession")) .to("mybatis:" + SessionMapper.class.getName() + ".findSession?statementType=SelectOne") - .when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("login")) + .when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("inspect")) .to("mybatis:" + SessionMapper.class.getName() + ".findSession?statementType=SelectOne") - .process(inspectionProcessor).end().marshal().json(JsonLibrary.Jackson); + .process(inspectionProcessor) + .when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("test")) + .process(testProcessor) + .end().marshal().json(JsonLibrary.Jackson); } } \ No newline at end of file diff --git a/src/main/java/com/example/sbcamel/mapper/SessionMapper.java b/src/main/java/com/example/sbcamel/mapper/SessionMapper.java index 53806e5..6bed4a6 100644 --- a/src/main/java/com/example/sbcamel/mapper/SessionMapper.java +++ b/src/main/java/com/example/sbcamel/mapper/SessionMapper.java @@ -15,20 +15,31 @@ import com.example.sbcamel.service.UuidTypeHandler; public interface SessionMapper { @Insert({ "" }) - Session updateSession(Session session); - - @Results({ @Result(property = "sessionId", column = "sessionId", javaType=UUID.class, jdbcType=JdbcType.OTHER, typeHandler=UuidTypeHandler.class), - @Result(property = "username", column = "username"), @Result(property = "password", column = "password") }) - @Select({ "" }) Session findSession(UUID sessionId); - @Results({ @Result(property = "sessionId", column = "sessionId", javaType=UUID.class, jdbcType=JdbcType.OTHER, typeHandler=UuidTypeHandler.class), - @Result(property = "username", column = "username"), @Result(property = "password", column = "password") }) - @Select({ "" }) + @Results({ + @Result(property = "sessionId", column = "sessionId", javaType = UUID.class, jdbcType = JdbcType.OTHER, typeHandler = UuidTypeHandler.class), + @Result(property = "username", column = "username"), @Result(property = "password", column = "password"), + @Result(property = "selector1", column = "selector1"), + @Result(property = "selector2", column = "selector2"), + @Result(property = "selector3", column = "selector3") }) + @Select({ "" }) Collection findSessions(); } diff --git a/src/main/java/com/example/sbcamel/processor/InspectionProcessor.java b/src/main/java/com/example/sbcamel/processor/InspectionProcessor.java index 1c5ce58..aee970a 100644 --- a/src/main/java/com/example/sbcamel/processor/InspectionProcessor.java +++ b/src/main/java/com/example/sbcamel/processor/InspectionProcessor.java @@ -1,5 +1,10 @@ package com.example.sbcamel.processor; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.htmlunit.WebClient; @@ -8,11 +13,15 @@ import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlPasswordInput; import org.htmlunit.html.HtmlTextInput; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; -import com.example.sbcamel.service.Session; +import com.example.sbcamel.service.Session; public class InspectionProcessor implements Processor { @@ -20,43 +29,43 @@ public class InspectionProcessor implements Processor { @Value("${app.htmlunit.login-url}") private String loginUrl; - + @Value("${app.htmlunit.login-btn-selector}") private String loginBtnSelector; - + @Value("${app.htmlunit.login-wait-millis:3000}") private Long loginWaitMillis; - + @Value("${app.htmlunit.user-page-url}") private String userPageUrl; - + @Value("${app.htmlunit.vip1-page-url}") private String vip1PageUrl; - + @Value("${app.htmlunit.vip2-page-url}") private String vip2PageUrl; - + @Value("${app.htmlunit.vip3-page-url}") private String vip3PageUrl; - + @Value("${app.htmlunit.logout-url}") private String logoutUrl; - + @Override public void process(Exchange exchange) throws Exception { Session session = (Session) exchange.getMessage().getBody(); logger.info("session: {}", session); - + try (final WebClient webClient = new WebClient()) { - + final HtmlPage loginPage = webClient.getPage(loginUrl); logger.info("loginPage: {}", loginPage.asXml()); - + final HtmlForm form = loginPage.getForms().get(0); final HtmlTextInput usernameField = form.getInputByName("username"); usernameField.type(session.getUsername()); logger.info("entered username: {}", session.getUsername()); - + final HtmlPasswordInput passwordField = form.getInputByName("password"); passwordField.type(session.getPassword()); logger.info("entered password: {}", session.getPassword()); @@ -64,23 +73,54 @@ public class InspectionProcessor implements Processor { HtmlButton loginBtn = loginPage.querySelector(loginBtnSelector); logger.info("loginBtn type: {}", loginBtn.getType()); loginBtn.click(); - + Thread.sleep(loginWaitMillis); - HtmlPage userPage = webClient.getPage(userPageUrl); - logger.info("userPage: {}", userPage.asXml()); + HtmlPage userPage = webClient.getPage(userPageUrl); + logger.info("userPage hashcode: {}", userPage.hashCode()); + + Map> reply1 = new HashMap<>(); HtmlPage vip1Page = webClient.getPage(vip1PageUrl); - logger.info("vip1Page: {}", vip1Page.asXml()); - + Document doc = Jsoup.parse(vip1Page.asXml()); + for (String selector : List.of(session.getSelector1(), session.getSelector2(), session.getSelector3())) { + Elements elements = doc.select(selector); + List selectedList = new ArrayList<>(); + for (Element element : elements) { + logger.info("[vip1Page] {} -> {}", selector, element.html()); + selectedList.add(element.html()); + } + reply1.put(selector, selectedList); + } + + Map> reply2 = new HashMap<>(); HtmlPage vip2Page = webClient.getPage(vip2PageUrl); - logger.info("vip2Page: {}", vip2Page.asXml()); - + doc = Jsoup.parse(vip2Page.asXml()); + for (String selector : List.of(session.getSelector1(), session.getSelector2(), session.getSelector3())) { + Elements elements = doc.select(selector); + List selectedList = new ArrayList<>(); + for (Element element : elements) { + logger.info("[vip2Page] {} -> {}", selector, element.html()); + selectedList.add(element.html()); + } + reply2.put(selector, selectedList); + } + + Map> reply3 = new HashMap<>(); HtmlPage vip3Page = webClient.getPage(vip3PageUrl); - logger.info("vip3Page: {}", vip3Page.asXml()); - - HtmlPage logoutPage = webClient.getPage(logoutUrl); - logger.info("logoutPage: {}", logoutPage.asXml()); - + doc = Jsoup.parse(vip3Page.asXml()); + for (String selector : List.of(session.getSelector1(), session.getSelector2(), session.getSelector3())) { + Elements elements = doc.select(selector); + List selectedList = new ArrayList<>(); + for (Element element : elements) { + logger.info("[vip3Page] {} -> {}", selector, element.html()); + selectedList.add(element.html()); + } + reply3.put(selector, selectedList); + } + + webClient.getPage(logoutUrl); + exchange.getMessage().setBody(Map.of("vip1Page", reply1, "vip2Page", reply2, "vip3Page", reply3)); + } catch (Exception e) { logger.error("LoginProcessor process error!", e); } diff --git a/src/main/java/com/example/sbcamel/processor/TestProcessor.java b/src/main/java/com/example/sbcamel/processor/TestProcessor.java new file mode 100644 index 0000000..4a32876 --- /dev/null +++ b/src/main/java/com/example/sbcamel/processor/TestProcessor.java @@ -0,0 +1,54 @@ +package com.example.sbcamel.processor; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.commons.io.FileUtils; +import org.apache.cxf.message.MessageContentsList; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; + +public class TestProcessor implements Processor { + + private static final Logger logger = LoggerFactory.getLogger(TestProcessor.class); + + @Value("${app.jsoup.html-file}") + private String htmlFilePath; + + @SuppressWarnings("unchecked") + @Override + public void process(Exchange exchange) throws Exception { + logger.info("in class: {}", exchange.getIn().getBody().getClass().getName()); + MessageContentsList mcl = (MessageContentsList) exchange.getIn().getBody(); + List selectors = (List) mcl.get(0); + logger.info("selectors: {}", selectors); + + File htmlFile = new File(htmlFilePath); + String html = FileUtils.readFileToString(htmlFile, StandardCharsets.UTF_8); + Document doc = Jsoup.parse(html); + Map> reply = new HashMap<>(); + + for (String selector : selectors) { + Elements elements = doc.select(selector); + List selectedList = new ArrayList<>(); + for (Element element : elements) { + logger.info("{} -> {}", selector, element.html()); + selectedList.add(element.html()); + } + reply.put(selector, selectedList); + } + exchange.getMessage().setBody(reply); + } + +} diff --git a/src/main/java/com/example/sbcamel/service/Session.java b/src/main/java/com/example/sbcamel/service/Session.java index 5ec68b6..0e431f0 100644 --- a/src/main/java/com/example/sbcamel/service/Session.java +++ b/src/main/java/com/example/sbcamel/service/Session.java @@ -24,6 +24,15 @@ public class Session implements Serializable { @NotNull @Size(min = 3, max = 40) private String password; + + @NotNull + private String selector1; + + @NotNull + private String selector2; + + @NotNull + private String selector3; public Session() { } @@ -59,6 +68,30 @@ public class Session implements Serializable { this.password = password; } + public String getSelector1() { + return selector1; + } + + public void setSelector1(String selector1) { + this.selector1 = selector1; + } + + public String getSelector2() { + return selector2; + } + + public void setSelector2(String selector2) { + this.selector2 = selector2; + } + + public String getSelector3() { + return selector3; + } + + public void setSelector3(String selector3) { + this.selector3 = selector3; + } + @Override public String toString() { return ReflectionToStringBuilder.toString(this); diff --git a/src/main/java/com/example/sbcamel/service/SessionService.java b/src/main/java/com/example/sbcamel/service/SessionService.java index 700140e..a8e5f3f 100644 --- a/src/main/java/com/example/sbcamel/service/SessionService.java +++ b/src/main/java/com/example/sbcamel/service/SessionService.java @@ -1,6 +1,8 @@ package com.example.sbcamel.service; import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.UUID; import jakarta.validation.Valid; @@ -33,7 +35,12 @@ public interface SessionService { Collection findSessions(); @POST - @Path("/login/{sessionId}") + @Path("/inspect/{sessionId}") @Produces(MediaType.APPLICATION_JSON) - Session login(@PathParam("sessionId") UUID sessionId); + Map> inspect(@PathParam("sessionId") UUID sessionId); + + @POST + @Path("/test") + @Produces(MediaType.APPLICATION_JSON) + Map>> test(List selectors); } \ No newline at end of file