JavaRush /Blog Jawa /Random-JV /Kita nambahake kemampuan kanggo langganan klompok artikel...

Kita nambahake kemampuan kanggo langganan klompok artikel. (Bagian 1) - "Proyek Jawa saka A nganti Z"

Diterbitake ing grup
Hello! Dina iki kita bakal nambah langganan menyang klompok artikel ing JavaRush. Iki cocog karo masalah JRTB-5 ing GitHub. Ayo kula nerangake: JavaRush duwe bagean sing diarani Artikel , lan ing kono ana Grup Artikel. Ide iki kanggo nampa kabar babagan artikel anyar saka siji utawa luwih grup liwat bot telegram."Proyek Jawa saka A nganti Z": Nambahake kemampuan kanggo langganan klompok artikel.  Bagean 1 - 1

Tambah JRTB-5

Coba aku kasengsem karo artikel saka grup Kisah Sukses . Mulane, aku pengin langganan nganyari saka grup iki lan nampa link menyang publikasi anyar saben wektu. Minangka bagéan saka tugas iki, kita kudu sinau carane nggunakake API mbukak kanggo nggarap grup ing JavaRush. Mung ing wektu iki kedadeyan kaya ngono. Punika pranala menyang katrangan saka API mbukak .
Kanca-kanca! Apa sampeyan pengin langsung ngerti nalika kode anyar kanggo proyek utawa artikel anyar dirilis? Join channel tg aku . Ing kana aku ngumpulake artikel, pikirane lan pangembangan open-source bebarengan.

Apa swagger? Ayo dipikir saiki

