Onde exatamente é um objeto de modelo criado em Spring MVC?

JAVA:

Depois de passar por alguns tutoriais e leitura inicial do documento a partir da referência docs.spring.org eu entendi que ele é criado no controlador de uma classe POJO criado pelo desenvolvedor. Mas ao ler este me deparei com o parágrafo abaixo:

Um @ModelAttributeem um argumento método indica o argumento deve ser recuperada a partir do modelo. Se não estiver presente no modelo, o argumento deve ser instanciado em primeiro lugar e, em seguida, adicionados ao modelo. Uma vez presentes no modelo, os campos do argumento deve ser preenchida a partir de todos os parâmetros de solicitação que têm nomes correspondentes. Isto é conhecido como dados de ligação em Spring MVC, um mecanismo muito útil que poupa de ter de analisar cada campo de formulário individualmente.

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(@ModelAttribute Pet pet) {

}

Documentação primavera

No parágrafo que é mais preocupante é a linha:

"Se não estiver presente no modelo ..."

Como podem os dados estar lá no modelo? (Porque não criamos um modelo - que será criado por nós.)

Além disso, tenho visto alguns métodos controlador aceitante do Modeltipo como um argumento. O que isso significa? Está ficando a Modelalgum lugar criado? Se assim for, que está criando para nós?

Andrew Tobilko:

Se não estiver presente no modelo, o argumento deve ser instanciado em primeiro lugar e, em seguida, adicionados ao modelo.

O parágrafo descreve o seguinte trecho de código:

if (mavContainer.containsAttribute(name)) {
    attribute = mavContainer.getModel().get(name);
} else {
    // Create attribute instance
    try {
        attribute = createAttribute(name, parameter, binderFactory, webRequest);
    }
    catch (BindException ex) {
        ...
    }
}
...
mavContainer.addAllAttributes(attribute);

(retirado ModelAttributeMethodProcessor#resolveArgument)

Para cada pedido, Primavera inicializa uma ModelAndViewContainerinstância que grava modelo e vista-relacionado decisões tomadas por HandlerMethodArgumentResolvers e HandlerMethodReturnValueHandlers durante o curso de invocação de um método de controlador.

A recém-criado ModelAndViewContainerobjecto é inicialmente preenchido com atributos de flash (se houver):

ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));

Isso significa que o argumento não será inicializado se ele já existe no modelo.

Para provar isso, vamos passar a um exemplo prático.

A Petclasse:

public class Pet {
    private String petId;
    private String ownerId;
    private String hiddenField;

    public Pet() {
         System.out.println("A new Pet instance was created!");
    }

    // setters and toString
}

A PetControllerclasse:

@RestController
public class PetController {

    @GetMapping(value = "/internal")
    public void invokeInternal(@ModelAttribute Pet pet) {
        System.out.println(pet);
    }

    @PostMapping(value = "/owners/{ownerId}/pets/{petId}/edit")
    public RedirectView editPet(@ModelAttribute Pet pet, RedirectAttributes attributes) {
        System.out.println(pet);
        pet.setHiddenField("XXX");

        attributes.addFlashAttribute("pet", pet);
        return new RedirectView("/internal");
    }

}

Vamos fazer um pedido POST para o URI /owners/123/pets/456/edite ver os resultados:

A new Pet instance was created!
Pet[456,123,null]
Pet[456,123,XXX]

A new Pet instance was created!

Primavera criou um ModelAndViewContainere não encontrou nada para preencher a instância com (é um pedido de um cliente; não havia nenhum redirecionamentos). Desde que o modelo está vazio, Primavera teve que criar um novo Petobjeto, chamando o construtor padrão que imprimiu a linha.

Pet[456,123,null]

Uma vez presentes no modelo, os campos do argumento deve ser preenchida a partir de todos os parâmetros de solicitação que têm nomes correspondentes.

Nós imprimimos o dado Petpara se certificar de todos os campos petIde ownerIdtinha sido obrigado corretamente.

Pet[456,123,XXX]

Nós estabelecemos hiddenFieldpara verificar a nossa teoria e redirecionado para o método invokeInternalque também espera um @ModelAttribute. Como podemos ver, o segundo método recebeu o exemplo (com o próprio valor oculto), que foi criado para o primeiro método.

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=175844&siteId=1
Recomendado
Clasificación