JavaRush /Java Blog /Random-TK /REST API we maglumatlary barlamak
Денис
Dereje
Киев

REST API we maglumatlary barlamak

Toparda çap edildi
Birinji bölüme baglanyşyk: REST API we indiki synag meselesi Gowy, programmamyz işleýär, biz ondan haýsydyr bir jogap alyp bileris, ýöne bu bize näme berýär? Peýdaly iş edenok. Edileninden gysga wagtda, peýdaly bir zady durmuşa geçireliň. Ilki bilen, build.gradle-a birnäçe täze garaşlylyk goşalyň, olar bize peýdaly bolar:
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.apache.commons:commons-collections4:4.4'
implementation 'org.springframework.boot:spring-boot-starter-validation'
Işlemeli hakyky maglumatlarymyzdan başlarys. Geliň, tutanýerlilik bukjamyza gaýdyp geleliň we guramany dolduryp başlalyň. .Adyňyzda bolsa, biz ony diňe bir meýdan bilen goýduk, soň bolsa awtoulag "@GeneratedValue (strategy = GenerationType.IDENTITY)" arkaly döredilýär "Geliň, birinji bapdaky tehniki aýratynlyklary ýada salalyň:
{
  "firstName": String,
  "lastName": String,
  "department": String,
  "salary": String
  "hired": String //"yyyy-mm-dd"
  "tasks": [
  ]
}
Ilkinji gezek ýeterlik meýdanlarymyz bar, geliň ony durmuşa geçirip başlalyň. Ilkinji üç ugur sorag döredenok - bu adaty setirler, ýöne aýlyk meýdany eýýäm teklip edýär. Näme üçin hakyky setir? Hakyky işde bu-da bolýar, bir müşderi size gelip: - Bu ýük ýüküni size ibermek isleýärin, siz bolsa ony işleýärsiňiz. Elbetde, egniňizi gysyp, edip bilersiňiz, ylalaşyga gelip, maglumatlary zerur formatda geçirmegiň has gowudygyny düşündirip bilersiňiz. Akylly müşderä duş gelendigimizi we sanlary san görnüşinde geçirmegiň has gowudygyny göz öňüne getireliň we pul hakda gürleşýändigimiz üçin goşa bolsun. Payük ýükümiziň indiki parametri işe alynjak senesi bolar, müşderi ony ylalaşylan formatda bize iberer: yyyy-mm-dd, bu ýerde birnäçe ýyllap jogapkärçilik çekýär, birnäçe günläp m garaşýar - 2022- 08-12. Häzirki wagtda iň soňky meýdan, müşderä berlen meseleleriň sanawy bolar. Elbetde, Task maglumatlar bazamyzdaky başga bir guramadyr, ýöne entek bu barada känbir bilemzok, şonuň üçin işgär bilen öňküsi ýaly iň esasy guramany dörederis. Indi göz öňüne getirip biljek ýeke-täk zadymyz, bir işgäre birden köp ýumuş berlip bilner, şonuň üçin “Bir-köp” diýilýän çemeleşmäni ulanarys. Jikme-jik gürlemek bilen, işgärler tablisasyndaky bir ýazgy meseleler tablisasyndaky birnäçe ýazgylara gabat gelip biler . Şeýle hem, bir işgäri beýlekisinden anyk tapawutlandyryp biler ýaly, özboluşlyNumber meýdançasy ýaly bir zat goşmak kararyna geldim. Häzirki wagtda biziň işgärler synpymyz şeýle:
@Entity
@Data
@Accessors(chain = true)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonIgnore
    Long id;

    @NotBlank
    @Column(unique = true)
    private String uniqueNumber;
    private String firstName;
    private String lastName;
    private String department;
    private Double salary;
    private LocalDate hired;

    @OneToMany
    @JoinColumn(name = "employee_id")
    List<Task> tasks = new ArrayList<>();
}
Taslama guramasy üçin aşakdaky synp döredildi:
@Entity
@Data
@Accessors(chain = true)
public class Task {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long taskId;
}
Aýdyşym ýaly, Taskda täze bir zat görmeris, bu synp üçin täze ammar döredildi, bu işgär üçin ammaryň göçürmesi - men bermerin, meňzeşlik bilen döredip bilersiňiz. Emma Işgärler synpy hakda gürleşmegiň manysy bar. Aýdyşym ýaly, birnäçe ugur goşduk, ýöne iň soňkusy indi gyzyklandyrýar - meseleler. Bu sanaw <Task> meseleler , derrew boş ArrayList bilen başlaýar we birnäçe bellikler bilen bellenýär. 1. @OneToMany Aýdyşym ýaly, bu işgärleriň wezipelere bolan gatnaşygy bolar. 2. @JoinColumn - guramalaryň goşuljak sütüni. Bu ýagdaýda, işgäriň şahsyýetini görkezýän Taslama tablisasynda bir işgär_id sütüni dörediler; bu bize ForeighnKey hökmünde hyzmat eder Adyň mukaddesligi ýaly görünse-de, sütüne islän zadyňyzy berip bilersiňiz. Diňe şahsyýetnamany däl, eýsem hakyky sütüni ulanmaly bolsaňyz, ýagdaý birneme çylşyrymlaşar; bu mowzuga soňrak degip geçeris. 3. ID-den ýokarda täze bir belligi gören bolmagyňyz mümkin - @JsonIgnore. Id içerki guramamyz bolansoň, ony müşderä gaýtarmak hökman däl. 4. @NotBlank, meýdançanyň boş ýa-da boş setir bolmaly däldigini aýdýan tassyklama üçin ýörite düşündirişdir. @ Sütün (üýtgeşik = dogry) bu sütüniň özboluşly gymmatlyklarynyň bolmalydygyny aýdýar. Şeýlelikde, eýýäm iki sany guramamyz bar, hatda biri-birine bagly. Olary programmamyza goşmagyň wagty geldi - geliň hyzmatlar we gözegçilik edijiler bilen iş salyşalyň. Ilki bilen, getAllEmployees () usulyndan stubymyzy aýyralyň we ony hakykatdanam işleýän bir zada öwüreliň:
public List<Employee> getAllEmployees() {
       return employeeRepository.findAll();
   }
