Spring In Action< Five >

Keywords: Spring Java xml Front-end

5. Building Spring Web Applications

Spring MVC is based on the Model-View-Controller mode to build flexible and loosely coupled Web applications for us. The following figure shows all the sites that have experienced using Spring MVC:


Next, let's analyze the Spring MVC process so that we can learn Spring MVC better. "1" means that the request contains all the information about the content of the request, at least the URL of the request. The first stop for requests is Dispatcher Servlet, and all requests for Spring MVC are made through a front-end controller. Dispatcher Servlet is the front-end controller of Spring MVC. As a single instance servlet, Dispatcher Servlet delegates other components to complete the actual task. The task of the Dispatcher Servlet is to send requests to Spring MVC Controller, Spring MVC Controller is the component that processes requests. Dispatch Servlet queries one or more processor maps to determine where the next station is (this is the "2" process), and the processor maps make decisions based on the URL information carried by the request. Once the appropriate controller is selected, the Dispatch Servlet sends the request to the selected controller (this is "3"), which generally handles the business logic to several java objects. Controller processing returns some information based on the processing results, which is called model. Spring MVC controller packages model data and shows the view name for rendering output. Spring MVC controller sends the model and view name to Dispatcher Servlet together (this is "4"). Dispatcher Servlet uses a view parser to match a specific view implementation (this is "5"). Finally, the implementation of the view (this is "6").

The only way to configure Dispatcher Servlets in web.xml is to configure Dispatcher Servlets. With the enhancement of servlets 3 and Spring 3.1, the following way to configure Dispatcher Servlets in web.xml is not the only way.

       

<! - ContextLoaderListener automatically assembles the configuration information of Application Context when launching the web container - >
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <! - Front-end Controller - >
  <servlet>
      <servlet-name>first</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>/WEB-INF/spring-mvc.xml</param-value>
      </init-param>
      <! - The smaller the value, the higher the priority of application startup is, the less startup it is - >
      <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>first</servlet-name>
      <! - indicates which requests are handed over to the servlet, / indicates the defau lt servlet mapping - >
      <url-pattern>/</url-pattern>
  </servlet-mapping>

1. Using Java to configure Dispatcher Servlet instead of configuring in web.xml

Using Java to configure Dispatch Servlets into servlet containers instead of using web.xml. In servlet 3.0, the container finds the class that implements the javax. servlet. Servlet Container Initializer interface in the classpath, and if found, it will configure the Servlet container. Abstract Annotation Config Dispatcher Servlet Initializer:

package spring.in.action.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[]{RootConfig.class};
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[]{WebConfig.class};
	}

	@Override
	protected String[] getServletMappings() {
		return new String[]{"/"};
	}
}

Spittr Web App Initializer rewrites three methods of AbstractAnnotation Config Dispatcher Servlet Initializer, getServlet Mappings () which maps one or more paths to Dispatcher Servlet. The code above says "/" so it is the default servlet for the application. To understand the other two approaches, we need to look at Dispatcher Servlet and ContextLoaderListener, which are two application contexts.

Dispatcher Servlet creates Spring application context when loading. In getServletConfiClasses(), we require Dispatcher Servlet to configure beans in the WebConfig class when loading application context. In Spring applications, there is actually an application context created by ContextLoaderListener. We want Dispatcher Servlet to create beans of web components such as controllers, processor maps, view parsers, etc., and ContextLoaderListener to load other beans such as mid-tier and data-tier components of the back-end. AbstractAnnotation Config Dispatcher Servlet Initializer creates both Dispatcher Servlet and ContextLoader Listener. The getServletConfigClass() method returns a class with the @Configuration annotation to define the bean in the Dispatcher Servlet application context, and the getRootConfigClass() method returns a class with the @Configuration annotation to define the bean in the ContextLoaderListener application context.

The WebConfig classes are as follows: @Configuration and @Enable WebMvc


package spring.in.action.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.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan("spring.in.action.controller")
public class WebConfig extends WebMvcConfigurerAdapter{
     @Bean
     public ViewResolver viewResolver(){
    	 InternalResourceViewResolver   resolver = new InternalResourceViewResolver();
    	 resolver.setPrefix("/WEB-INF/views");
    	 resolver.setSuffix(".jsp");
    	 resolver.setExposeContextBeansAsAttributes(true);
    	 return resolver;
     }

     @Override
     public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
	configurer.enable();
     }
}

If there is no view resolver configured in WebConfig, Spring defaults to BeanNameViewResolver, which looks for beans whose ID matches the view name, and the beans it finds implement the View interface. In the configuration, we set up the scan package, and the controller we write will be annotated with @Controller, so there is no need to explicitly configure the controller. Internal ResourceViewResolver finds the jsp file, and then adds a specific prefix and suffix to the view name. We rewrote the configureDefaultServletHandling method to require Dispatcher Servlet to forward requests for static resources to the default servlet of the Servlet container by calling the enable() method of DefaultServletHandler Configurer instead of using Dispatcher Servlet to process such requests. RootConfig configuration is very simple, the code is as follows:


package spring.in.action.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan(basePackages={"spring.in.action"},excludeFilters={@Filter(type=FilterType.ANNOTATION,value=EnableWebMvc.class)})
public class RootConfig {

}


2. Write basic controllers

In Spring MVC, the controller just adds the class of @RequestMapping annotation to the method, and the @Controller annotation to the controller class. The @Controller annotation is used to declare the controller. Its purpose is to assist in component scanning. Because the HomeController has @Controller, the component scanner will find the HomeController and make its life a Spring application context. A bean. The code is as follows:


