[Spring learning 4] MVC

Brief introduction

Previous page program service code is embedded into the JSP page, higher coupling.

Later, after the separation of the front and rear ends of the code, using the MVC architecture, M: a view showing, in charge of view, C:: Model, the data model is responsible for the control, V controller, responsible for the data model is rendered onto the respective views.

Request Process

                            ┌─────────┐
                           ↗│ 处理器映射│
                         2/ └─────────┘
                         /         3
请求 1 ┌─────────────────┐ --------------------> ┌─────┐
----->│DispatcherServlet│ <--┌─────────────┐  4 │控制器│
      └─────────────────┘    │模型及逻辑视图名│ ---│     │
                      \  \   └─────────────┘    └─────┘
                       \  \5   ┌────────┐
                       6\  --->│视图解析器│
                         ↘     └────────┘
            响应 7      ┌────┐
<----------------------│视图 │
                       └────┘

process:

  • Request: When asked to leave the browser, the user can with the information requested by the content, at least contain the URL request. (And possibly also with information such as forms)
  • DispatcherServlet: Spring MVC sends the request to the controller (Controller)
  • DispatcherServlet: Unlike most Java-based Web frameworks, all requests will be via a Spring MVC front controller (front controller) Servlet. In this embodiment of a single Servlet delegates the request to other components of the application to perform the actual process. In Spring MVC in, DispatcherServlet is the front controller.
  • DispatcherServletThe task is to send the request to the controller Spring MVC ( controller). (Spring controller is a component for processing the request.)
  • DispatcherServletYou need to know which sends the request to the controller. So DispatcherServletwith one or more queries 处理器映射(handler mappingwhere) to determine the next stop on request. The mapping processor to make decisions based on the URL information request carried.
  • To the controller, the load request will remove (User Submission) and wait controller processes the information. (In fact, well-designed controller itself only deals with little or no processing, but the business logic entrusted to one or more service objects are processed)
  • After completion logic controller, typically have some information that needs to be returned to the user and displayed on the browser. This information is referred to as model model( ).
  • This information is usually need to be formatted in a user-friendly manner, it will generally be HTML. Therefore, the information needs to be sent to a view ( view), usually a JSP.
  • The controller did last thing is to model data package and identify the name of the view for rendering output. Then it will request along 模型and 视图名sent back DispatcherServlet.
  • Passed to DispatcherServletthe view name does not directly indicate a specific JSP. In fact it can not even determine the view is JSP. Instead, it just passed a 逻辑名称, this name will be used to find the real view to produce results.
  • DispatcherServletIt will be used 视图解析器(view resolver)to match the logical view name for a specific view implementations, it may or may not JSP.
  • Using a model view will render output data, the output will be passed to the client in response to the object.

Configuration DispatcherServlet

DispatcherServletYou can configure the web.xmlfile.

AbstractAnnotationConfigDispatcherServletInitializer

In the specification and Spring 3.1 Servlet 3, the java can be DispatcherServletarranged in Servlet容器the required inheritance AbstractAnnotationConfigDispatcherServletInitializer, override three methods.

