Spring MVC(一)

1、Spring MVC 简介

1.1、概念

        模型—视图—控制器(MVC)是一个众所周知的以设计界面应用程序为基础的设计思想。它主要通过分离模型、视图及控制器在应用程序中的角色将业务逻辑从界面中解耦。通常,模型负责封装应用程序数据在视图层展示。视图仅仅只是展示这些数据,不包含任何业务逻辑。控制器负责接收来自用户的请求,并调用后台服务(service或者dao)来处理业务逻辑。处理后,后台业务层可能会返回了一些数据在视图层展示。控制器收集这些数据及准备模型在视图层展示。MVC模式的核心思想是将业务逻辑从界面中分离出来,允许它们单独改变而不会相互影响。

1.2、特点

  • 让我们能非常简单的设计出干净的 Web 层

  • 进行更简洁的 Web 层的开发

  • 天生与 Spring 框架集成(如 IOC 容器、AOP 等)

  • 提供强大的约定大于配置的契约式编程支持

  • 能简单的进行 Web 层的单元测试;

  • 支持灵活的 URL 到页面控制器的映射

  • 非常容易与其他视图技术集成,如 jsp、Velocity、FreeMarker 等等,因为模型数据不放在特定的 API 里,而是放在一个 Model 里(Map 数据结构实现,因此很容易被其他框架使用)

  • 非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的 API

  • 支持灵活的本地化等解析

  • 更加简单的异常处理

  • 对静态资源的支持

  • 支持 Restful 风格

2、Spring MVC 的执行流程

  • 首先用户发送请求,请求被 SpringMvc 前端控制器(DispatherServlet)捕获
  • 前端控制器(DispatherServlet)对请求 URL 解析获取请求 URI,根据 URI,调用HandlerMapping
  • 前端控制器(DispatherServlet)获得返回的 HandlerExecutionChain(包括 Handler 对象以及 Handler 对象对应的拦截器
  • DispatcherServlet 根据获得的 HandlerExecutionChain,选择一个合适的 HandlerAdapter(附注:如果成功获得 HandlerAdapter 后,此时将开始执行拦截器的 preHandler(...)方法)
  • HandlerAdapter 根据请求的 Handler 适配并执行对应的 Handler;HandlerAdapter (提取Request)中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)。在填充 Handler 的入参过程中,根据配置,Spring 将做一些额外的工作:
    • HttpMessageConveter:将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息
    • 数据转换:对请求消息进行数据转换。如 String转换成 Integer、Double 等数据
    • 格式化:数据格式化。如将字符串转换成格式化数字或格式化日期等
    • 数据验证:验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或 Error 中)
  • Handler 执行完毕,返回一个 ModelAndView (即模型和视图)给 HandlerAdaptor
  • HandlerAdaptor 适配器将执行结果 ModelAndView 返回给前端控制器
  • 前端控制器接收到 ModelAndView 后,请求对应的视图解析器
  • 视图解析器解析 ModelAndView 后返回对应 View
  • 渲染视图并返回渲染后的视图给前端控制器
  • 最终前端控制器将渲染后的页面响应给用户或客户端

3、Spring MVC 环境搭建

3.1、创建 Maven war 项目

3.2、添加依赖

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
    <!-- spring web -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.2.4.RELEASE</version>
    </dependency>

    <!-- spring mvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.4.RELEASE</version>
    </dependency>

    <!-- web servlet -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- 编译环境插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>11</source>
                <target>11</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>

        <!-- jetty插件 -->
        <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>9.4.27.v20200227</version>
            <configuration>
                <scanIntervalSeconds>10</scanIntervalSeconds>
                <!-- 设置端口 -->
                <httpConnector>
                    <port>9090</port>
                </httpConnector>
                <!-- 设置项目路径 -->
                <webAppConfig>
                    <contextPath>/Spring_MVC01</contextPath>
                </webAppConfig>
            </configuration>
        </plugin>
    </plugins>
</build>

3.3、配置 web.xml 文件

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

    <!--解决乱码的过滤器-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 中央控制器-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定核心配置文件 springmvc.xml 的位置 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:springmvc.xml</param-value>
        </init-param>
        <!-- 懒汉变饿汉 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

