SpringAction学习三、Spring MVC:完整的SpringMVC请求

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MASORL/article/details/82694741

目录

SpringMVC流程图

完整 的目录结构

示例代码

补充一:通过MockMvc来测试Spring MVC控制器,省去重复启动服务器的麻烦

补充二:处理多个请求

补充三:接受路径参数的传入

补充四:处理表单


SpringMVC流程图

  1. 请求会携带用户所请求内容的信息(至少会包含请求的URL。可能带有其他的信息,例如用户提交的表单信息)到前端控制器(front controllerServlet,在Spring MVC中就是DispatcherServlet
  2. DispatcherServlet会查询一个或多个处理器映射(handler mapping)。处理器映射会根据请求所携带的URL信息来进行决策,决定使用哪个控制器。
  3. 选择了合适的控制器,DispatcherServlet会将请求发送给选中的控制器。
  4. 控制器在完成逻辑处理后,是将模型数据打包,并且标示出用于渲染输出的视图名。接下来会将请求连同模型(model)视图(view)名发送回 DispatcherServlet 。
  5. DispatcherServlet会使用视图解析器(view resolver) 来将逻辑视图名匹配为一个特定的视图实现。
  6. 视图的实现。
  7. 视图将使用模型数据渲染输出,这个输出会通过响应对象传递给客户端。

完整 的目录结构

示例代码

pom.xml,配置项目的支持

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>Masorl</groupId>
    <artifactId>SpringValid</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <springframework.version>4.0.6.RELEASE</springframework.version>
        <hibernate.validator.version>5.1.2.Final</hibernate.validator.version>
        <javax.validation.version>1.1.0.Final</javax.validation.version>
    </properties>

    <dependencies>
        <!-- Spring dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <!-- jsr303 validation dependencies-->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>${javax.validation.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate.validator.version}</version>
        </dependency>

        <!-- Servlet dependencies -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!--MockMVC dependencies-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.0.6.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.2</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.4</version>
                    <configuration>
                        <warSourceDirectory>src/main/webapp</warSourceDirectory>
                        <warName>Spring4MVCFormValidationExample</warName>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
        <finalName>Spring4MVCFormValidationExample</finalName>
    </build>

</project>

DispatcherServlet创建

通过继承AbstractAnnotationConfigDispatcherServletInitializer类,在Servlet3.0环境中,容器会在类路径查找到继承该类的类,并用它来配置servlet容器。【扩展该类,会自动配置DispatcherServlet和Spring应用上下文,Spring应用上下文会位于应用程序的Servlet上下文之中】

重写getServletConfigClasses: 指定配置文件

重写getServletMappings:将dispatcherservlet映射到"/",也就是说所有的请求都会由dispatcherservlet来处理

package websystique.springmvc.configuration;

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


public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  
  @Override
  protected Class<?>[] getRootConfigClasses() {
    return null;
  }

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

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

}

配置类

通过EnableWebMvc开启Spring MVC

通过@ComponentScan,扫描包下的控制器文件

配置了一个视图解析器,这个解析器是用来解析jsp的

package websystique.springmvc.configuration;

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;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "websystique.springmvc")
public class HelloWorldConfiguration {
//配置视图解析器
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        internalResourceViewResolver.setViewClass(JstlView.class);
        internalResourceViewResolver.setPrefix("/WEB-INF/views/");
        internalResourceViewResolver.setSuffix(".jsp");
        return internalResourceViewResolver;
    }


}

控制器

@Controller表明他是一个控制器

@RequestMapping:拦截相关请求

package websystique.springmvc.controller;

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

@Controller
@RequestMapping("/")
public class HelloWorldController {
    @RequestMapping(method = RequestMethod.GET)
    public String sayHello(ModelMap model){
        model.addAttribute("greeting", "Hello World");
        return "welcome";
    }

    @RequestMapping(value = "helloagain", method = RequestMethod.GET)
    public String sayHelloAgain(ModelMap modelMap){
        modelMap.addAttribute("greeting", "Hello World Again");
        return "welcome";
    }
}

JSP文件

<%--
  Created by IntelliJ IDEA.
  User: masorl
  Date: 2018/9/14
  Time: 11:42
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>HelloWorld page</title>
</head>
<body>
Greeting : ${greeting}
</body>
</html>

结果:

url:http://localhost:8080/

url:http://localhost:8080/helloagain

补充一:通过MockMvc来测试Spring MVC控制器,省去重复启动服务器的麻烦

静态的standaloneSetup方法传入一个控制器实例,再使用build(),即可以构建MockMvc实例。