package com.yww.config;

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

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{ RootConifg.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {    // 指定配置类
        return new Class[]{ WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {   // 将DispatcherServlet映射到"/"
        return new String[]{ "/" };
    }
}
  • getServletMappings(): Will be mapped to one or more paths DispatcherServleton. In this example, it maps is " /", which means it will be the default Servlet application. It handles all requests into the application.
  • To understand the other two methods, we must first understand DispatcherServletand Servlet监听器(ContextLoaderListener)relationships. (as follows)
    AbstractAnnotationConfigDispatcherServletInitializer
              |                            |
             创建                          创建
              |                            |
              v                            v
      DispatcherServlet               ContextLoaderListener
              |                            |
             加载                          加载
              |                            |
              v                            V
          应用上下文                     应用上下文
(查找@Configuration注解的类,      (查找@Configuration注解的类,
  加载包含Web组件的bean。             加载应用中的其它bean。
  如控制器,视图解析器,处理器映射等)     如自定义的业务所需的bean)

AbstractAnnotationConfigDispatcherServletInitializerAnalysis :

  • The container looks implemented in the class path in Servlet 3.0 environment javax.servlet.ServletContainerInitializerclass interface, if they can find, they would use it to configure the Servlet container.
  • Spring provides an implementation of this interface, called SpringServletContainerInitializer, in turn, will find this class to achieve WebApplicationInitializerclass and give them tasks to complete the configuration.
  • Spring 3.2 introduces a convenient WebApplicationInitializerbase to achieve, that is AbstractAnnotationConfigDispatcherServletInitializer.
  • When our custom class inherits AbstractAnnotationConfigDispatcherServletInitializerwhen deployed to Servlet 3.0容器time in the container it will automatically find it, and to configure Servlet上下文.
                        容器(Servlet 3.0)
                                |类路径查找
                                v
            实现javax.servlet.ServletContainerInitializer接口的类
                                |
                                v
              SpringServletContainerInitializer(Spring提供)
                                |查找
                                v
        实现`WebApplicationInitializer`的类,将配置的任务交给它们完成
                                |
                AbstractDispatcherServletInitializer
                  AbstractContextLoaderInitializer
                                |
                                v
    AbstractAnnotationConfigDispatcherServletInitializer(Spring提供)
                                |
                                v
                  自定义类继承,即可配置Servlet上下文

Servlet configuration class

Role: Enable Web MVC, enable the component scanning, configuration view resolver configuration process static resources.

WebConfig.javaIn the above getServletConfigClasses()setting process.

The simplest configuration :

package com.yww.config;

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

@Configuration
@EnableWebMvc
public class WebConfig {
}

Empty configuration WebConfigalthough can enable Spring MVC, but there are many problems:

  • No configuration view resolver. Spring will default BeanNameVire-Resolver, this view resolver will find the view ID matches the name of the bean, bean and look to achieve View interface, which parses the view in such a way.
  • Not enabled component scans. Spring can only be found explicitly declared in the configuration controller class.
  • DispatcherServletIt will be mapped to the default Servlet application, so it will process all requests, including requests for static resources.

But the smallest available Spring MVC configuration :

package com.yww.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.WebMvcConfigurationSupport;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc       // 启用Spring MVC
@ComponentScan      // 启用组件扫描
public class WebConfig extends WebMvcConfigurationSupport {

    // 配置JSP视图解析器
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/jsp/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    // 配置静态资源的处理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
        configurer.enable();
    }
}

@ComponentScanYou will find with @Controllerclass notes, so we do not need to explicitly declare the class in the configuration controller.

ViewResolverLooks for JSP files as prefix and suffix set.

configureDefaultServletHandling()The method by calling DefaultServletHandlerConfigurerthe enable()method requires DispatcherServletwill forward the request to the static resources Servlet容器on the default Servlet, rather than DispatcherServlettheir own to deal with such requests.

Root configuration class

Role: Load custom business component.

package com.yww.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 = {"com.yww"},
        excludeFilters = {@Filter(type= FilterType.ANNOTATION, value = EnableWebMvc.class)}
)
public class RootConfig {
}

Controller

Controller Notes :

@ControllerIs based on the @Componentnotes, the effect is the same. But in the MVC @Componentin the ideographic it could be worse.

Mapping annotations :

@RequestMappingIt specifies the path to process the request.

It can be placed on the type, or method. Setting map on the path to the group, which in this embodiment further requires specifying the requested annotation.

Or a method of mapping the same class can have multiple paths.

Return value - View name :

The returned string will be interpreted as Spring MVC view name to render. DispatcherServletView resolvers will be asked to resolve the logical name for the actual view.

InternalResourceViewResolverRecognizes returned with a prefix character redirect:or forward:, respectively, they are redirected to go.

Model parameters :

Data transfer parameters of the model are three kinds: Model, ModelMap, ModelAndView.

Their relationship is as follows.

public class ExtendedModelMap extends ModelMap implements Model{}

ModelAndViewCompared to other purposes, you can set the rendering of the view name.

Model calls addAttribute()method does not specify when the key, key will be determined according to the type inference object.

It may be Mapthe type to model.

Or even can return a list, or when the processor returns a collection of objects, this value will be placed in the model, key will come to the model according to its type inference. And the noun logical view will be inferred according to the request path.

When the view is a JSP, the model data will be placed in the request as a request attribute.

model

Check the properties can be achieved annotate the model. Also pass parameters in the controller before adding @Validannotations, and the 紧接着additional parameters Errorsacquired abnormalities.

Java校验注解:@AssertFalse, @AssertTrue, @DecimalMax, @DecimalMin, @Digits, @Future, @Max, @Min, @NotNull, @Null, @Past, @Pattern, @Size。

Examples

  • Basic MVC program
  • Accept the request input
    • Path parameters
    • Form parameters

Basic MVC program

xml configuration DispatcherServlet

Project structure