Kita durung ngomong babagan swagger. Kanggo sing ora ngerti, aku bakal nerangake kanthi ringkes: iki minangka papan sing bisa dibukak ing API server lan nyoba nggawe sawetara panjaluk. Biasane, klompok swagger bisa njaluk. Ing kasus kita, ana telung klompok: forum-pitakonan , grup , kirim . Ing saben klompok bakal ana siji utawa luwih panjalukan sing nuduhake kabeh data sing dibutuhake kanggo mbangun panjalukan iki (yaiku, paramèter tambahan apa sing bisa dilewati, apa sing kudu dilakoni, cara http apa, lan liya-liyane). Aku menehi saran supaya maca lan nonton luwih akeh babagan topik iki, amarga iki minangka bagean pangembangan sing meh saben sampeyan bakal nemoni. Kanggo ngerteni, ayo ngerteni jumlah klompok ing JavaRush. Kanggo nindakake iki, nggedhekake grup kontroler grup banjur pilih Njaluk request /api/1.0/rest/groups/count . Bakal ngasilake jumlah klompok ing JavaRush. Delengen: "Proyek Jawa saka A nganti Z": Nambahake kemampuan kanggo langganan klompok artikel.  Bagean 1 - 2Gambar nuduhake yen pitakon iki ndhukung sawetara paramèter (kueri, jinis, saringan). Kanggo nyoba panjalukan iki, sampeyan kudu nemokake tombol Coba metu , sawise paramèter iki bisa dikonfigurasi: "Proyek Jawa saka A nganti Z": Nambahake kemampuan kanggo langganan klompok artikel.  Bagean 1 - 3Sampeyan uga bisa ngatur jinis, saringan, lan pitakon ing kana (pancen menarik ing kene: iki bakal dadi telusuran teks ing a klompok). Nanging saiki, ayo mbukak tanpa watesan lan deleng jumlah klompok ing JavaRush. Kanggo nindakake iki, klik Execute. Ing ngisor iki bakal ana respon (ing bagean Response Server) kanggo panyuwunan iki: "Proyek Jawa saka A nganti Z": Nambahake kemampuan kanggo langganan klompok artikel.  Bagean 1 - 4Kita ndeleng manawa ana 30 klompok total , panjaluk iki rampung ing 95ms lan ana sawetara header ing respon. Sabanjure, ayo nyoba ngatur sawetara paramèter. Ayo pilih parameter jinis sing padha karo nilai COMPANY lan deleng kepiye asil owah-owahan: "Proyek Jawa saka A nganti Z": Nambahake kemampuan kanggo langganan klompok artikel.  Bagean 1 - 5Ana 4. Carane mriksa iki? Iku gampang: sampeyan bisa pindhah menyang situs web, golek bagean artikel, pilih kabeh grup lan nambah filter cocok ana ( https://javarush.com/groups/all?type=COMPANY ). Lan ya pancen mung ana 4. Padahal sejatine ana telu :D "Proyek Jawa saka A nganti Z": Nambahake kemampuan kanggo langganan klompok artikel.  Bagean 1 - 6Nganti saiki cocok. Oalah, yen mriksa universitas, durung ana. Mung kanggo seneng-seneng, ndeleng apa sing kedadeyan yen sampeyan nyetel filter = MY ing browser sing sampeyan mlebu ing Javarush lan ora mlebu. Luwih lengkap babagan swagger - ing artikel iki babagan Habré .

Nulis klien kanggo Javarush API kanggo grup

Saiki, adhedhasar API mbukak, kita bakal nulis klien Jawa sing bisa nggawe panjalukan, nampa respon lan ngerti persis apa obyek bakal teka. Kita uga bakal njupuk obyek saka swagger, saka bagean Model (ing sisih ngisor kaca). Ayo nggawe paket anyar lan nyebat javarushclient ing jejere layanan, gudang. Ing mangsa ngarep, kita bakal mindhah iki menyang perpustakaan kapisah ing organisasi Komunitas Javarush lan bakal digunakake sacara eksklusif minangka dependensi. Kaping pisanan, sampeyan kudu nambah Unitrest, perpustakaan kanggo nggawe panjalukan http menyang JavaRush API:
<dependency>
  <groupId>com.konghq</groupId>
  <artifactId>unirest-java</artifactId>
  <version>${unirest.version}</version>
</dependency>
Lan lebokake versi ing blok properti:
<unirest.version>3.11.01</unirest.version>
Sawise kita duwe dependensi, kita bisa miwiti nambah kode. Ayo nggawe klien kanggo grup JavaRushGroupClient lan implementasine ing kelas JavaRushGroupClientImpl. Nanging pisanan sampeyan kudu nggawe DTO (obyek transfer data) - yaiku, kelas sing obyek bakal nggawa kabeh data sing dibutuhake kanggo klien. Kabeh model bisa dideleng ing swagger. Ing sisih paling ngisor ana bagean Models , ing ngendi sampeyan bisa ngetung. Iki minangka GroupDiscussionInfo ing swagger: Ing paket javarushclient, kita bakal nggawe "Proyek Jawa saka A nganti Z": Nambahake kemampuan kanggo langganan klompok artikel.  Bagean 1 - 7paket dto , sing bakal ditambahake, adhedhasar data saka swagger, kelas ing ngisor iki:
  • MeGroupInfoStatus :

    package com.github.javarushcommunity.jrtb.javarushclient.dto;
    
    /**
    * Member group status.
    */
    public enum MeGroupInfoStatus {
       UNKNOWN, CANDIDATE, INVITEE, MEMBER, EDITOR, MODERATOR, ADMINISTRATOR, BANNED
    }

  • MeGroupInfo :

    package com.github.javarushcommunity.jrtb.javarushclient.dto;
    
    import lombok.Data;
    
    /**
    * Group information related to authorized user. If there is no user - will be null.
    */
    @Data
    public class MeGroupInfo {
       private MeGroupInfoStatus status;
       private Integer userGroupId;
    }

  • GroupInfoType :

    package com.github.javarushcommunity.jrtb.javarushclient.dto;
    
    /**
    * Group Info type;
    */
    public enum GroupInfoType {
       UNKNOWN, CITY, COMPANY, COLLEGE, TECH, SPECIAL, COUNTRY
    }

  • UserDiscussionInfo :

    package com.github.javarushcommunity.jrtb.javarushclient.dto;
    
    import lombok.Data;
    
    /**
    * DTO for User discussion info.
    */
    @Data
    public class UserDiscussionInfo {
    
       private Boolean isBookmarked;
       private Integer lastTime;
       private Integer newCommentsCount;
    }

  • GroupVisibilitysdtatus :

    package com.github.javarushcommunity.jrtb.javarushclient.dto;
    
    /**
    * Group Visibility status.
    */
    public enum GroupVisibilityStatus {
       UNKNOWN, RESTRICTED, PUBLIC, PROTECTED, PRIVATE, DISABLED, DELETED
    }

  • Banjur - GroupInfo :

    package com.github.javarushcommunity.jrtb.javarushclient.dto;
    
    import lombok.Data;
    import lombok.ToString;
    
    /**
    * Group Info DTO class.
    */
    @Data
    @ToString
    public class GroupInfo {
    
       private Integer id;
       private String avatarUrl;
       private String createTime;
       private String description;
       private String key;
       private Integer levelToEditor;
       private MeGroupInfo meGroupInfo;
       private String pictureUrl;
       private String title;
       private GroupInfoType type;
       private Integer userCount;
       private GroupVisibilityStatus visibilityStatus;
    }

Wiwit GroupInfo lan GroupDiscussionInfo meh padha, ayo disambungake ing warisan - GroupDiscusionInfo :
package com.github.javarushcommunity.jrtb.javarushclient.dto;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

/**
* Group discussion info class.
*/
@EqualsAndHashCode(callSuper = true)
@Data
@ToString(callSuper = true)
public class GroupDiscussionInfo extends GroupInfo {

   private UserDiscussionInfo userDiscussionInfo;
   private Integer commentsCount;
}
Kita uga mbutuhake panyaring kanggo panyuwunan GroupFilter :
package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* Filters for group requests.
*/
public enum GroupFilter {

   UNKNOWN, MY, ALL
}
Ing panjalukan kanggo njaluk ID, bali GroupDiscussionInfo, lan ing panjalukan kanggo kumpulan grup, sampeyan bisa njaluk loro GroupInfo lan GroupDiscussionInfo. Amarga panjaluk bisa duwe jinis, pitakon, saringan, ngimbangi lan watesan, ayo nggawe kelas GroupRequestArgs sing kapisah lan nggawe kelas pembangun (waca apa pola pembangun):
package com.github.javarushcommunity.jrtb.javarushclient.dto;

import lombok.*;

import java.util.HashMap;
import java.util.Map;

import static java.util.Objects.nonNull;

/**
* Request arguments for group requests.
*/
@Builder
@Getter
public class GroupRequestArgs {

   private final String query;
   private final GroupInfoType type;
   private final GroupFilter filter;

   /**
    * specified where to start getting groups
    */
   private final Integer offset;
   /**
    * Limited number of groups.
    */
   private final Integer limit;

   public Map populateQueries() {
       Map queries = new HashMap<>();
       if(nonNull(query)) {
           queries.put("query", query);
       }
       if(nonNull(type)) {
           queries.put("type", type);
       }
       if(nonNull(filter)) {
           queries.put("filter", filter);
       }
       if(nonNull(offset)) {
           queries.put("offset", offset);
       }
       if(nonNull(limit)) {
           queries.put("limit", limit);
       }
       return queries;
   }
}
Kanggo nggoleki nomer grup, iku rada beda. Mung nduweni pitakon, jinis lan saringan. Lan koyone sampeyan ora pengin duplikat kode kasebut. Ing wektu sing padha, yen sampeyan miwiti nggabungake, dadi ora nyenengake nalika nggarap tukang. Dadi aku mutusake kanggo misahake lan mbaleni kode kasebut. Iki katon kaya GroupCountRequestArgs :
package com.github.javarushcommunity.jrtb.javarushclient.dto;

import lombok.Builder;
import lombok.Getter;

import java.util.HashMap;
import java.util.Map;

import static java.util.Objects.nonNull;

/**
* Request arguments for group count requests.
*/
@Builder
@Getter
public class GroupsCountRequestArgs {
   private final String query;
   private final GroupInfoType type;
   private final GroupFilter filter;

   public Map populateQueries() {
       Map queries = new HashMap<>();
       if (nonNull(query)) {
           queries.put("query", query);
       }
       if (nonNull(type)) {
           queries.put("type", type);
       }
       if (nonNull(filter)) {
           queries.put("filter", filter);
       }
       return queries;
   }
}
Ya, aku ora nyatakake yen rong kelas pungkasan duwe metode populateQueries, sing bakal nyiapake peta kanggo nggawe pitakon (sampeyan bakal weruh mengko). Adhedhasar kelas kasebut ing ndhuwur, ayo nggawe antarmuka kanggo JavaRushGroupClient :
package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupDiscussionInfo;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupInfo;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupRequestArgs;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupsCountRequestArgs;

import java.util.List;

/**
 * Client for Javarush Open API corresponds to Groups.
 */
public interface JavaRushGroupClient {

    /**
     * Get all the {@link GroupInfo} filtered by provided {@link GroupRequestArgs}.
     *
     * @param requestArgs provided {@link GroupRequestArgs}.
     * @return the collection of the {@link GroupInfo} objects.
     */
    List<GroupInfo> getGroupList(GroupRequestArgs requestArgs);

    /**
     * Get all the {@link GroupDiscussionInfo} filtered by provided {@link GroupRequestArgs}.
     *
     * @param requestArgs provided {@link GroupRequestArgs}
     * @return the collection of the {@link GroupDiscussionInfo} objects.
     */
    List<GroupDiscussionInfo> getGroupDiscussionList(GroupRequestArgs requestArgs);

    /**
     * Get count of groups filtered by provided {@link GroupRequestArgs}.
     *
     * @param countRequestArgs provided {@link GroupsCountRequestArgs}.
     * @return the count of the groups.
     */
    Integer getGroupCount(GroupsCountRequestArgs countRequestArgs);

    /**
     * Get {@link GroupDiscussionInfo} by provided ID.
     *
     * @param id provided ID.
     * @return {@link GroupDiscussionInfo} object.
     */
    GroupDiscussionInfo getGroupById(Integer id);
}
Rong panjaluk sing beda kanggo kasus kasebut nalika kita pengin nambah informasi GroupInfo utawa GroupDiscussionInfo. Yen ora, panjaluk kasebut padha, lan mung bedane yaiku yen ing salah sijine gendera Diskusi bakal bener, lan ing liyane bakal palsu. Mulane, ana 4 cara, ora telu. Saiki ayo miwiti implementasine:
package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupDiscussionInfo;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupInfo;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupRequestArgs;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupsCountRequestArgs;
import kong.unirest.GenericType;
import kong.unirest.Unirest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;

/**
* Implementation of the {@link JavaRushGroupClient} interface.
*/
@Component
public class JavaRushGroupClientImpl implements JavaRushGroupClient {

   private final String javarushApiGroupPath;

   public JavaRushGroupClientImpl(@Value("${javarush.api.path}") String javarushApi) {
       this.javarushApiGroupPath = javarushApi + "/groups";
   }

   @Override
   public List<GroupInfo> getGroupList(GroupRequestArgs requestArgs) {
       return Unirest.get(javarushApiGroupPath)
               .queryString(requestArgs.populateQueries())
               .asObject(new GenericType<list<GroupInfo>>() {
               })
               .getBody();
   }

   @Override
   public List<GroupDiscussionInfo> getGroupDiscussionList(GroupRequestArgs requestArgs) {
       return Unirest.get(javarushApiGroupPath)
               .queryString(requestArgs.populateQueries())
               .asObject(new GenericType<list<GroupDiscussionInfo>>() {
               })
               .getBody();
   }

   @Override
   public Integer getGroupCount(GroupsCountRequestArgs countRequestArgs) {
       return Integer.valueOf(
               Unirest.get(String.format("%s/count", javarushApiGroupPath))
                       .queryString(countRequestArgs.populateQueries())
                       .asString()
                       .getBody()
       );
   }

   @Override
   public GroupDiscussionInfo getGroupById(Integer id) {
       return Unirest.get(String.format("%s/group%s", javarushApiGroupPath, id.toString()))
               .asObject(GroupDiscussionInfo.class)
               .getBody();
   }


}
Aku nambah path kanggo API ing konstruktor nggunakake annotation Nilai wis menowo. Iki nuduhake yen nilai ing anotasi cocog karo lapangan ing file properti. Mulane, ayo nambah baris anyar menyang application.properties:
javarush.api.path=https://javarush.com/api/1.0/rest
Nilai iki saiki bakal ana ing sak panggonan kanggo kabeh klien API, lan yen path API diganti, kita bakal cepet nganyari. Sadurunge, aku palu kuku karo mikroskop, nampa respon saka request http liwat Unirest, nerjemahake menyang senar lan banjur parsed senar iki liwat Jackson ... Iku medeni, tedious lan mbutuhake akeh tambahan. Ing perpustakaan iki sampeyan bisa ndeleng kaya apa. Sanalika aku njaluk tangan, aku bakal refactor kabeh.
Sapa wae sing pengin nyoba nganyari perpustakaan iki - nambah obyek sing nampa mung nggunakake piranti perpustakaan unirest - nulis ing pesen pribadi utawa minangka masalah anyar ing perpustakaan kasebut. Iki bakal dadi pengalaman kerja nyata kanggo sampeyan, nanging aku ora mikir. Aku bakal nindakake review kode lengkap lan bantuan yen perlu.
Saiki pitakonan: apa kode kita bisa digunakake kaya sing dikarepake? Jawabane gampang: sampeyan mung kudu nulis tes kanggo dheweke. Kaya sing wis dakkandhakake luwih saka sepisan, pangembang kudu bisa nulis tes. Mulane, nggunakake UI Swagger kita, kita bakal ngirim panjalukan, katon ing respon lan ngganti menyang tes minangka asil samesthine. Sampeyan bisa uga langsung weruh yen jumlah klompok ora statis lan bisa diganti. Lan sampeyan bener. Pitakonan mung sepira kerepe nomer iki ganti? Arang banget, saengga sajrone pirang-pirang wulan kita bisa ujar manawa nilai kasebut bakal statis. Lan yen ana owah-owahan, kita bakal nganyari tes kasebut. Meet - JavaRushGroupClientTest:
package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupDiscussionInfo;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupInfo;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupRequestArgs;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupsCountRequestArgs;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;

import static com.github.javarushcommunity.jrtb.javarushclient.dto.GroupInfoType.TECH;

@DisplayName("Integration-level testing for JavaRushGroupClientImplTest")
class JavaRushGroupClientTest {

   private final JavaRushGroupClient groupClient = new JavaRushGroupClientImpl("https://javarush.com/api/1.0/rest");

   @Test
   public void shouldProperlyGetGroupsWithEmptyArgs() {
       //given
       GroupRequestArgs args = GroupRequestArgs.builder().build();

       //when
       List<GroupInfo> groupList = groupClient.getGroupList(args);

       //then
       Assertions.assertNotNull(groupList);
       Assertions.assertFalse(groupList.isEmpty());
   }

   @Test
   public void shouldProperlyGetWithOffSetAndLimit() {
       //given
       GroupRequestArgs args = GroupRequestArgs.builder()
               .offset(1)
               .limit(3)
               .build();

       //when
       List<GroupInfo> groupList = groupClient.getGroupList(args);

       //then
       Assertions.assertNotNull(groupList);
       Assertions.assertEquals(3, groupList.size());
   }

   @Test
   public void shouldProperlyGetGroupsDiscWithEmptyArgs() {
       //given
       GroupRequestArgs args = GroupRequestArgs.builder().build();

       //when
       List<GroupDiscussionInfo> groupList = groupClient.getGroupDiscussionList(args);

       //then
       Assertions.assertNotNull(groupList);
       Assertions.assertFalse(groupList.isEmpty());
   }

   @Test
   public void shouldProperlyGetGroupDiscWithOffSetAndLimit() {
       //given
       GroupRequestArgs args = GroupRequestArgs.builder()
               .offset(1)
               .limit(3)
               .build();

       //when
       List<GroupDiscussionInfo> groupList = groupClient.getGroupDiscussionList(args);

       //then
       Assertions.assertNotNull(groupList);
       Assertions.assertEquals(3, groupList.size());
   }

   @Test
   public void shouldProperlyGetGroupCount() {
       //given
       GroupsCountRequestArgs args = GroupsCountRequestArgs.builder().build();

       //when
       Integer groupCount = groupClient.getGroupCount(args);

       //then
       Assertions.assertEquals(30, groupCount);
   }

   @Test
   public void shouldProperlyGetGroupTECHCount() {
       //given
       GroupsCountRequestArgs args = GroupsCountRequestArgs.builder()
               .type(TECH)
               .build();

       //when
       Integer groupCount = groupClient.getGroupCount(args);

       //then
       Assertions.assertEquals(7, groupCount);
   }

   @Test
   public void shouldProperlyGetGroupById() {
       //given
       Integer androidGroupId = 16;

       //when
       GroupDiscussionInfo groupById = groupClient.getGroupById(androidGroupId);

       //then
       Assertions.assertNotNull(groupById);
       Assertions.assertEquals(16, groupById.getId());
       Assertions.assertEquals(TECH, groupById.getType());
       Assertions.assertEquals("android", groupById.getKey());
   }
}
Tes ditulis kanthi gaya sing padha karo sadurunge. Ana sawetara tes kanggo saben panjalukan. Ora ana gunane kanggo nyoba kabeh, amarga aku mikir yen API iki wis diuji kanthi cara sing paling apik.

Kesimpulan

Minangka bagéan saka artikel iki, kita nambah klien Java kanggo grup menyang JavaRush API. Kaya sing dikandhakake, urip lan sinau. Nalika aku nulis klien iki, aku njupuk kauntungan saka dokumentasi lan trep digunakake karya karo obyek sing nyedhiyani. Aku narik kawigaten sampeyan marang tugas sing dakkarepake. Yen wong kasengsem, nulis kula pesen pribadi, Aku luwih saka manawa iku bakal dadi pengalaman menarik banget. Iki minangka bagéan pisanan. Ing kaloro, kita bakal langsung ngleksanakake printah nambah lan (yen kita pas menyang siji artikel) kita bakal nambah njupuk dhaftar klompok sing pangguna wis langganan. Sabanjure, sapa wae sing duwe kepinginan lan bakat nulis teks kanggo bot, mangga nulis menyang kula ing PM. Aku dudu ahli babagan perkara iki lan bantuan apa wae bakal mbiyantu banget. Ayo dadi resmi kabeh iki minangka pangembangan open source, bakal menarik! Inggih, kaya biasane - kaya, langganan, lonceng , menehi bintang proyek kita , nulis komentar lan menehi rating artikel!
pranala migunani

Dhaptar kabeh materi ing seri kasebut ana ing wiwitan artikel iki.

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION