ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] FCM Push API 만들기
    JAVA 2018. 9. 4. 21:01
    반응형


    FCM이란?

    FCM이란 Firbase Cloud Messaging의 약자로 GCM의 업그레이드 버전이지만 FireBase 진영에 속합니다.

    앞으로 글은 새로운 기능을 더이상 GCM에는 추가하지않고 FCM에만 추가한다고 발표를 하였습니다. 이토록 강력히 FCM 사용을 권장하고 있으니 기존 GCM으로 개발했던 기능들도 FCM으로 리펙토링 하는 추세입니다.


    들어가기 앞서

    해당 포스트는 Spirng기반의 간단한 Push Api서버를 구축하는 것입니다. 

    Controller로 구현하되 최대한 심플하게 작성하였습니다. 

    Fcm Server 발송 쪽만 작성되어 있으며 Client 처리 부분은 작성되어 있지 않습니다.

    Firbaes App 등록 절차 및 Client Toeken 발급 절차는 설명하고 있지 않습니다. 해당 발급 절차는 가이드 url 참고 하여주시기 바랍니다.  코드를 보기전 꼭 Firebase 가이드를 읽고 봐주시기 바랍니다.


    Client Token 발급 절차 

    https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko


    Admin Fcm 메시지 전송 가이드

    https://firebase.google.com/docs/cloud-messaging/admin/send-messages?hl=ko


    Fcm Server Key 발급 절차




    FCM 메시지 매개변수



    FcmCont

    package push.cont;

    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.beans.factory.annotation.Autowired;
    import push.domain.FcmDomain;
    import push.util.FcmUtil;


    @RestController
    class FcmCont {

    @Autowired
    FcmUtil fcmUtil;

    @RequestMapping(value = '/fcmPush', method = RequestMethod.POST)
    Object fcmPush(@Valid @RequestBody FcmPushData fcmPushData) throws Exception {

    HashMap<String, Object> reSult = new HashMap<String, Object>();

    reSult.put("rt_code",0);

    fcmUtil.send(fcmPushData.title, fcmPushData.body, fcmPushData.device);

    return reSult;
    }


    }


    FcmUtil

    package push.util;

    import org.springframework.stereotype.Component;
    import org.springframework.messaging.support.MessageBuilder;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.annotation.Async;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import push.http.FcmGw;

    @Component
    class FcmUtil{

    @Autowired
    ObjectMapper mapper;

    @Autowired
    FcmGw fcmGw;

    private String FCM_SERVER_KEY = "FCM_KEY를 넣어주세요";
    private String FCM_URL = "https://fcm.googleapis.com/fcm/send";

    @Async("asyncTask")
    void send(String title, String body, String device) {

    String param = buildupMsg(title, body, device);

    String resJson = fcmGw.sendReq(MessageBuilder.withPayload(param)
    .setHeader('url', FCM_URL)
    .setHeader('Content-Type', 'application/json;charset=UTF-8')
    .setHeader('Authorization','key='+FCM_SERVER_KEY)
    .build()).getPayload().toString();
    }

    String buildupMsg(String title, String body, String device) throws Exception{

    String param = mapper.writeValueAsString('notification' : ['title' : title,
    'body' : body],
    'to' : device);
    return param;

    }

    }


    FcmPushData

    package push.domain;
    class FcmPushData {
    String title="";
    String body ="";
    String device="";

    }

    FcmConf
    package push.http;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.task.TaskExecutor;
    import org.springframework.expression.Expression;
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.client.ClientHttpRequestFactory;
    import org.springframework.http.client.SimpleClientHttpRequestFactory;
    import org.springframework.integration.annotation.ServiceActivator;
    import org.springframework.integration.channel.ExecutorChannel;
    import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
    import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
    import org.springframework.integration.mapping.HeaderMapper;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.MessageHandler;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    import java.util.concurrent.ThreadPoolExecutor;

    @Configuration
    class FcmConf {
    @Bean
    MessageChannel fcmCh() {
    return new ExecutorChannel(fcmTask());
    }

    @Bean
    ClientHttpRequestFactory fcmFac() {
    SimpleClientHttpRequestFactory fcmFac = new SimpleClientHttpRequestFactory();
    fcmFac.setReadTimeout(2000);
    fcmFac.setConnectTimeout(2000);
    return fcmFac;
    }

    @Bean
    TaskExecutor fcmTask() {
    ThreadPoolTaskExecutor fcmTask = new ThreadPoolTaskExecutor();
    fcmTask.setThreadNamePrefix('fcmTask-');
    fcmTask.setCorePoolSize(5);
    fcmTask.setMaxPoolSize(10);
    fcmTask.setQueueCapacity(0);
    fcmTask.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
    return fcmTask;
    }

    @Bean
    @ServiceActivator(inputChannel = 'fcmCh')
    MessageHandler fcmReq() {
    HttpRequestExecutingMessageHandler fcmReq = new HttpRequestExecutingMessageHandler('{url}');
    fcmReq.setRequestFactory(fcmFac());
    fcmReq.setHeaderMapper(fcmHeaderMapper());
    fcmReq.setEncodeUri(false);
    fcmReq.setHttpMethod(HttpMethod.POST);
    fcmReq.setCharset('UTF-8');
    fcmReq.setExpectedResponseType(String.class);
    Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
    ExpressionParser parser = new SpelExpressionParser();
    uriVariableExpressions.put('url', parser.parseExpression('headers[\'url\']'));
    fcmReq.setUriVariableExpressions(uriVariableExpressions);
    fcmReq.setExtractPayload(true);
    return fcmReq;
    }

    @Bean
    HeaderMapper fcmHeaderMapper() {
    DefaultHttpHeaderMapper fcmHeaderMapper = new DefaultHttpHeaderMapper();
    fcmHeaderMapper.setOutboundHeaderNames('*');
    fcmHeaderMapper.setInboundHeaderNames('*');
    fcmHeaderMapper.setUserDefinedHeaderPrefix('');
    return fcmHeaderMapper;
    }
    }

    FcmGw
    package push.http;

    import org.springframework.integration.annotation.Gateway;
    import org.springframework.integration.annotation.MessagingGateway;
    import org.springframework.messaging.Message;
    @MessagingGateway

    interface FcmGw {
    @Gateway(requestChannel = 'fcmCh')
    Message<String> sendReq(Message<String> postMsg);
    }
    Application에 추가!
    @Bean(name = "asyncTask")
    public TaskExecutor asyncTask() {

    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setThreadNamePrefix("asyncTask-");
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(100);
    executor.setQueueCapacity(0);
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
    return executor;
    }


    반응형

    'JAVA' 카테고리의 다른 글

    [JAVA] 람다식(Lambda)의 개념 및 사용법  (11) 2018.09.28
Designed by Tistory.