Spring学习笔记(六)——SpringMVC 概述和入门案例

2022-09-24 09:55:42 浏览数 (2)

SpringMVC 概述

SpringMVC 是什么

SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于 SpringFrameWork 的后续产品,已经融合在 Spring Web Flow 里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用 Spring 进行 WEB 开发时,可以选择使用 Spring的 Spring MVC 框架或集成其他 MVC 开发框架,如 Struts1(现在一般不用),Struts2 等。 SpringMVC 已经成为目前最主流的 MVC 框架之一,并且随着 Spring3.0 的发布,全面超越 Struts2,成为最优秀的 MVC 框架。 它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful 编程风格的请求。

SpringMVC 在三层架构的位置

SpringMVC 和 Struts2 的优略分析

  • 共同点: 它们都是表现层框架,都是基于 MVC 模型编写的。 它们的底层都离不开原始 ServletAPI。 它们处理请求的机制都是一个核心控制器。
  • 区别: Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter Spring MVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。 Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便 Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2 的表单标签,远没有 html 执行效率高。

SpringMVC 的入门

SpringMVC入门程序

  1. 创建WEB工程,引入开发的jar包

* 具体的坐标如下

代码语言:javascript复制
<?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>cn.qkongtao</groupId>
  <artifactId>Spring_MVC1</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>Spring_MVC1 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>

  </dependencies>

  <build>
    <finalName>Spring_MVC1</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
  • 配置核心的控制器(配置DispatcherServlet)
代码语言:javascript复制
<!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>
    <display-name>Archetype Created Web Application</display-name>

    <!-- SpringMVC的核心控制器 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- 配置servlet启动时加载对象 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
  • 编写springmvc.xml的配置文件
代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置spring创建容器时要扫描的包 -->
    <context:component-scan base-package="cn.kt"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 配置spring开启注解mvc的支持-->
    <mvc:annotation-driven />
</beans>
  • 编写index.jsp和HelloController控制器类

index.jsp

代码语言:javascript复制
<%--
  Created by IntelliJ IDEA.
  User: tao
  Date: 2020-04-08
  Time: 16:05
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
  <h2>SpringMVC入门</h2>
  <a href="/hello">sayHello</a>
</body>
</html>

HelloController.java

代码语言:javascript复制
package cn.kt.controller;/*
 *Created by tao on 2020-04-08.
 */

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

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String HelloController(){
        System.out.println("Hello Controller");
        //SpringMVC默认是 springmvc.xml 视图解析器配置位置的跳转
        return "success";
    }
}
  • 在WEB-INF目录下创建pages文件夹,编写success.jsp的成功页面
代码语言:javascript复制
package cn.kt.controller;/*
 *Created by tao on 2020-04-08.
 */

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

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String HelloController(){
        System.out.println("Hello Controller");
        //SpringMVC默认是 springmvc.xml 视图解析器配置位置的跳转
        return "success";
    }
}