3.4、配置 springmvc.xml 文件

<?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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 开启扫描 -->
    <context:component-scan base-package="com.yjxxt.controller"/>
    <!-- 静态资源处理的 handler -->
    <mvc:default-servlet-handler/>
    <!-- 注解的驱动 -->
    <mvc:annotation-driven/>
    <!-- 视图解析器 -->
    <bean id="resolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
        <!-- 后缀 -->
    </bean>

</beans>

3.5、页面控制器

@Controller
public class HelloController {

    @RequestMapping("hello")
    public ModelAndView sayIndex(){
        // 实例化对象
        ModelAndView view = new ModelAndView();
        // 存储数据
        view.addObject("message", "Hello Spring MVC!");
        // 指定视图
        view.setViewName("hello");
        // 返回目标对象
        return view;
    }
}

3.6、视图页面

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${message}
</body>
</html>

3.7、启动 jetty 服务器,访问 http://localhost:9090/Spring_MVC01/hello

4、返回类型

4.1、ModelAndView 对象

@RequestMapping("hello")
public ModelAndView sayIndex(){
    // 实例化对象
    ModelAndView view = new ModelAndView();
    // 存储数据
    view.addObject("message", "Hello Spring MVC!");
    // 指定视图
    view.setViewName("hello");
    // 返回目标对象
    return view;
}

 4.2、String

@RequestMapping("index")
public String Index(Model model){
    // 存储数据
    model.addAttribute("info", "yangzhiqiang!");
    // 返回对象
    return "mvc";
}

        mvc.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${info}
</body>
</html>

5、收集数据

5.1、基本数据类型

        表达域的 name 值与 handler 方法形参一致即可

@Controller
public class DataController {

    @RequestMapping("data")
    public ModelAndView say01(String username, String password, Integer age, Double score){
        System.out.println(username + " ---> " + password + " ---> " + age + " ---> " + score);
        // 实例化对象
        ModelAndView view = new ModelAndView();
        // 存储数据
        view.addObject("username", username);
        view.addObject("password", password);
        view.addObject("age", age);
        view.addObject("score", score);
        // 指定视图
        view.setViewName("data");
        // 返回对象
        return view;
    }
}

        data.jsp: 

<form action="data" method="get">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    年龄:<input type="text" name="age"><br>
    分数:<input type="text" name="score"><br>
    <input type="submit" value="提交">
</form>

${username} ---> ${password} ---> ${age} ---> ${score}

         设置默认值:

@Controller
public class DataController {

    @RequestMapping("data")
    public ModelAndView say01(String username, String password, @RequestParam(defaultValue = "18") Integer age, @RequestParam(defaultValue = "60") Double score){
        System.out.println(username + " ---> " + password + " ---> " + age + " ---> " + score);
        // 实例化对象
        ModelAndView view = new ModelAndView();
        // 存储数据
        view.addObject("username", username);
        view.addObject("password", password);
        view.addObject("age", age);
        view.addObject("score", score);
        // 指定视图
        view.setViewName("data");
        // 返回对象
        return view;
    }
}

5.2、收集数组

        表达域的 name 值与目标方法形参名称一致即可

@Controller
public class DataController {

    @RequestMapping("array")
    public String say02(String [] hobby, Model model){
        System.out.println(Arrays.toString(hobby));
        String str = hobby.toString();
        model.addAttribute("hobby", str);
        return "array";
    }
}

        array.jsp:

<form action="array" method="get">
    <input type="checkbox" name="hobby" value="抽烟">抽烟
    <input type="checkbox" name="hobby" value="喝酒">喝酒
    <input type="checkbox" name="hobby" value="烫头">烫头
    <input type="submit" value="提交">
</form>

${hobby}

5.3、收集 JavaBean

        表单域 name 值与 javaBean 的属性值一致即可

        javaBean:

public class User {

    private Integer userid;
    private String username;
    private String password;
    private Double sal;
    private Integer age;
    private String [] hobby;

    public User() {}