.
├── build.gradle
└── src
    └── main
        ├── java
        │   └── com
        │       └── yww
        │           ├── HomeController.java
        │           └── Message.java
        ├── resources
        │   └── application.properties
        └── webapp
            ├── index.jsp
            └── WEB-INF
                ├── applicationContext.xml
                ├── dispatcher-servlet.xml
                ├── jsp
                │   └── home.jsp
                └── web.xml

Code

build.gradle

plugins {
    id 'java'
    id 'war'
}

group = 'com.yww'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
targetCompatibility = 1.8

ext{
    springVersion = '5.2.0.RELEASE'
}

repositories {
    mavenCentral()
}

dependencies {
    compile "org.springframework:spring-core:$springVersion"
    compile "org.springframework:spring-context:$springVersion"
    compile "org.springframework:spring-beans:$springVersion"
    compile "org.springframework:spring-expression:$springVersion"
    compile "org.springframework:spring-aop:$springVersion"
    compile "org.springframework:spring-aspects:$springVersion"
    compile "org.springframework:spring-web:$springVersion"
    compile "org.springframework:spring-webmvc:$springVersion"

    testCompile "junit:junit:4.12"
}

web.xml: Configuring DispatcherServletand map the path, ContextLoaderListener(load any bean named xml file), bean xml configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
<!--        <url-pattern>*.form</url-pattern>-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

dispatcher-servlet.xml: Xxx-servlet.xml designated format file is automatically loaded spring mvc, configured path view resolved.

<?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"
       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">

    <context:component-scan base-package="com.yww"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

applicationContext.xml: Configure the ContextLoaderListenerpost, you can load xml file naming any of the bean without xxx-servlet.xml format.

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

    <bean id="msg1" class="com.yww.Message">
        <property name="msg" value="mvc - xml config"/>
    </bean>

</beans>

HomeController.java

package com.yww;

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 org.springframework.beans.factory.annotation.Autowired;

@Controller
@RequestMapping("/home")
public class HomeController {

    @Autowired
    public Message msg1;

    @RequestMapping(method = RequestMethod.GET)
    public String printHome(Model model){
        String str1 = msg1.getMsg();
        model.addAttribute("msg", "this is a page! gradle " + str1);

        return "home";
    }
}

Message.java

package com.yww;

public class Message {
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = "this mssage is : " + msg;
    }

}

index.jsp

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

home.jsp

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>${msg}<h1>
</body>
</html>

start up

  • Project Structe -> Artifacts -> + -> WebApplication:Exploded -> From Modules... -> OK
  • Project Structe -> Artifacts -> + -> WebApplication:Archive -> For 'xxx:war exploded' -> OK
  • Edit Configurations... -> + -> Tomcat Server -> local -> Deployment -> + Artifact... -> OK
  • run(shift + F10)

java configuration DispatcherServlet

Project structure

.
├── build.gradle
└── src
    └── main
        ├── java
        │   └── com
        │       └── yww
        │           ├── config
        │           │   ├── MyWebAppInitializer.java
        │           │   ├── RootConfig.java
        │           │   └── WebConfig.java
        │           ├── HomeController.java
        │           └── Message.java
        ├── resources
        │   └── application.properties
        └── webapp
            ├── index.jsp
            └── WEB-INF
                ├── jsp
                │   └── home.jsp
                └── web.xml

Code

build.gradle: Unlike the previous, java configuration DispatcherServlet, you need to add servlet-apithe library.

plugins {
    id 'java'
    id 'war'
}

group = 'com.yww'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
targetCompatibility = 1.8

ext{
    springVersion = '5.2.0.RELEASE'
}

repositories {
    mavenCentral()
}

dependencies {
    compile "org.springframework:spring-core:$springVersion"
    compile "org.springframework:spring-context:$springVersion"
    compile "org.springframework:spring-beans:$springVersion"
    compile "org.springframework:spring-expression:$springVersion"
    compile "org.springframework:spring-aop:$springVersion"
    compile "org.springframework:spring-aspects:$springVersion"
    compile "org.springframework:spring-web:$springVersion"
    compile "org.springframework:spring-webmvc:$springVersion"

    testCompile "junit:junit:4.12"
    providedCompile 'javax.servlet:javax.servlet-api:4.0.1'
}

web.xml: Nothing to configure, fully configured using java.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

</web-app>

MyWebAppInitializer.java