Şeýlelik bilen, ammarymyz maglumatlar bazasyndaky ähli zatlary sarsdyrar we bize berer. Şeýle hem meseläniň sanawyny aljakdygy bellärliklidir. Itöne ony çykarmak elbetde gyzykly, ýöne ol ýerde hiç zat ýok bolsa näme çykarýar? Dogry, bu ýerde nädip bir zat goýmalydygyny anyklamalydyrys. Ilki bilen kontrollerimize täze usul ýazalyň.
@PostMapping("${application.endpoint.employee}")
    public ResponseEntity<?> createOrUpdateEmployee(@RequestBody final Employee employee) {
        try {
            employeeService.save(employee);
        } catch (ValidationException e) {
            return ResponseEntity.badRequest().body(e.getViolations());
        }
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }
Bu @PostMapping, ýagny işgärlerimiziň ahyrky nokadyna gelýän POST haýyşlaryny işleýär. Umuman aýdanymda, bu gözegçä berlen haýyşlaryň hemmesi bir nokada geler diýip pikir etdim, geliň muny biraz ýönekeýleşdireliň. Application.yml-daky gowy sazlamalarymyzy ýadyňyzdamy? Geliň, olary düzedeliň. Programma bölümi indi şeýle bolsun:
application:
  endpoint:
    root: api/v1
    employee: ${application.endpoint.root}/employees
    task: ${application.endpoint.root}/tasks