    public Integer getUserid() {
        return userid;
    }

    public void setUserid(Integer userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Double getSal() {
        return sal;
    }

    public void setSal(Double sal) {
        this.sal = sal;
    }

    public Integer getAge() {
        return age;
    }

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

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "User{" +
                "userid=" + userid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", sal=" + sal +
                ", age=" + age +
                ", hobby=" + Arrays.toString(hobby) +
                '}';
    }
}

        controller:

@Controller
public class DataController {

    @RequestMapping("user")
    public String say03(User user, Model model){
        System.out.println(user);
        model.addAttribute("user", user);
        return "user";
    }
}

        user.jsp:

<form action="user" method="get">
    <input type="hidden" name="userid" value="1"><br>
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    年龄:<input type="text" name="age"><br>
    工资:<input type="text" name="sal"><br>
    爱好:
    <input type="checkbox" name="hobby" value="抽烟">抽烟
    <input type="checkbox" name="hobby" value="喝酒">喝酒
    <input type="checkbox" name="hobby" value="烫头">烫头
    <br>
    <input type="submit" value="提交">
</form>

${user.userid} ---> ${user.username} ---> ${user.password} ---> ${user.age} ---> ${user.sal} ---> ${user.hobby}

5.3、收集 list 数据

        定义 phone 实体类

public class Phone {

    private String num;

    public Phone() {}

    public Phone(String num) {
        this.num = num;
    }

    public String getNum() {
        return num;
    }

    public void setNum(String num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "num='" + num + '\'' +
                '}';
    }
}

         user 实体类:

public class User {

    private List<Phone> phones = new ArrayList<Phone>();

    public User() {}

    public List<Phone> getPhones() {
        return phones;
    }

    public void setPhones(List<Phone> phones) {
        this.phones = phones;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "phones=" + phones +
                '}';
    }
}

        controller:

@Controller
public class DataController {

    @RequestMapping("list")
    public String say04(User user){
        List<Phone> phones = user.getPhones();
        for (Phone p : phones) {
            System.out.println(p);
        }
        return "list";
    }
}

        list.jsp:

<form action="list" method="get">
    手机:<input type="text" name="phones[0].num" value="12345678910">
    电话:<input type="text" name="phones[1].num" value="123-45678910">
    <input type="submit" value="提交">
</form>

5.4、收集 set 数据

        user 实体类:

public class User {

    private Set<Phone> set = new HashSet<Phone>();

    public User() {
        set.add(new Phone());
        set.add(new Phone());
    }

    public Set<Phone> getSet() {
        return set;
    }

    public void setSet(Set<Phone> set) {
        this.set = set;
    }

    @Override
    public String toString() {
        return "User{" +
                "set=" + set +
                '}';
    }
}

        controller:

@Controller
public class DataController {

    @RequestMapping("set")
    public String say05(User user){
        Set<Phone> set = user.getSet();
        for (Phone p : set) {
            System.out.println(p);
        }
        return "set";
    }
}

        set.jsp:

<form action="set" method="get">
    手机:<input type="text" name="set[0].num" value="12345678910">
    电话:<input type="text" name="set[1].num" value="123-45678910">
    <input type="submit" value="提交">
</form>

5.5、收集 map 数据

        user 实体类:

public class User {

    private Map<String, Phone> map = new HashMap<String, Phone>();

    public Map<String, Phone> getMap() {
        return map;
    }

    public void setMap(Map<String, Phone> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "User{" +
                "map=" + map +
                '}';
    }
}

         controller:

@Controller
public class DataController {

    @RequestMapping("map")
    public String say06(User user){
        Map<String, Phone> map = user.getMap();
        // 获取 key
        Set<String> keys = map.keySet();
        // 遍历获取 value
        for (String key : keys) {
            System.out.println(key + " --- >" + map.get(key));
        }
        return "map";
    }
}

        map.jsp:

<form action="map" method="get">
    手机:<input type="text" name="map['0'].num" value="12345678910">
    电话:<input type="text" name="map['1'].num" value="123-45678910">
    <input type="submit" value="提交">
</form>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值