入门案例中涉及的组件

  1. DispatcherServlet:前端控制器 用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
  2. HandlerMapping:处理器映射器 HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
  3. Handler:处理器 它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。
  4. HandlAdapter:处理器适配器 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
  5. View Resolver:视图解析器 View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
  6. View:视图 SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是 jsp。 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。 7.<mvc:annotation-driven>说明 在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。 使用<mvc:annotation-driven> 自动加载 RequestMappingHandlerMapping (处理映射器) 和RequestMappingHandlerAdapter ( 处 理 适 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中 使 用 <mvc:annotation-driven>替代注解处理器和适配器的配置。

RequestMapping注解

  1. RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系
  2. RequestMapping注解可以作用在方法和类上
    1. 作用在类上:第一级的访问目录
    2. 作用在方法上:第二级的访问目录
    3. 细节:路径可以不编写 / 表示应用的根目录开始
    4. 细节:${ pageContext.request.contextPath }也可以省略不写,但是路径上不能写 /
  3. RequestMapping的属性
    1. path 指定请求路径的url
    2. value value属性和path属性是一样的
    3. method 指定该方法的请求方式
      • @RequestMapping(value="/saveAccount",method=RequestMethod.POST)
    4. params 指定限制请求参数的条件
      • @RequestMapping(value="/removeAccount",params= {"accountName","money>100"})
    5. headers 发送的请求中必须包含的请求头

请求参数的绑定

请求参数中文乱码的解决

在web.xml中配置Spring提供的过滤器类

代码语言:javascript复制
<!-- 配置过滤器,解决中文乱码的问题 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filterclass>
<!-- 指定字符集 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
  1. 绑定机制
    1. 表单提交的数据都是k=v格式的 username=haha&password=123
    2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
    3. 要求:提交表单的name和参数的名称是相同的
  2. 支持的数据类型
    1. 基本数据类型和字符串类型
    2. 实体类型(JavaBean)
    3. 集合数据类型(List、map集合等)
  3. 基本数据类型和字符串类型
    1. 提交表单的name和参数的名称是相同的
    2. 区分大小写
  4. 实体类型(JavaBean)
    1. 提交表单的name和JavaBean中的属性名称需要一致
    2. 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:address.name
  5. 给集合属性数据封装
    1. JSP页面编写方式:list[0].属性
    2. JSP页面编写方式:map['key'].属性
  6. 自定义类型转换器
  7. 表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明Spring框架内部会默认进行数据类型转换。
  8. 如果想自定义数据类型转换,可以实现Converter的接口

* 自定义类型转换器

代码语言:javascript复制
package cn.kt.utils;/*
 *Created by tao on 2020-04-08.
 */

import org.springframework.core.convert.converter.Converter;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class StringToDate implements Converter<String, Date> {

    /**
     *
     * @param source 传进来的字符串
     * @return
     */
    @Override
    public Date convert(String source) {
        //判断
        if(source==null){
            throw new RuntimeException("请传入数据");
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        //把字符转换为日期
        try {
            return df.parse(source);
        } catch (ParseException e) {
            throw new RuntimeException("数据类型转换出现错误");
        }
    }
}
  • 注册自定义类型转换器,在springmvc.xml配置文件中编写配置
代码语言:javascript复制
 <!--配置自定义类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="cn.kt.utils.StringToDate"></bean>
            </set>
        </property>
    </bean>

    <!-- 配置spring开启注解mvc的支持-->
    <mvc:annotation-driven conversion-service="conversionService" />

Spring默认的Date格式是yyyy/MM/dd;上述就配置好了使用yyyy-MM-dd的日期字符串格式也可以转换为Date格式 9. 在控制器中使用原生的ServletAPI对象 只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象

代码语言:javascript复制
 /**
     * 原生API
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/testServlet")
    public String testServlet(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("执行了");
        System.out.println(request);
        HttpSession session = request.getSession();
        System.out.println(session);
        ServletContext servletContext = session.getServletContext();
        System.out.println(servletContext);
        System.out.println(response);
        return "success";
    }

请求参数绑定测试案例

  1. params.jsp
代码语言:javascript复制
<%--
  Created by IntelliJ IDEA.
  User: tao
  Date: 2020-04-08
  Time: 17:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--请求参数绑定--%>
<a href="param/testParams?username=KT" rel="nofollow noopener" >请求参数绑定</a>

<h2>表单登陆</h2>
<form action="param/saveAccount" method="post">
    姓名:<input type="text" name="username"></br>
    密码:<input type="password" name="password"> <br>
    金额:<input type="text" name="money"></br>
    生日:<input type="text" name="date"></br>
    持卡人姓名:<input type="text" name="user.uname"></br>
    年龄:<input type="number" name="user.age"></br>
    持卡人姓名:<input type="text" name="list[0].uname"></br>
    年龄:<input type="number" name="list[0].age"></br>
    持卡人姓名:<input type="text" name="map['ppp'].uname"></br>
    年龄:<input type="number" name="map['ooo'].age"></br>
    <input type="submit" value="提交">
</form>
</body>
</html>
  1. ParameController.java(控制器Controller)
代码语言:javascript复制
package cn.kt.controller;/*
 *Created by tao on 2020-04-08.
 */

import cn.kt.domian.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("param")
public class ParameController {


    /**
     * 请求参数入门
     *
     * @param username
     * @return
     */
    @RequestMapping("/testParams")
    public String testParams(String username) {
        System.out.println("执行了。。。");
        System.out.println("用户名:"   username);
        return "success";
    }

    /**
     * 把请求参数绑定到javaBean中
     *
     * @return
     */
    @RequestMapping("/saveAccount")
    public String saveAccount(Account account) {
        System.out.println("执行了。。。");
        System.out.println(account);
        return "success";
    }

    /**
     * 原生API
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/testServlet")
    public String testServlet(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("执行了");
        System.out.println(request);
        HttpSession session = request.getSession();
        System.out.println(session);
        ServletContext servletContext = session.getServletContext();
        System.out.println(servletContext);
        System.out.println(response);
        return "success";
    }
}
  1. javaBean封装
代码语言:javascript复制
package cn.kt.domian;/*
 *Created by tao on 2020-04-08.
 */

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class Account {
    private String username;
    private String password;
    private int money;
    //引用类型
    private User user;
    //集合
    private List<User>list ;
    private Map<String,User> map;
    //日期类型
    private Date date;

    @Override
    public String toString() {
        return "Account{"  
                "username='"   username   '''  
                ", password='"   password   '''  
                ", money="   money  
                ", user="   user  
                ", list="   list  
                ", map="   map  
                ", date="   date  
                '}';
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    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 int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public List<User> getList() {
        return list;
    }

    public void setList(List<User> list) {
        this.list = list;
    }

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

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

效果如下 1. 前台

2. 后台获取的数据 Account{username='admin', password='123456', money=6666, user=User{uname='呵呵', age=22}, list=[User{uname='熊大', age=33}], map={ooo=User{uname='null', age=44}, ppp=User{uname='熊二', age=0}}, date=Fri Nov 22 00:00:00 CST 2222}

0 人点赞