Bu bize näme berýär? Dolandyryjyda her aýratyn usul üçin kartalaşdyryşy aýryp biljekdigimiz we ahyrky nokady @RequestMapping ("$ {application.endpoint.employee}") düşündirişinde synp derejesinde kesgitlener . Bu häzirki gözellik gözegçimiz:
@RestController
@RequestMapping("${application.endpoint.employee}")
@RequiredArgsConstructor
public class EmployeeController {

    private final EmployeeService employeeService;

    @GetMapping
    public ResponseEntity<List<Employee>> getEmployees() {
        return ResponseEntity.ok().body(employeeService.getAllEmployees());
    }

    @PostMapping
    public ResponseEntity<?> createOrUpdateEmployee(@RequestBody final Employee employee) {
        try {
            employeeService.save(employee);
        } catch (ValidationException e) {
            return ResponseEntity.badRequest().body(e.getViolations());
        }
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }
}
Şeýle-de bolsa, dowam edeliň. CreateOrUpdateEmployee usulynda näme bolýar? Elbetde, işgärlerimiziň hyzmatynda tygşytlaýyş usuly bar, bu ähli tygşytlaýyş işlerine jogapkär bolmaly. Şeýle hem bu usulyň özüni düşündirýän at bilen kadadan çykma döredip biljekdigi äşgärdir. Bular. haýsydyr bir tassyklama geçirilýär. Jogap, 201 dörediljekdigine ýa-da nädogry zatlaryň sanawy bilen 400 badRequest boljakdygyna gönüden-göni tassyklama netijelerine baglydyr. Öňe seretseň, bu biziň täze tassyklama hyzmatymyz, zerur meýdanlaryň bardygyny barlaýan maglumatlary barlaýar (@NotBlank ýadyňyzdamy?) We şeýle maglumatlaryň bize laýyk gelýändigini ýa-da ýokdugyny kesgitleýär. Tygşytlaýyş usulyna geçmezden ozal, bu hyzmaty tassyklap, durmuşa geçireliň. Munuň üçin hyzmatymyzy goýjak aýratyn tassyklama bukjasyny döretmegi teklip edýärin.
import com.example.demo.exception.ValidationException;
import com.example.demo.persistence.entity.Employee;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;

@Service
@RequiredArgsConstructor
public class ValidationService {

    private final Validator validator;

    public boolean isValidEmployee(Employee employee) throws ValidationException {
        Set<Constraintviolation<Employee>> constraintViolations = validator.validate(employee);

        if (CollectionUtils.isNotEmpty(constraintViolations)) {
            throw new ValidationException(buildViolationsList(constraintViolations));
        }
        return true;
    }

    private <T> List<Violation> buildViolationsList(Set<Constraintviolation<T>> constraintViolations) {
        return constraintViolations.stream()
                                   .map(violation -> new Violation(
                                                   violation.getPropertyPath().toString(),
                                                   violation.getMessage()
                                           )
                                   )
                                   .toList();
    }
}
Synp gaty uly bolup çykdy, ýöne howsala düşmäň, indi düşüneris :) Bu ýerde taýýar tassyklama kitaphanasynyň gurallaryny ulanýarys javax.validation Bu kitaphana bize täze garaşlylyklardan geldi. build.graddle durmuşa geçirmek üçin goşuldy 'org.springframework.boot: spring-boot-starter -validation' Köne dostlarymyz hyzmaty we zerurArgsConstructor Bu synp hakda bilmeli zatlarymyzy eýýäm bize aýdyň, hususy gutarnykly tassyklaýjy meýdançam bar. Jady eder. Işgär guramasyny geçip bilýän isValidEmployee usulyny döretdik, bu usul biraz soňrak ýazarys, ValidationException atýar. Hawa, bu biziň zerurlyklarymyz üçin adaty kadadan çykma bolar. Validator.validate (işgäri) ​​usulyny ulanyp, ConstraintViolation obýektleriniň sanawyny alarys - ozal goşan tassyklama belliklerimiz bilen bu gapma-garşylyklar. Geljekki logika ýönekeý, eger bu sanaw boş bolmasa (ýagny düzgün bozmalar bar), kadadan çykma edýäris we düzgün bozmalaryň sanawyny düzýäris - buildViolationsList usuly, munuň umumy usuldygyny ýadyňyzdan çykarmaň. dürli obýektleriň bozulmalarynyň sanawlary bilen işläp biler - başga bir zady tassyklasak geljekde peýdaly bolup biler. Bu usul aslynda näme edýär? Akym API ulanyp, düzgün bozmalaryň sanawyndan geçýäris. Karta usulyndaky her bir düzgüni öz bozulma obýektimize öwürýäris we ýüze çykan ähli zatlary sanawa ýygnaýarys. Biz ony gaýtaryp berýäris. Biziň bozýan zadymyz başga näme? Ine ýönekeý ýazgy
public record Violation(String property, String message) {}
Javaazgylar, hiç hili logika ýa-da başga bir zat bolmazdan, maglumatly bir obýekt gerek bolsa, Java-da şeýle aýratyn täzeliklerdir. Munuň näme üçin edilendigine entek düşünmedimem, käwagt gaty amatly zat. Adaty synp ýaly aýratyn faýlda döredilmeli. Adaty ValidationException-a gaýdyp gelmek - bu şeýle görünýär:
@RequiredArgsConstructor
public class ValidationException extends Exception {

