# Spring MVC



## Introduction

* Modal: Any java class that containing data
* View: JSP which is used to display the modal&#x20;
* Controller: A Java class marked with controller annotation which will be used to receive the data, return the modal with result data to the view

## Configuration (by xml)

1. web.xml

* To tell where the config file is
* Setup the dispatcherServlet so as to send the user request to corresponding controller to handle the request and return the correct view
* The output file(war) will be generated based web.xml so as to do deployment

```markup
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">

	<display-name>spring-mvc-demo</display-name>

	<absolute-ordering />

	<!-- Spring MVC Configs -->

	<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- Spring creates a WebApplicationContext object 
			based on the bean definitions 
		and stores it in the ServletContext of one's web application. -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc-demo-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
</web-app>
```

2\. spring-mvc-demo-servlet.xml

* To perform component scanning
* Allow the support of validation
* Define the pattern of getting the view

```markup
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://www.springframework.org/schema/context
    	http://www.springframework.org/schema/context/spring-context.xsd
    	http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan base-package="com.luv2code.springdemo" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven/>

	<mvc:resources mapping="/resources/**" location="/resources/"></mvc:resources>


	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/view/" />
		<property name="suffix" value=".jsp" />
	</bean>

</beans>
```

## Configuration (By Annotation)

{% code title="DemoAppConfig.java" %}
```java
package com.luv2code.springdemo.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="com.luv2code.springdemo")
public class DemoAppConfig {
 
	// define a bean for ViewResolver
	@Bean
	public ViewResolver viewResolver() {
		
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		
		viewResolver.setPrefix("/WEB-INF/view/");
		viewResolver.setSuffix(".jsp");
		
		return viewResolver;
	}
}
```
{% endcode %}

{% code title="MySpringMvcDispatcherServletInitializer.java" %}
```java
package com.luv2code.springdemo.config;
 
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 
public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 
	@Override
	protected Class<?>[] getRootConfigClasses() {
		// TODO Auto-generated method stub
		return null;
	}
 
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class[] { DemoAppConfig.class };
	}
 
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
}
```
{% endcode %}

## Binding with modal

* Basically,  just put the java object into model

```java
    @RequestMapping(value = "/helloform")
    public String formPage(Model model){
        Map<String, String> countryList = new HashMap<>();
        countryList.put("China","CN");
        countryList.put("USA", "US");

        Map<String, String> foodList = new HashMap<>();
        foodList.put("FishBall","Fish Ball");
        foodList.put("ChickenWing", "Chicken Wing");

        model.addAttribute("student", new Student("Peter","Cheng", ""));
        model.addAttribute("countryOption", countryList);
        model.addAttribute("foodOption", foodList);

        return "helloForm";
    }
```

## Validation

* To validate whether the user input is matched to the ideal pattern or not
* If not , return to the same page with error message

## Modal

```java
public class Customer {

    @Pattern(regexp = "^/w{5}$", message = "Wrong Pattern")
    private String firstName;

    @NotNull
    @Size(min=1, message = "is required")
    private String lastName;

    @Min(value = 18, message = "must be greater than or equal to 18")
    @Max(value = 30, message = "must be smaller than or equal to 30")
    private Integer age;

    public Customer() {
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

}

```

## Controller

```java
@Controller
@RequestMapping("/customer")
public class CustomerController {

    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {

        // To filter out the space if the user input contains space
        StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);

        dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
    }


    @RequestMapping("/processForm")
    public String processForm(
            @Valid @ModelAttribute("customer") Customer theCustomer,
            BindingResult theBindingResult) {

        // Check whether all of the user input fulfill the pattern or not
        if (theBindingResult.hasErrors()) {
            return "customer-form";
        }
        else {
            return "customer-confirmation";
        }
    }
}
```

## View

```markup
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>

<head>
	<title>Customer Registration Form</title>
	
	<style>
		.error {color:red}
	</style>
</head>
<body>

<i>Fill out the form. Asterisk (*) means required.</i>
<br><br>

	<form:form action="processForm" modelAttribute="customer">
	
		First name: <form:input path="firstName" />
		
		<br><br>
		
		Last name (*): <form:input path="lastName" />
		<form:errors path="lastName" cssClass="error" />
		
		<br><br>

		Age: <form:input path="age" />
		<form:errors path="age" cssClass="error" />

		<br><br>

        CourseCode: <form:input path="courseCode" />
        <form:errors path="courseCode" cssClass="error" />

        <br><br>

		<input type="submit" value="Submit" />
				
	</form:form>

</body>

</html>
```