然后通过MockMvc,就可以执行对请求已经希望得到的视图名称进行判断。

package websystique.springmvc.controller;


import org.junit.Test;
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.view;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;

public class HelloWorldControllerTest {
    @Test
   public void controllTest() throws Exception{
        HelloWorldController helloWorldController = new HelloWorldController();
        //搭建MockMvc
        MockMvc mockMvc =   standaloneSetup(helloWorldController).build();
        mockMvc.perform(get("/"))
                .andExpect(view().name("welcome"));
    }

}

注意:再运行时候,出现了以下错误:

Error:(17, 34) java: 无法访问org.hamcrest.Matcher
  找不到org.hamcrest.Matcher的类文件

原因是Junit版本过低(当时用的4.0),改为4.11版本后无error

 

补充二:处理多个请求

 @RequestMapping(value = {"helloagain","say"}, method = RequestMethod.GET)

补充三:传递模型数据到视图中

注:helloPOJO是一个bean

    @RequestMapping(value = "getModel", method = RequestMethod.GET)
    public String setModel(Model model){
        model.addAttribute("helloPOJO", helloPOJO);
        return "welcome";

    }

结果

还有一种写法

返回一个对象,这个对象会直接放到模型里,而返回的视图,根据请求路径,这里是"model",所以返回的视图也是"model"

    @RequestMapping(value = "model", method = RequestMethod.GET)
    public HelloPOJO setModel2(Model model){
        return helloPOJO;
    }

补充三:接受路径参数的传入

只需要通过@RequestParam(参数名) 接收即可

//测试接受参数
    @RequestMapping(value = "acceptArgs", method = RequestMethod.GET)
    public String acceptArgs(@RequestParam("arg") String arg,
                             Model model){
        model.addAttribute("arg", arg);
        return "welcome";
    }

补充四:处理表单

在控制器添加两个相同请求路径的方法,一个用于处理GET请求,一个用于处理POST请求

GET方式请会跳转到register.jsp页面进行表单注册

POST请求会接受表单数据

    @RequestMapping(value = "register", method = RequestMethod.GET)
    public String showRegistration(){
        return "register";
    }

    @RequestMapping(value = "register", method = RequestMethod.POST)
    public String processRegistration(Spitrr spitrr){
        System.out.println(spitrr);
        return "register";
    }

register.jsp页面

form表单没有写action,它会提交到与先前相同的URL路径上,不过此时提交的方式为POST

<%--
  Created by IntelliJ IDEA.
  User: masorl
  Date: 2018/9/15
  Time: 11:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>注册</title>
</head>
<body>
        <form  method="POST">
            First Name: <input type="text" name="firstName" /><br/>
            Last Name: <input type="text" name="lastName" /><br/>
            Email: <input type="email" name="email" /><br/>
            Username: <input type="text" name="username" /><br/>
            Password: <input type="password" name="password" /><br/>
            <input type="submit" value="注册" />
        </form>
</body>
</html>

当点击提交后,会传入处理POST请求的processRegistration(Spitrr spitrr),参数会传入到Spitrr 类中

【自动调用Spitrr的无参构造函数,并调用setter方法将表单值 传入到类的实例中】

Spitrr类:普通的POJO类

package websystique.springmvc.domain;

import org.springframework.stereotype.Component;

public class Spitrr {
    private String firstName;
    private String lastName;
    private String email;
    private String username;
    private String password;

    public Spitrr() {
        System.out.println("默认构造器");
    }


    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        System.out.println("setFirstName:" + firstName);
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        System.out.println("setLastName:" + firstName);
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        System.out.println("setEmail:" + email);
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        System.out.println("setUsername:" + username);
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        System.out.println("setPassword:" + password);
        this.password = password;
    }
}

结果:成功接受到了表单传过来的数据

默认构造器
setEmail:3@4
setFirstName:1
setLastName:1
setPassword:6
setUsername:5
websystique.springmvc.domain.Spitrr@40423458

注意:必须要有无参构造器,不然报如下错误

 No default constructor found; nested exception is java.lang.NoSuchMethodException: websystique.springmvc.domain.Spitrr.<init>()

*************************************************************************************************************************************************

来自官网给出的实例【HTML】

<!-- freemarker config -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    <property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
</bean>

<!--
View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver.
-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="cache" value="true"/>
    <property name="prefix" value=""/>
    <property name="suffix" value=".ftl"/>
</bean>

猜你喜欢

转载自blog.csdn.net/MASORL/article/details/82694741