java8 を練習しながら line bot を書いてみた


java8 + spring-boot で line bot を書きました

  • callback は https://...:443/linebot に
  • 必要情報は環境変数で
  • jackson, httpclient, lombok 使用
  • try catch はノーポリシー

controller

@RestController
public class LineBotController {
    @Autowired
    LineBotService botService;

    @RequestMapping(value = "/linebot")
    String index(HttpServletRequest request) throws RuntimeException {
        botService.sendToChannel(request);
        return "OK";
    }
}

model

// callback にくるやつ
@Data
public class LineBotResponse {
    List<LineBotResponseResult> result;
}

@Data
public class LineBotResponseResult {
    LineBotResponseContent content;
    BigDecimal createdTime;
    String eventType;
    String from;
    BigDecimal fromChannel;
    String id;
    List<String> to;
    BigDecimal toChannel;

}

@Data
public class LineBotResponseContent {
    String toType;
    BigDecimal createdTime;
    String from;
    String location;
    String id;
    List<String> to;
    String text;
    Map<String, String> contentMetadata;
    BigDecimal deliveredTime;
    BigDecimal contentType;
    String seq;

}

// line bot api に投げるやつ
@Data
public class LineBotRequest {
    List<String> to;
    final int toChannel = 1383378250;
    final String eventType = "138311608800106203";
    LineBotResponseContent content;
}

service

@Service
@val
@Slf4j
public class LineBotService {
    final String LINEBOTAPI_ENDPOINT = System.getenv("LINEBOTAPI_ENDPOINT");
    final String LINE_CHANNEL_ID = System.getenv("LINE_CHANNEL_ID");
    final String LINE_CHANNEL_SECRET = System.getenv("LINE_CHANNEL_SECRET");
    final String LINE_CHANNEL_MID = System.getenv("LINE_CHANNEL_MID");

    public void sendToChannel(HttpServletRequest request) {
        try {
            val jb = new StringBuffer();
            request.getReader().lines().forEach(jb::append);

            val mapper = new ObjectMapper();
            val botResponse = mapper.readValue(jb.toString(), LineBotResponse.class);

            botResponse.getResult().stream().forEach(this::sendRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    void sendRequest(LineBotResponseResult botResponse) {
        try {
            val botContent = botResponse.getContent();
            val request = new LineBotRequest();
            request.setTo(Arrays.asList(botContent.getFrom()));
            request.setContent(botContent);
            val text = botContent.getText();
            // 1もじづつばらばらにして送り返す
            Stream<String> stream = Arrays.stream(text.split(""));
            val post = new HttpPost(LINEBOTAPI_ENDPOINT);
            post.setHeader("Content-Type", "application/json; charset=UTF-8");
            post.setHeader("X-Line-ChannelID", LINE_CHANNEL_ID);
            post.setHeader("X-Line-ChannelSecret", LINE_CHANNEL_SECRET);
            post.setHeader("X-Line-Trusted-User-With-ACL", LINE_CHANNEL_MID);
            try (val httpclient = HttpClients.createDefault()) {
                stream.forEach(e -> sendOneRequest(httpclient, post, request, e));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    void sendOneRequest(CloseableHttpClient client, HttpPost post, LineBotRequest request, String oneString) {
        try {
            request.getContent().setText(oneString);
            val mapper = new ObjectMapper();
            val json = mapper.writeValueAsString(request);

            post.setEntity(new StringEntity(json, StandardCharsets.UTF_8));
            val res = client.execute(post);

            try (val br = new BufferedReader(
                    new InputStreamReader(res.getEntity().getContent(), StandardCharsets.UTF_8))) {
                br.lines().forEach(e -> log.info(e.toString()));
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("STATUSLINE:" + res.getStatusLine().toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

build.gradle

dependencies {
    compileOnly('org.projectlombok:lombok')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('com.fasterxml.jackson.core:jackson-databind:2.7.0')
    compile('com.fasterxml.jackson.core:jackson-annotations:2.7.0')
    compile('com.fasterxml.jackson.core:jackson-core:2.7.0')
    compile('org.apache.httpcomponents:httpasyncclient:4.1.1')
    compile('org.apache.httpcomponents:httpcore-nio:4.4.4')
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.12'
}