Spring Boot - многопоточность на одном объекте - PullRequest
0 голосов
/ 09 октября 2018

Я работаю над проектом, который управляет базой данных контактов с опциями CRUD, но я не знаю, как обрабатывать многопоточность.

Я использую Java 8 и подпружинную загрузку 2.0.4 RELEASE

ОБНОВЛЕНИЕ -> Код вместо изображений

Это контроллер:

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:4200", allowedHeaders="*")
public class ContactController {

    @Autowired
    private ContactService contactService;

    /*---  Toute la liste  ---*/
    @GetMapping("/contact")
    public List<ContactDTO> getDestinataires() {
        return contactService.getContacts();
    }

    /* ------------------------- CRUD ----------------------- */

    // Creation contact
    @PostMapping("/contact/create")
    public boolean create(@Valid @RequestBody ContactDTO contact) {
        return contactService.create(contact);
    }

    // infos d'un contact
    @GetMapping("/contact/{id}")
    public ContactDTO read(@PathVariable Integer id) {
        return contactService.getContact(id);
    }

    // Maj contact
    @PutMapping("/contact/update")
    public boolean update(@RequestBody ContactDTO contact) {
        return contactService.update(contact);
    }

    // Maj contact
    @DeleteMapping("/contact/delete/{id}")
    public boolean delete(@PathVariable Integer id) {
        return contactService.delete(id);
    }

}

Служба (с аннотацией @Service) извлекает объект ContactDTO, отправленный фронтом, и устанавливает объект контакта,Он работает с Java-классом CoreServices (без аннотаций Spring).

Вот так:

@Service
public class ContactService extends CoreServices{

    private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ContactService.class);

    public boolean update(ContactDTO contactDTOFront) {

        logger.info("ContactService - start update method");
        try {
            // contrôle si contact existe
            setContact(getContactRepo().findByIdaicontact(contactDTOFront.getIdaicontact()));
            if (getContact() == null) {
                return false;
            }

            // alimentation du bean hibernate par le bean dto.
            contactDTOFront.alimBean(this);

            // maj de la bdd
            if (getContactRepo().save(getContact()) == null) {
                return false;
            }

        } catch (Exception ure) {
            logger.error("ContactService - Error update method: " + ExceptionUtils.getStackTrace(ure));
            return false;
        }

        return true;
    }

Все компоненты EJB (DTO и сущности) управляются в классе CoreServices:

public class CoreServices {

    @Autowired
    private ContactRepository contactRepo;

    // Bean Contact
    Contact contact = new Contact();
    ContactDTO contactDTO = new ContactDTO();
    List<ContactDTO> contactDTOList = new ArrayList<ContactDTO>();
    List<Contact> contactList = new ArrayList<Contact>();

    public ContactRepository getContactRepo() {
        return contactRepo;
    }
    public Contact getContact() {
        return contact;
    }
    public void setContact(Contact contact) {
        this.contact = contact;
    }
    public ContactDTO getContactDTO() {
        return contactDTO;
    }
    public void setContactDTO(ContactDTO contactDTO) {
        this.contactDTO = contactDTO;
    }
    public List<ContactDTO> getContactDTOList() {
        return contactDTOList;
    }
    public void setContactDTOList(List<ContactDTO> contactDTOList) {
        this.contactDTOList = contactDTOList;
    }
    public List<Contact> getContactList() {
        return contactList;
    }
    public void setContactList(List<Contact> contactList) {
        this.contactList = contactList;
    }

Чтобы установить компонент EJB, я использую метод "alimBean", определенный в объекте DTO.Этот метод вызывается в моем сервисе.

 public void alimBean(CoreServices service) throws Exception {

logger.info("ContactDTO - start alimBean method");
service.getContact().setIdaicontact(this.getIdaicontact());
service.getContact().setIdentifiant(this.getIdentifiant());
service.getContact().setIdaisite(this.getIdaisite());
service.getContact().setIdaitype(this.getIdaitype());
service.getContact().setNom(this.getNom());
service.getContact().setPrenom(this.getPrenom());
service.getContact().setEmail(this.getEmail());
service.getContact().setComment(this.getComment());
service.getContact().setStatus(this.getStatus());
service.getContact().setLocked(this.getLocked());
service.getContact().setUserlock(this.getUserlock());
service.getContact().setCreuser(this.getCreuser());
service.getContact().setUpduser(this.getUpduser());

// Gestion des dates STRING -> DATE

logger.info("ContactDTO - end alimBean method");

}

Теперь при условии, что два запроса на обновление обрабатываются одновременно.Как это работает ?Я читал некоторые Туто о "синхронизации", но они немного запутались для меня.Я не знаю, является ли это лучшим способом, и я не хочу нарушать весь код, за исключением случаев, когда это единственное решение для обработки этого случая многопоточности

Что я могу добавить к этому коду, чтобы убедиться, что второйВ запросе не будет установлен объект Contact до окончания первого запроса.

1 Ответ

0 голосов
/ 09 октября 2018

Вы должны синхронизировать только действия по обновлению и удалению, например, id, если оно уникально.Вы можете использовать мою библиотеку, но она в альфа-версии, но она протестирована и работает хорошо.Вы должны добавить зависимость:

<dependency>
  <groupId>com.jsunsoft.util</groupId>
  <artifactId>concurrent</artifactId>
  <version>0.0.1-alpha2</version>
</dependency>

и написать код, подобный этому

import com.jsunsoft.util.concurrent.locks.Lock;

public class ContactService extends CoreServices {
  private final Lock contactLock = new StripedLock(minimumNumberOfStripes, lockTimeSec);

public boolean update(ContactDTO contactDTOFront) {
    logger.info("ContactService - start update method");
    try {
        updateSynched(contactDTOFront);
    } catch (Exception ure) {
        logger.error("Co: " + ExceptionUtils.getStackTrace(ure));
        return false;
    }
    return true;
}

//you can add the method updateSynched
private void updateSynched(ContactDTO contactDTOFront) throws Exception {
    contactLock.lock(contactDTOFront.getId(), () -> {
        setContact(getContactRepo().findByIdaicontact(contactDTOFront.getIdaicontact()));
        if (getContact() == null) {
            throw new Exception("msg");
        }
        // alimentation du bean hibernate par le bean dto.
        contactDTOFront.alimBean(this);
        // maj de la bdd
        if (getContactRepo().save(getContact()) == null) {
            throw new Exception("msg");
        }
    });
}
}

Примечание. В этой библиотеке я использовал блокировку с использованием гуавы, если вы хотите использовать напрямую API-интерфейс гуавы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...