Spring MVC Concepts: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 76: Line 76:
</syntaxhighlight>
</syntaxhighlight>


The API allows to associate a path with a logical view name, without the need to write a controller class.
The API allows to associate a path with a [[#View_Logical_Name|view logical name]], without the need to write a controller class.


=View=
=View=

Revision as of 06:25, 12 October 2018

Internal

To Process

TO PROCESS:

Model

The model is an object that ferries data between a controller and whatever view is charged with rendering that data. org.springframework.ui.Model: a holder for model attributes, conceptually a map. Ultimately, data that is placed in the model's attributes will be copied into the servlet response attributes, where the view can find them.

Controller

A controller is a class that handles requests, fetches and processes data, and then responds with information of some sort. The controller's method handing the requests are named handler methods. Controller classes must be annotated with @Controller.

In case of a browser-facing application, a controller responds by optionally populating model data and passing the request to a view that produces HTML to be returned to the browser. The view that is supposed to render the response is indicated by its logical name, which is returned by the handler method.

@Controller
public class HomeController {

    @GetMapping("/")
    public String home() {

        // returns the view name
        return "home";
    }
}

In case of a REST application, the controller writes data directly into the body of the response.

A conventional pattern to designate the responsibilities of the handler methods and to associate them with paths and request types is to use @RequestMapping at class level to configure the base path, and then use @GetMapping, @PostMapping, @PutMapping, @DeleteMapping and @PatchMapping to designate HTTP method-specific handlers:

@Controller
@RequestMapping("/something")
public class SomeController {

    @GetMapping
    public String read() {
        ...
    }

    @PostMapping
    public String create() {
        ...
    }

    @PutMapping
    public String update() {
        ...
    }
}

View Controller

A view controller is a controller that is simply enough that it does not populate a model or process input, but simply forward the request to a view. View controller do not require a class on their own, as there is no functionality to populate that class with. Instead, they can be defined by using a specific API in a configuration class.

@Configuration
public class MyWebConfiguration implements WebMvcConfigurer {
  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("home");
  }
}

The API allows to associate a path with a view logical name, without the need to write a controller class.

View

The view renders data into HTML format.

The view is instantiated dynamically, and its implementation depends on the template engine that is available in the classpath. Template libraries are designed to be decoupled by any particular web framework, so they are unaware of Spring's model abstraction and are not able to work with the data the controller places in the model. They can work with servlet request attributes, though, and Spring copies the model data into the request attributes before the request is handed over to the view.

View Logical Name

The template name is derived from the logical name by prefixing it with /templates and postfixing it with .html. Simply placing a <logical-view-name>.html under src/resources/templates makes the template-based view available.

Redirect View

"redirect:/home"

Project Directory Layout

src/main/resource/static
src/main/resource/static/images
src/main/resource/templates

Testing MVC Applications

import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.hamcrest.Matchers.containsString;

@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testHomePage() throws Exception {

        mockMvc.perform(get("/")).
                andExpect(status().isOk()).
                andExpect(view().name("home")).
                andExpect(content().string(containsString("Welcome to ...")));
    }
}

Spring MVC testing implies using @WebMvcTest. MockMvc mocks the mechanics of Spring MVC, instead of starting a full blown web server.

REST Clients

RestTemplate

TO PROCESS: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#webmvc-resttemplate

POSTing Resource. Data

This overloaded version allows you to receive the newly created resource as a domain model object:

RestTemplate restTemplate = new RestTemplate();

MyResource model = new MyResource(...);

MyResource created = restTemplate.postForObject("http://localhost:8080/myresource", model, MyResource.class);