package com.yww.config;

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

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

    @Override
    protected Class<?>[] getServletConfigClasses() {    // 指定配置类
        return new Class[]{ WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {   // 将DispatcherServlet映射到"/"
        return new String[]{ "/" };
    }
}

WebConfig.java

package com.yww.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.WebMvcConfigurationSupport;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc       // 启用Spring MVC
//@ComponentScan("com.yww")
@ComponentScan      // 启用组件扫描,只会扫描当前包下的配置
public class WebConfig extends WebMvcConfigurationSupport {

    // 配置JSP视图解析器
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/jsp/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    // 配置静态资源的处理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
        configurer.enable();
    }
}

RootConfig.java

package com.yww.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 = {"com.yww"},
        excludeFilters = {@Filter(type= FilterType.ANNOTATION, value = EnableWebMvc.class)}
)
public class RootConfig {
}

HomeController.java(Ibid)

Message.java(Ibid)

index.jsp(Ibid)

home.jsp(Ibid)

Accept the request input

Spring MVC in various ways to allow the client to transfer data to the processor controller method:

  • Query parameters (Query Parameter)
  • Form parameters (Form Parameter)
  • Path variables (Path Variable)

Project structure

.
├── build.gradle
└── src
    └── main
        ├── java
        │   └── com
        │       └── yww
        │           ├── dao
        │           │   └── User.java
        │           ├── FormParamController.java
        │           ├── PathParamController.java
        │           └── QueryParamController.java
        ├── resources
        │   └── application.properties
        └── webapp
            ├── index.jsp
            └── WEB-INF
                ├── applicationContext.xml
                ├── dispatcher-servlet.xml
                ├── jsp
                │   ├── form.jsp
                │   └── home.jsp
                └── web.xml

Code

User.java

package com.yww.dao;

public class User {
    private int id;
    private String name;
    private String passwd;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
}

QueryParamController.java

package com.yww;

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 org.springframework.web.bind.annotation.RequestParam;

@Controller
public class QueryParamController {

    @RequestMapping(value = "/query_param", method = RequestMethod.GET)
    public String printHome(
            Model model,
            @RequestParam int id,
            @RequestParam(value = "name", defaultValue = "yww") String username,
            @RequestParam(value = "count", defaultValue = "10") long count  // 尽管defaultValue属性给定的时String类型的值,但当绑定到方法的count参数时,会自动转换为long类型。
    ){
        String str1 = " query - id:" + id + " username:" + username + " count:" + count;
        model.addAttribute("msg", "this is a page! " + str1);

        return "home";
    }
}

PathParamController.java

package com.yww;

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

@Controller
public class PathParamController {

    @RequestMapping(value = "/path_param/{id}", method = RequestMethod.GET)
    public String printHome(
            Model model,
            @PathVariable("id") int id
    ){
        String str1 = " path - id:" + id;
        model.addAttribute("msg", "this is a page! " + str1);

        return "home";
    }
}

FormParamController.java

package com.yww;

import com.yww.dao.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.*;

@Controller
public class FormParamController {

    @RequestMapping(value = "/form_param", method = GET)
    public String showForm(){
        return "form";
    }

    @RequestMapping(value = "/form_param", method = POST)
    public String postForm(
            Model model,
            User user
    ){
        model.addAttribute("msg", "this is a page! form : " + user.getName());
        return "home";
    }
}

form.jsp

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post">
    id : <input type="text" name="id" /> </br>
    name : <input type="text" name="name" /> </br>
    password : <input type="text" name="passwd" /> </br>

    <input type="submit" value="login" />
</form>
</body>
</html>

start up

Query parameters (Query Parameter): http: // localhost: 8080 / mvc_param / query_param id = 1001 & name = megumin & count = 7?

Path variables (Path Variable): http: // localhost: 8080 / mvc_param / path_param / 1001

Form parameters (Form Parameter): http: // localhost: 8080 / mvc_param / form_param

PS

Note: xml configuration file

Xxx-servlet.xml designated file format are automatically loaded spring mvc (eg: dispatcher-servlet.xml).

The configuration ContextLoaderListener, the load xml document on the bean arbitrarily named without xxx-servlet.xml format (eg: applicationContext.xml).

错误:class file for javax.servlet.ServletException not found

java configuration DispatcherServlet, you need to build.gradleadd the library:

`providedCompile 'javax.servlet:javax.servlet-api:4.0.1'`

Note: The form submission path

<form>Tag action attribute is not set, then, when the form is submitted, it will be submitted to the same url path and presentation.

Guess you like

Origin www.cnblogs.com/maplesnow/p/11795448.html