    @Getter
    private final List<Violation> violations;
}
Ol ähli düzgün bozmalaryň sanawyny saklaýar, Lombok düşündiriş - Getter sanawa goşulýar we başga bir Lombok düşündirişiniň üsti bilen zerur konstruktory "durmuşa geçirdik" :) Bu ýerde isValid-iň özüni alyp barşyny dogry ýerine ýetirmeýändigimi bellemelidiris. ... usul, ýa-da dogry ýa-da kadadan çykýar, ýöne adaty False bilen çäklenmeli. Kadadan çykma çemeleşmesi edilýär, sebäbi bu ýalňyşlygy müşderä gaýtaryp bermek isleýärin, bu bolsa bulean usulyndan dogry ýa-da ýalňyşdan başga zady yzyna gaýtarmaly. Diňe içerki tassyklama usullary bar bolsa, kadadan çykma zerurlygy ýok, bu ýerde hasaba alynmak talap edilýär. Şeýle-de bolsa, “EmployeeService” -e gaýdyp geleliň, obýektleri tygşytlamaga başlamalydyrys :) Geliň, bu synpyň häzir nähili bolýandygyny göreliň:
@Service
@RequiredArgsConstructor
public class EmployeeService {

    private final EmployeeRepository employeeRepository;
    private final ValidationService validationService;

    public List<Employee> getAllEmployees() {
        return employeeRepository.findAll();
    }

    @Transactional
    public void save(Employee employee) throws ValidationException {
        if (validationService.isValidEmployee(employee)) {
            Employee existingEmployee = employeeRepository.findByUniqueNumber(employee.getUniqueNumber());
            if (existingEmployee == null) {
                employeeRepository.save(employee);
            } else {
                existingEmployee = updateFields(existingEmployee, employee);
                employeeRepository.save(existingEmployee);
            }
        }
    }