package spring.in.action.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HomeController {
     
	@RequestMapping(value="/",method=RequestMethod.GET)
	public String home(){
		return "home";
	}
}

We see that HomeController's home method does not do much, and it returns a String type of data. This String will be interpreted by Spring MVC as the name of the view to be rendered. Dispatcher Servlet asks the view parser to parse this logical name into a real view.

In the previous example, we defined method-level requests. Next, we define class-level request processing.


package spring.in.action.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value="/")
public class HomeController {
     
	@RequestMapping(method=RequestMethod.GET)
	public String home(){
		return "home";
	}
}


Mapping the controller to /, and @RequestMapping on the processor method complements the @RequestMapping declaration at the class level. value can also be an array of String type, as follows:

package spring.in.action.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value={"/","homepage"})
public class HomeController {
     
	@RequestMapping(method=RequestMethod.GET)
	public String home(){
		return "home";
	}
}

Now home can map to GET requests for "/" and "/ homepage".


package spring.in.action.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import spring.in.action.entity.Student;

@Controller
@RequestMapping(value={"/","homepage"})
public class HomeController {
    private Student student;
    @Autowired
    public HomeController(Student student){
    	this.student = student;
    }
    
	@RequestMapping(method=RequestMethod.GET)
	public String home(Model model){
		model.addAttribute("student", student);
		System.out.println(student==null);
		return "home";
	}
}

We can see that there is an additional parameter Model in the home method, so that the home method can fill the student data into the model. The model is actually a Map, which is passed to the view, so that the data can be rendered into the view. If we return student directly, spring infers the view name based on the request path, because the method is for the request path of "/ homepage", so the view name is the deleted homepage, in this case homepage.jsp.

3. Input to receive requests

Spring supports a variety of ways to transfer client data to processor processing methods: 1) query parameters, 2) form parameters, 3) path variables.

1) Query parameter @RequestMapping(value = "/student", method=RequestMethod.GET)

public String homeRequest(Model model,
	@RequestParam(value="studentId",required=true,defaultValue="09005810") Long studentId){
	model.addAttribute("student", student);
	System.out.println(student==null);
	return "home";
	}

Use @RequestParam to get the client parameter with the same name, defaultValue to set the default value, and required to true to indicate that the parameter is required.

2) Form parameters

@RequestMapping(value = "/studentmethod", method=RequestMethod.GET)
public String homePathValue(Model model,Student student){
	model.addAttribute("student", student);
	return "redirect:/student/"+student.getStudent_name();
}

Spring fills in the student variable of the above method with the same parameter as the student attribute name, and returns redirect: in the parameter, telling spring that this is a redirect, not a view name.

3) Path variables

If we want to query the student information according to the student number passed from the client, the processing method may deal with such url:/homepage?student_id=123, but it is better than the request "/homepage/123". The code is as follows:

@RequestMapping(value = "/{studentId}", method=RequestMethod.GET)
public String homePathValue(Model model,@PathVariable("studentId") Long student_id){
	model.addAttribute("student", student);
	System.out.println(student==null);
	return "home";
}

We see that the value value in the @RequestMapping annotation is equal to /{studentId} which is a placeholder, indicating that requests that meet the /* requirement can be satisfied. Whatever the placeholder value is, it will be the attribute value of @PathVariable, because the parameter name of the method is the same as the placeholder name, so we can abbreviate it as @PathVariable Long student_id.


4. Checklist

Spring provides support for the java validation API and does not require additional configuration, as long as the implementation of the java API is guaranteed to be included in the classpath. Following are the validation annotations provided by Spring, which are set on the properties of the model data:

The @AssertFalse annotation element must be false

AssertTrue annotation must be true

The @DecimalMax annotation must be numeric and less than or equal to the given BigDecimalString value

DecimalMin must be a number and greater than or equal to the given BigDecimalString value

Digits must be a number and must have a specified number of digits

Future must be a future date

Max less than or equal to the given value

Min greater than or equal to a given value

NotNull cannot be null

Null must be null

Past must be a bygone day

Pattern s must match a given regular expression

Size must be a collection, string, array, and within a given length range

Importing jar packages in Maven

<dependency>
     <groupId>javax.validation</groupId>
     <artifactId>validation-api</artifactId>
     <version>1.0.0.GA</version>
</dependency>

package spring.in.action.entity;

import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.springframework.stereotype.Component;

@Component("student")
public class Student {
    @NotNull
    @Size(min=2,max=30)
    private String  student_name;
    
    @NotNull
    private String  student_address;
    
    @Digits(fraction = 0, integer = 0)
    private Integer stduent_age;
    
    public String getStudent_name() {
        return student_name;
    }
    public void setStudent_name(String student_name) {
        this.student_name = student_name;
    }
    public String getStudent_address() {
        return student_address;
    }
    public void setStudent_address(String student_address) {
        this.student_address = student_address;
    }
    public Integer getStduent_age() {
        return stduent_age;
    }
    public void setStduent_age(Integer stduent_age) {
        this.stduent_age = stduent_age;
    }
    
}

        @RequestMapping(value = "/studentmethod", method=RequestMethod.GET)
	public String homePathValue(Model model,@Valid Student student,Errors error){
		model.addAttribute("student", student);
		if(error.hasErrors()){
			return "error";
		}
		return "redirect:/student/"+student.getStudent_name();
	}

The @Valid annotation tells Spring that it needs to validate this object, and then determines whether the validation is successful by using the hasErrors method of the Errors object.


Posted by benson on Wed, 02 Jan 2019 12:24:08 -0800