    private Employee updateFields(Employee existingEmployee, Employee updatedEmployee) {
        return existingEmployee.setDepartment(updatedEmployee.getDepartment())
                               .setSalary(updatedEmployee.getSalary())
            				 //TODO implement tasks merging instead of replacement
                               .setTasks(updatedEmployee.getTasks());
    }
}
Täze jemleýji emläk şahsy jemleýji ValidationService validationService üns beriň; Tygşytlaýyş usulynyň özi @Transactional düşündiriş bilen bellik edilýär, eger RuntimeException kabul edilse, üýtgeşmeler yzyna öwrüler. Ilki bilen, ýaňy ýazan hyzmatymyzy ulanyp gelýän maglumatlary tassyklaýarys. Everythinghli zat oňat giden bolsa, maglumatlar bazasynda bar bolan işgäriň bardygyny ýa-da ýokdugyny barlaýarys (üýtgeşik belgini ulanyp). Notok bolsa, täzesini ýatda saklaýarys, eger bar bolsa, synpdaky meýdanlary täzeleýäris. Aý hawa, hakykatdanam nädip barlamaly? Hawa, bu gaty ýönekeý, Işgärleriň ammaryna täze usul goşduk:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    Employee findByUniqueNumber(String uniqueNumber);
}
Belli zat näme? Bu ýerde elýeterli bolsa-da, haýsydyr bir logika ýa-da SQL talap ýazmadym. Bahar, usulyň adyny okamak bilen, meniň isleýän zadymy kesgitleýär - ByUniqueNumber-i tapyň we degişli setiri usula geçiriň. Meýdanlary täzelemäge gaýdyp gelmek - bu ýerde umumy düşünjäni ulanmagy we diňe bölümi, aýlyk we wezipeleri täzelemegi makul bildim, sebäbi adyny üýtgetmek, kabul ederlikli zat bolsa-da, henizem adaty zat däl. Işe kabul edilýän senäni üýtgetmek, umuman jedelli mesele. Bu ýerde näme etmek gowy bolardy? Taslama sanawlaryny birleşdiriň, ýöne entek wezipelerimiz ýok we olary nädip tapawutlandyrmalydygyny bilmeýänligimiz sebäpli TODO-dan çykarys. Frankenşteýnimizi işe girizmäge synanyşalyň. Hiç zady suratlandyrmagy ýatdan çykarmadyk bolsam, işlemeli, ýöne ilki bilen, şu ýerde alan synp agajymyz: REST API we maglumatlary barlamak - 1 Üýtgedilen synplar gök reňkde, täzeleri ýaşyl reňkde görkezilýär, işleýän bolsaňyz şular ýaly görkezmeleri alyp bilersiňiz. git ammary bilen, ýöne git biziň makalamyz üçin mowzuk däl, şonuň üçin bu barada durup geçmeris. Şeýlelik bilen, häzirki wagtda GET we POST iki usuly goldaýan bir ahyrky nokadymyz bar. .Eri gelende aýtsak, ahyrky nokat hakda käbir gyzykly maglumatlar. Mysal üçin, näme üçin getAllEmployees ýa-da Employees döretmek ýaly GET we POST üçin aýratyn nokatlar bölmedik? Hemme zat diýseň ýönekeý - ähli haýyşlar üçin ýekeje nokat bolmak has amatly. Routol marşruty HTTP usuly esasynda ýüze çykýar we içgin bolýar, getAllEmployees, getEmployeeByName-iň ähli üýtgeşikliklerini ýatda saklamagyň hajaty ýok, al ... täzeläň ... dörediň ... pozuň ... Geliň näme alandygymyzy synap göreliň. Öňki makalada bize “Poçta” gerek boljakdygyny ýazypdym, ony gurmagyň wagty geldi. Programma interfeýsinde täze POST haýyşyny döredýäris REST API we maglumatlary barlamak - 2 we ibermäge synanyşýarys. Hemme zat gowy geçen bolsa, ekranyň sag tarapynda 201-nji status alarys. Foröne, mysal üçin, şol bir zady iberen, ýöne özboluşly bir belgisiz (tassyklamamyz bar) başga bir jogap alýaryn: REST API we maglumatlary barlamak - 3 Geliň, doly saýlamamyzyň nähili işleýändigini barlap göreliň - şol bir nokat üçin GET usulyny döredýäris we iberýäris . REST API we maglumatlary barlamak - 4 Everythinghli zadyň edil meniň üçin bolşy ýaly netije berendigine we indiki makalada görülmegine tüýs ýürekden umyt edýärin .
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION