SpringMVC入门------一文上手SpringMVC框架

        SpringMVC是对Servlet的深层次封装,其架构功能分工明确,注解强大易用,方便整合MyBatis,Hiberate,JPA等其他框架。

        友情提示:阅读本文前需具备一些javaweb相关知识,可参考以下博文进行了解:

​​​​​​搭建一个简单的MVC框架_刚上路DE小白的博客-CSDN博客_mvc框架怎么建立

Spring入门之框架核心----IOC/AOP_刚上路DE小白的博客-CSDN博客

首先了解MVC模式:

        Model-View-Controller:模型--视图--控制器
        Model: 模型层 javaBean 负责数据访问和业务处理 dao service pojo
        View: 视图 JSP技术 负责收集和展示数据
        Controller: 控制器 servlet技术 中间调度
                控制器的工作:
                1、接受客户端的请求(包括请求中携带的数据)
                2、处理请求:调用后台的模型层中的业务逻辑
                3、页面导航:处理完毕给出响应:JSP页面

        下面代码示例为一个简单的SpringMVC案例,不涉及dao层,主要了解SpringMVC的工作机制和如何使用。

1.首先创建一个项目:

        创建maven项目后按照如下图补全目录结构:

2.在pom文件中添加依赖:

<?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>com.lxj</groupId>
    <artifactId>MySpringMVC</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope><!--插件运行的时候没有范围插件启动会失败-->
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- 编码和编译和JDK版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!--tomcat插件-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/</path>
                    <port>8080</port>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

 3.创建配置文件:

        首先是Spring的配置文件,在resources文件夹下创建applicationContext.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"
       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">
    <!--spring的配置文件:除了控制器之外的bean对象都在这里扫描-->
    <context:component-scan base-package="com.lxj.dao,com.lxj.service"/>
    <context:component-scan base-package="com.lxj.exception"/>
</beans>

        然后是SpringMVC的配置文件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
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--springmvc的配置文件:控制器的bean对象都在这里扫描-->
    <context:component-scan base-package="com.lxj.controller"/>
    <!--视图解析器-->
    <bean id="internalResourceViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <mvc:annotation-driven/>
    <!--annotation-driven是一种简写形式,也可以手动配置替代这种简写形式,简写形式可以让初学者快速
    应用默认配置方案。
    该注解会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter
    两个bean,是springMVC为@Controller分发用户请求所必须的,解决了@Controller注解使用的前提配
    置。
    同时它还提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支
    持,读写XML的支持(JAXB,读写JSON的支持(Jackson)。我们处理响应ajax请求时,就使用到了对json
    的支持(配置之后,在加入了jackson的core和mapper包之后,不写配置文件也能自动转换成json)。
    -->
    <mvc:default-servlet-handler/>
    <!--声 明 了 <mvc:default-servlet-handler /> 后 ,springmvc框架会在容器中创建
    DefaultServletHttpRequestHandler处理器对象。该对象会对所有进入 DispatcherServlet的URL
    进行检查。如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet 处理。
    一般的服务器都有默认的 Servlet。例如咱们使用的Tomcat服务器中,有一个专门用于处理静态资源
    访问的 Servlet 名叫 DefaultServlet。其<servlet-name/>为default。可以处理各种静态资源访问
    请求。该Servlet注册在 Tomcat 服务器的 web.xml 中。在 Tomcat安装目录/conf/web.xml。-->

    <mvc:resources location="/images/" mapping="/images/**" />
    <mvc:resources location="/js/" mapping="/js/**" />
    <mvc:resources location="/css/" mapping="/css/**" />


    <!--
    location: 表示静态资源所在目录。当然,目录不要使用/WEB-INF/及其子目录。
    mapping: 表示对该资源的请求。注意,后面是两个星号**。-->


    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 这里可以同时配置多个拦截器,配置的顺序就是拦截器的拦截顺序 -->
        <mvc:interceptor>
            <!-- 拦截器要拦截的请求路径 拦截所有用/** -->
            <mvc:mapping path="/**"/>
            <!-- 指定干活的拦截器 -->
            <bean class="com.lxj.interceptor.MyInterceptor"
                  id="myInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <!-- 拦截器要拦截的请求路径 拦截所有用/** -->
            <mvc:mapping path="/**"/>
            <!-- 指定干活的拦截器 -->
            <bean class="com.lxj.interceptor.MyInterceptor2"
                  id="myInterceptor2"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/file/**"/>
            <bean class="com.lxj.interceptor.FileInterceptor" id="fileInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    <!--如果有多个拦截器的时候:
        preHandle:按照配置前后顺序执行
        postHandle:按照配置前后逆序执行
        afterCompletion:按照配置前后逆序执行-->

    <!--文件上传-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--文件上传的大小限制 以字节B为单位 5m :1024*1024*5 1M=1024KB 1KB=1024B-->
        <property name="maxUploadSize" value="5242880"/>
        <property name="defaultEncoding" value="utf-8"/>
    </bean>


</beans>

注意:我们的项目中将存在两个容器,一个是 Spring 容器,另一个是SpringMVC 容器,Spring 容器通过 ContextLoaderListener 来加载,SpringMVC 容器则通过DispatcherServlet 来加载,这两个容器不一样:

        4.通过web.xml对spring和springmvc配置:

<?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">
    <!--spring的配置-->
    <context-param>
        <!--contextConfigLocation:表示用于加载 Bean的配置文件-->
        <param-name>contextConfigLocation</param-name>
        <!--指定spring配置文件的位置
        这个配置文件也有一些默认规则,它的配置文件名默认就叫 applicationContext.xml ,
        如果将这个配置文件放在 WEB-INF 目录下,那么这里就可以不用 指定配置文件位置,
        只需要指定监听器就可以。
        这段配置是 Spring 集成 Web 环境的通用配置;一般用于加载除控制器层的 Bean(如
        dao、service 等),以便于与其他任何Web框架集成。
        -->
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--SpringMVC的配置-->
    <!--
    前端控制器:所有的请求都会经过此控制器,然后通过此控制器分发到各个分控制器.
    前端控制器本质上还是一个Servlet,因为SpringMVC底层就是使用Servlet编写的
    -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 创建前端控制器的时候读取springmvc配置文件启动ioc容器 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>
        <!-- Tomcat启动就创建此对象 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 配置拦截路径url,所有以.do结尾的请求都会被前端控制器拦截处理 -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--
        SpringMVC的配置解析:
        1、servlet-class:前端控制器的完全限定名,在spring-webmvc-5.2.5.RELEASE.jar包中的
        org.springframework.web.servlet下
        2、load-on-startup:标记是否在Web服务器(这里是Tomcat)启动时会创建这个 Servlet 实
        例,即是否在 Web 服务器启动时调用执行该 Servlet 的 init()方
        法,而不是在真正访问时才创建。 要求取值是整数。
        值大于0:表示容器在启动时就加载并初始化这个 servlet,数值越小,该 Servlet的优先级就
        越高,其被创建的也就越早
        值小于0或者省略:表示该 Servlet 在真正被使用时才会去创建。
        值相同:容器会自己选择创建顺序
        3、url-pattern:可以写为 / ,可以写为*.do 、*.action、*.mvc等形式,此处先写*.do,以后
        介绍不同写法的区别。
        4、init-param:表示了springmvc配置文件的名称和位置。如果没有配置,默认在项目的WEB-INF目录下找名称为 Servlet 名称-servlet.xml 的配置文件。
        如果没有配置,启用默认的规则:即如果配置文件放在 webapp/WEB-INF/ 目录下,并且配置文
        件的名字等于 DispatcherServlet 的名字+ -servlet(即这里的配置文件路径是 webapp/WEBINF/dispatcherServlet-servlet.xml),如果是这样的话,可以不用添加 init-param 参数,即不
        用手动配置 springmvc 的配置文件,框架会自动加载。
        而一般情况下,配置文件是放在类路径下,即 resources 目录下。所以,在注册前端控制器时,
        还需要设置查找 SpringMVC 配置文件路径。
        其中contextConfigLocation属性:来自DispatcherServlet的父类FrameworkServlet,
        该类中的contextConfigLocation属性用来配置springmvc的路径和名称。
        -->
    <!--注册字符集过滤器:post请求中文乱码问题的解决方案-->
    <filter>
        <filter-name>characterEncodingFilter</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>
        <!--强制request使用字符集encoding-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
            <!--强制response使用字符集encoding-->
            <init-param>
                <param-name>forceResponseEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 使用Rest风格的URI 将页面普通的post请求转为指定的delete或者put请求原理:在Aajx中发送post请求后,带_method参数,将其修改为PUT,或者DELETE请求-->
    <filter>
        <filter-name>httpMethodFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.HiddenHttpMethodFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>httpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

         至此,相关配置文件创建完成,这里对SprngMVC工作流程做简要分析:

  1. 用户通过浏览器发送请求到前端控制器DispatcherServlet。
  2. 前端控制器直接将请求转给处理器映射器HandleMapping。
  3. 处理器映射器HandleMapping会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链HandlerExecutionChina后返回给前端控制器DispatcherServlet。
  4. 前端控制器DispatcherServlet根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器HandlerAdaptor。
  5. 处理器适配器HandlerAdaptor调用执行处理器Controller。
  6. 处理器Controller将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器HandlerAdaptor。
  7. 处理器适配器直接将结果返回给前端控制器DispatcherServlet。
  8. 前端控制器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。
  9. 视图解析器ViewResolver将封装了的视图View对象返回给前端控制器DispatcherServlet.
  10. 前端控制器DispatcherServlet调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。
  11. 前端控制器响应浏览器

下面对不同功能逐步进行介绍:

1.不同类型的参数获取:

        新建一个实体类:

package com.lxj.pojo.com.lxj;

import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

public class Team {
    private Integer teamId;
    private  String teamName;
    private String location;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date createTime;

    @Override
    public String toString() {
        return "Team{" +
                "teamId=" + teamId +
                ", teamName='" + teamName + '\'' +
                ", location='" + location + '\'' +
                ", createTime=" + createTime +
                '}';
    }

    public Integer getTeamId() {
        return teamId;
    }

    public void setTeamId(Integer teamId) {
        this.teamId = teamId;
    }

    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

        新建hello.jsp页面:

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2022/6/5
  Time: 21:49
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Hello</title>
</head>
<body>
    <h3>8、获取集合类型的参数</h3>
    <form action="/param/test08" method="post">
        球队名称1:<input type="text" name="teamName"/><br/>
        球队名称2:<input type="text" name="teamName"/><br/>
        球队名称3:<input type="text" name="teamName"/><br/>
        <button type="submit">提交</button>
    </form>
    <form action="/param/test09" method="post">
        球队id1:<input type="text" name="teamList[0].teamId"/><br/>
        球队id2:<input type="text" name="teamList[1].teamId"/><br/>
        球队id3:<input type="text" name="teamList[2].teamId"/><br/>
        球队名称1:<input type="text" name="teamList[0].teamName"/><br/>
        球队名称2:<input type="text" name="teamList[1].teamName"/><br/>
        球队名称3:<input type="text" name="teamList[2].teamName"/><br/>
        <button type="submit">提交</button>
    </form>
    <h3>7、获取数组类型的参数</h3>
    <form action="/param/test07" method="post">
        球队名称1:<input type="text" name="teamName"/><br/>
        球队名称2:<input type="text" name="teamName"/><br/>
        球队名称3:<input type="text" name="teamName"/><br/>
        <button type="submit">提交</button>
    </form>
    <h3>6、获取日期类型的参数</h3>
    <form action="/param/test06" method="post">
        球队id:<input type="text" name="teamId"/><br/>
        球队名称:<input type="text" name="teamName"/><br/>
        球队位置:<input type="text" name="location"/><br/>
        创建日期:<input type="text" name="createTime"/><br/>
        <button type="submit">提交</button>控制器ParamController.java
    </form>
    <h3>5、直接使用URL地址传参</h3>
    <h3>4、使用HttpServletRequest 对象获取参数</h3>
    <form action="/param/test04" method="post">
        球队id:<input type="text" name="teamId"/><br/>
        球队名称:<input type="text" name="teamName"/><br/>
        球队位置:<input type="text" name="location"/><br/>
        <button type="submit">提交</button>
    </form>
    <h3>3、请求参数和方法名称的参数不一致</h3>
    <form action="/param/test03" method="post">
        球队id:<input type="text" name="teamId"/><br/>
        球队名称:<input type="text" name="teamName"/><br/>
        球队位置:<input type="text" name="location"/><br/>
        <button type="submit">提交</button>
    </form>
    <h3>2、使用对象接收多个参数</h3>
    <form action="/param/test02" method="post">
        球队id:<input type="text" name="teamId"/><br/>
        球队名称:<input type="text" name="teamName"/><br/>
        球队位置:<input type="text" name="location"/><br/>
        <button type="submit">提交</button>
    </form>
    <h3>1、直接使用方法的参数逐个接收</h3>
    <form action="/param/test01" method="post">
        球队id:<input type="text" name="teamId"/><br/>
        球队名称:<input type="text" name="teamName"/><br/>
        球队位置:<input type="text" name="teamLocation"/><br/>
        <button type="submit">提交</button>
    </form>
</body>
</html>

        新建对应的controlor:

package com.lxj.controller;

import com.lxj.pojo.com.lxj.QueryVO;
import com.lxj.pojo.com.lxj.Team;
import com.lxj.service.TeamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Controller
@RequestMapping("param")
public class TeamController {
    @Autowired
    TeamService teamService;

    /**
    * 1、直接使用方法的参数逐个接收:方法的参数名称必须与用户请求中携带的参数名称保持一致,否则
        就获取不到
    * 好处:不需要类型转换
    */
    @RequestMapping("test01")
    public ModelAndView test01(Integer teamId,String teamName,String
            teamLocation){
        System.out.println("test01-----------------");
        System.out.println(teamId);
        System.out.println(teamName);
        System.out.println(teamLocation);
        return new ModelAndView("ok");
    }
    //2、使用对象接收多个参数:要求用户请求中携带的参数名称必须是实体类中的属性保持一致,否则就获取不到
    @RequestMapping("test02")
    public ModelAndView test02(Team team){
        System.out.println("test02-----------------");
        System.out.println(team);
        return new ModelAndView("ok");
    }
    //3、请求参数和方法名称的参数不一致:使用@RequestParam进行矫正,
    // value属性表示请求中的参数名称
    // required属性表示参数是否是必须的:true:必须赋值,否则报出400错;false:可以不赋值,结果就是null
    @RequestMapping("test03")
    public ModelAndView test03(@RequestParam(value = "teamId",required = false)
                                       Integer id,
                               @RequestParam(value = "teamName",required = true)
                                       String name,
                               @RequestParam("location") String loc){
        System.out.println("test03-----------------");
        System.out.println(id);
        System.out.println(name);
        System.out.println(loc);
        return new ModelAndView("ok");
    }

    //4、使用HttpServletRequest 对象获取参数:跟原来的javaWeb项目中使用的方式是一样的
    @RequestMapping("test04")
    public ModelAndView test04(HttpServletRequest request){
        System.out.println("test04-----------------");
        String teamId = request.getParameter("teamId");
        String teamName = request.getParameter("teamName");
        String location = request.getParameter("location");
        if(teamId!=null)
            System.out.println(Integer.valueOf(teamId));
        System.out.println(teamName);
        System.out.println(location);
        return new ModelAndView("ok");
    }
    //5、直接使用URL地址传参: 借助@PathVariable 注解
    // 例如http://localhost:8080/param/test05/1001/lacker/las
    @RequestMapping("test05/{id}/{name}/{loc}")
    public ModelAndView test05(@PathVariable("id") Integer teamId,
                               @PathVariable("name") String teamName,
                               @PathVariable("loc") String teamLocation){
        System.out.println("test05-----------------");
        System.out.println(teamId);
        System.out.println(teamName);
        System.out.println(teamLocation);
        return new ModelAndView("ok");
    }

    //6、获取日期类型的参数
    @RequestMapping("test06")
    public ModelAndView test06(Team team){
        System.out.println("test06-----------------");
        System.out.println(team);
        return new ModelAndView("ok");
    }
    //7、获取数组类型的参数
    @RequestMapping("test07")
    public ModelAndView test07(String[] teamName,HttpServletRequest request){
        System.out.println("test07-----------------");
        //方式1:
        for (String s : teamName) {
            System.out.println(s);
        } System.out.println("---------------");
        //方式2:
        String[] teamNames = request.getParameterValues("teamName");
        for (String name : teamNames) {
            System.out.println(name);
        }
        return new ModelAndView("ok");
    }

    //8、获取集合类型的参数: 简单类型的可以通过@RequestParam注解实现;对象集合不支持直接获取,必须封装在类中,作为一个属性操作
    @RequestMapping("test08")
    public ModelAndView test08(@RequestParam("teamName") List<String> nameList){
        System.out.println("test08-----------------");
        for (String s : nameList) {
            System.out.println(s);
        }
        return new ModelAndView("ok");
    }
    @RequestMapping("test09")
    public ModelAndView test09(QueryVO vo){
        System.out.println("test09-----------------");
        for (Team team : vo.getTeamList()) {
            System.out.println(team);
        }
        return new ModelAndView("ok");
    }

    @RequestMapping("Hello.do")
    public ModelAndView add(){
        System.out.println("TeamController:add()");
        teamService.add();
        ModelAndView mv=new ModelAndView();
        mv.addObject("teamName","湖人");//相当于request.setAttrubuite("teanName","湖人");
        mv.setViewName("index");//未来经过springmvc的视图解析器处理,转换成物理资源路径,相当于request.getRequestDispatcher("index.jsp").forward();
        //经过InternalResourceViewResolver对象的处理之后加上前后缀就变为了/jsp/index.jsp
        return mv;
    }
}

遇到中午乱码问题,可在web.xml中添加字符集过滤器(详见上文web.xml中)

2.不同类型的返回值

        新建result.jsp:

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2022/6/6
  Time: 20:24
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>result</title>
    <script src="/js/jquery-1.11.1.js"></script>
</head>
<body>
    <h1>result----------------</h1>
    <h3>test01------${teamName}---</h3>

    <h3>test02---request作用域获取:---${requestScope.team.teamName}--
        -${requestScope.team.teamId}---${requestScope.team.location}</h3>
    <h3>test02---session作用域获取:---${sessionScope.team.teamName}--
        -${sessionScope.team.teamId}---${sessionScope.team.location}</h3>

    <div>
        <button type="button" id="btn1">ajax请求自定义对象</button>
        <h3>ajax请求自定义对象的结果展示</h3>
        <p id="res"></p>
    </div>
    <script>
        $(function(){
            $("#btn1").click(function () {
                $.ajax({
                    type: "POST",
                    url: "/result/test03-3",
                    data: "",
                    success: function(msg){
                        alert( "Data Saved: " + msg );
                        var name=msg.teamName;
                        var id=msg.teamId;
                        var loc=msg.location;
                        $("#res").html("name:"+name+",id:"+id+",location:"+loc);
                    }
                });
            });
        });
    </script>

    <div>
        <button type="button" id="btn2">ajax请求自定义对象</button>
        <h3>ajax请求自定义对象的结果展示</h3>
        <p id="res2"></p>
    </div>
    <script>
        $(function(){
            $("#btn2").click(function () {
                $.ajax({
                    type: "POST",
                    url: "/result/test03-4",
                    data: "",
                    success: function(list){
                        alert( "Data Saved: " + list );
                        var str="";
                        for(var i=0;i<list.length;i++){
                            var obj=list[i];
                            str+="name:"+obj.teamName+",id:"+obj.teamId+",location:"+obj.location+"<br/>";
                        } $
                        ("#res2").html(str);
                    }
                });
            });
        });
    </script>

    <div>
        <button type="button" id="btn3">ajax请求Map</button>
        <h3>ajax请求Map的结果展示</h3>
        <p id="res3"></p>
    </div>
    <script>
        $(function() {
            $("#btn3").click(function () {
                $.ajax({
                    type: "POST",
                    url: "/result/test03-5",
                    data: "",
                    success: function (map) {
                        alert("Data Saved: " + map);
                        var str = "";
                        $.each(map, function (i, obj) {
                            str += "name:" + obj.teamName + ",id:" + obj.teamId + ",location:" + obj.location + "<br/>";
                        });
                        $("#res3").html(str);
                    }
                });
            });
        });
    </script>

</body>
</html>

        新建对应的controllor:

package com.lxj.controller;

import com.lxj.pojo.com.lxj.Team;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

@Controller
@RequestMapping("result")
public class ResultController {
    //1、返回值是ModelAndView: 这种方式既有数据的携带还有资源的跳转,可以选择该种方式
    @RequestMapping("test01")
    public ModelAndView test01(){
        ModelAndView mv=new ModelAndView();//模型与视图
        //携带数据
        mv.addObject("teamName","湖人队");//相当于request.setAttribute("teamName","湖人队“);
        mv.setViewName("result");// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
        return mv;
    }
    //2、返回字符串
    @RequestMapping("test02")
    public String test02(HttpServletRequest request){
        Team team=new Team();
        team.setLocation("迈阿密");
        team.setTeamId(1002);
        team.setTeamName("热火");
        //携带数据
        request.setAttribute("team",team);
        request.getSession().setAttribute("team",team);
        //资源的跳转
        return "result";// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
    }
    //3、返回对象类型:Integer Double String 自定义类型 List Map 返回的不是逻辑视图的名称,而直接就是数据返回 ,一般是ajax请求搭配使用 ,将json格式的数据直接返回给响应体一定要与@ResponseBody
    @ResponseBody
    @RequestMapping("test03-1")
    public Integer test031(){
        return 666;
    }
    @ResponseBody
    @RequestMapping("test03-2")
    public String test032(){
        return "test";
    }
    @ResponseBody
    @RequestMapping("test03-3")
    public Team test033(){
        Team team=new Team();
        team.setLocation("迈阿密");
        team.setTeamId(1002);
        team.setTeamName("热火");
        return team;
    }

    @ResponseBody
    @RequestMapping("test03-4")
    public List<Team> test034(){
        List<Team> list=new ArrayList<>(5);
        for(int i=1;i<=5;i++) {
            Team team = new Team();
            team.setLocation("迈阿密"+i);
            team.setTeamId(1002+i);
            team.setTeamName("热火"+i);
            list.add(team);
        }
        return list;
    }

    @ResponseBody
    @RequestMapping("test03-5")
    public Map<String,Team> test035(){
        Map<String,Team> map=new HashMap();
        for(int i=1;i<=5;i++) {
            Team team = new Team();
            team.setLocation("金州"+i);team.setTeamId(1000+i);
            team.setTeamName("勇士"+i);
            //日期类型,在返回的时候是个数字,如果想要按日期格式展示需要在实体类对应属性添加注解@JsonFormat(pattern = "yyyy-MM-dd")
            team.setCreateTime(new Date());
            map.put(team.getTeamId()+"",team);
        }
        return map;
    }

    //通过 HttpServletRequest 做服务端跳转
    @RequestMapping("test04-1")
    public void test041(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        System.out.println("直接使用HttpServletRequest进行服务器端的转发");
        request.getRequestDispatcher("/jsp/ok.jsp").forward(request,response);
    }

    //通过 HttpServletResponse 做重定向
    @RequestMapping("test04-2")
    public void test042(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        System.out.println("直接使用HttpServletResponse重定向跳转");
        response.sendRedirect("/jsp/ok.jsp");
    }

    //通过 HttpServletResponse 给出响应
    @RequestMapping("test04-3")
    public void test043(HttpServletResponse response) throws ServletException,
            IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write("返回void类型测试---直接返回字符串");
        writer.flush();
        writer.close();
    }

    //也可以自己手动指定响应头去实现重定向:
    @RequestMapping("test04-4")
    public void test044(HttpServletResponse response) throws ServletException,
            IOException {
        response.setStatus(302);//设置响应码,302表示重定向
        response.setHeader("Location","/jsp/ok.jsp");
    }

}

3.转发和重定向:

package com.lxj.controller;

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

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("navigation")
public class NavigationController {

    @RequestMapping("test01-1")
    public String test011(HttpServletRequest request){
        request.setAttribute("teamName","湖人");
        //return "ok";//默认方式:由视图解析器处理之后将逻辑视图转为物理资源路径
        return "forward:/jsp/ok.jsp";//当添加了forward前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
    }

    @RequestMapping("test01-2")
    public ModelAndView test012(){
        ModelAndView mv=new ModelAndView();
        mv.addObject("teamName","热火");
        //mv.setViewName("ok");//默认方式:由视图解析器处理之后将逻辑视图转为物理资源路径
        mv.setViewName( "forward:/jsp/ok.jsp");//当添加了forward前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
        return mv;
    }

    @RequestMapping("test02-1")
    public String test021(HttpServletRequest request){
        request.setAttribute("teamName","勇士");//页面上无法获取到存储在request作用域中的值,请求中断了
        return "redirect:/jsp/ok.jsp";//当添加了redirect前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
    }

    @RequestMapping("test02-2")
    public ModelAndView test022(){
        ModelAndView mv=new ModelAndView();
        mv.addObject("teamName","huangfeng");
        //存储在request作用域中的值以参数的形式追加在URL后面
        http://localhost:8080/jsp/ok.jsp?teamName=huangfeng&teamId=1002
        mv.addObject("teamId","1002");
        mv.setViewName( "redirect:/jsp/ok.jsp");//当添加了redirect前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
        return mv;
    }
}

4.异常处理:

        首先自定义不同级别的异常类:

package com.lxj.exception;

public class TeamException extends Exception{
    public TeamException() {
    }
    public TeamException(String message) {
        super(message);
    }
}
package com.lxj.exception;

public class TeamIdException extends TeamException{
    public TeamIdException() {
    }
    public TeamIdException(String message) {
        super(message);
    }
}
package com.lxj.exception;

public class TeamNameException extends TeamException{
    public TeamNameException() {
    }
    public TeamNameException(String message) {
        super(message);
    }
}

        编写对应的controller:

package com.lxj.controller;

import com.lxj.exception.TeamIdException;
import com.lxj.exception.TeamNameException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("exp")
public class ExController {

    @RequestMapping("test01/{id}/{name}")
    public ModelAndView test01(@PathVariable("id") Integer teamId, @PathVariable("name") String teamName)
            throws TeamIdException,TeamNameException {
        ModelAndView mv=new ModelAndView();
        if(teamId<=1000){
            throw new TeamIdException("teamId不合法!必须在1000之上!");
        }
        if("test".equals(teamName)){
            throw new TeamNameException("teamName不合法!不能使用test!");
        }
        System.out.println(10/0);
        mv.setViewName("ok");
        return mv;
    }

    @ExceptionHandler(value = {TeamIdException.class,TeamNameException.class,Exception.class})
    public ModelAndView exHandler(Exception ex){
        ModelAndView mv=new ModelAndView();
        mv.addObject("msg",ex.getMessage());
        if(ex instanceof TeamIdException)
            mv.setViewName("idError");
        else if(ex instanceof TeamNameException)
            mv.setViewName("nameError");
        else
            mv.setViewName("error");
        return mv;
    }
}

package com.lxj.exception;

import com.lxj.exception.TeamException;
import com.lxj.exception.TeamIdException;
import com.lxj.exception.TeamNameException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = TeamIdException.class)
    public ModelAndView exHandler1(Exception ex){
        ModelAndView mv=new ModelAndView();
        mv.addObject("msg",ex.getMessage());
        mv.setViewName("idError");
        return mv;
    }
    @ExceptionHandler(value = TeamNameException.class)
    public ModelAndView exHandler2(Exception ex){
        ModelAndView mv=new ModelAndView();
        mv.addObject("msg",ex.getMessage());
        mv.setViewName("nameError");
        return mv;
    }

    @ExceptionHandler(value = TeamException.class)
    public ModelAndView exHandler4(Exception ex){
        ModelAndView mv=new ModelAndView();
        mv.addObject("msg",ex.getMessage());
        mv.setViewName("nameError");
        return mv;
    }
    @ExceptionHandler(value = Exception.class)
    public ModelAndView exHandler3(Exception ex){
        ModelAndView mv=new ModelAndView();
        mv.addObject("msg",ex.getMessage());
        mv.setViewName("error");
        return mv;
    }

}

        分别写error.jsp/iderror.jsp/nameerror.jsp进行实验:

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2022/6/13
  Time: 20:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>error</title>
</head>
<body>
    <h1>默认的错误页面--${msg}</h1>
</body>
</html>
<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2022/6/13
  Time: 20:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>teamId</title>
</head>
<body>
    <h1>teamId Error----${msg}</h1>
</body>
</html>
<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2022/6/13
  Time: 20:41
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>teamName</title>
</head>
<body>
    <h1>teamName error---${msg}</h1>
</body>
</html>

5.拦截器:

        SpringMVC 中的 拦截器( Interceptor)是非常重要的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。拦截的时间点在“处理器映射器HandlerMapping根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器HandlerAdaptor执行处理器之前”。在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链HandlerExecutionChain,并返回给了前端控制器。自定义拦截器,需要实现 HandlerInterceptor 接口。而该接口中含有三个方法:

preHandle(request,response, Object handler):
        该方法在处理器方法执行之前执行。其返回值为boolean,若为true,则紧接着会执行处理器方法,且会将afterCompletion()方法放入到一个专门的方法栈中等待执行。
postHandle(request,response, Object handler,modelAndView):
        该方法在处理器方法执行之后执行。处理器方法若最终未被执行,则该方法不会执行。由于该方法是在处理器方法执行完后执行,且该方法参数中包含 ModelAndView,所以该方法可以修改处理器方法的处理结果数据,且可以修改跳转方向。
afterCompletion(request,response, Object handler, Exception ex):
        当 preHandle()方法返回true时,会将该方法放到专门的方法栈中,等到对请求进行响应的所工作完成之后才执行该方法。即该方法是在前端控制器渲染(数据填充)了响应页面之后执行的,此时对ModelAndView再操作也对响应。

        首先自定义拦截器:

package com.lxj.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class MyInterceptor implements HandlerInterceptor {
    //执行时间: 控制器方法执行之前,在ModelAndView返回之前
    //使用场景: 登录验证
    // 返回值 true : 继续执行控制器方法 表示放行 false: 不会继续执行控制器方法,表示拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle---------------------");
        return true;
    }
    //执行时间: 控制器方法执行之hou后,在ModelAndView返回之前,有机会修改返回值
    //使用场景: 日记记录,记录登录的ip,时间
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle---------------------");
    }
    //执行时间: 控制器方法执行之后,在ModelAndView返回之后,没有机会修改返回值
    //使用场景: 全局资源的一些操作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion----------------------");
    }
}
package com.lxj.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class MyInterceptor2 implements HandlerInterceptor {
    //执行时间: 控制器方法执行之前,在ModelAndView返回之前
    //使用场景: 登录验证
    // 返回值 true : 继续执行控制器方法 表示放行 false: 不会继续执行控制器方法,表示拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle2---------------------");
        return true;
    }
    //执行时间: 控制器方法执行之hou后,在ModelAndView返回之前,有机会修改返回值
    //使用场景: 日记记录,记录登录的ip,时间
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2---------------------");
    }
    //执行时间: 控制器方法执行之后,在ModelAndView返回之后,没有机会修改返回值
    //使用场景: 全局资源的一些操作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion2----------------------");
    }
}

        然后在springmvc.xm中进行配置(详见前文配置文件)

6.文件上传和下载

        首先添加依赖,并在springmvc.xml中配置

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<!--文件上传-->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>

        在项目中添加文件夹保存上传的文件:

         添加fileHandle.jsp文件:

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2022/6/14
  Time: 21:04
  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 action="/file/upload" method="post" enctype="multipart/form-data">
        请选择文件:<input type="file" name="myFile" /><br/>
        <button type="submit">上传文件</button>
    </form>

    <form action="/file/download" method="post" enctype="multipart/form-data">
        <button type="submit">下载图片--9078a8f8d2f148629136f3f03133631e.png</button>
    </form>
</body>
</html>

        新建controller:

package com.lxj.controller;

import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.UUID;

@Controller
@RequestMapping("file")
public class FileController {
    @RequestMapping("upload")
    public String upload(@RequestParam("myFile") MultipartFile myFile,
                         HttpServletRequest request){
        //获取文件的原始名称 d:\te.aa\txcat.jpg
        String originalFilename = myFile.getOriginalFilename();
        // 实际开发中,一般都要将文件重新名称进行存储
        // 存储到服务器的文件名称=随机的字符串+根据实际名称获取到源文件的后缀
        String fileName= UUID.randomUUID().toString().replace("-","")
                +originalFilename.substring(originalFilename.lastIndexOf("."));
        System.out.println(fileName);
        //文件存储路径
        String realPath = request.getServletContext().getRealPath("/uploadFile")+"/";
        try {
            myFile.transferTo(new File(realPath+fileName));//真正的文件上传到服务器指定的位置
            System.out.println("上传成功!"+realPath+fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "ok";
    }

    @RequestMapping("download")
    public ResponseEntity<byte[]> download(HttpServletRequest request) throws IOException {
        String path=request.getServletContext().getRealPath("/uploadFile")+"/9078a8f8d2f148629136f3f03133631e.png";
        //创建响应 的头信息的对象
        HttpHeaders headers=new HttpHeaders();
        //标记以流的方式作出响应
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //以附件的形式响应给用户
        headers.setContentDispositionFormData("attachment", URLEncoder.encode("9078a8f8d2f148629136f3f03133631e.png","utf-8"));
        File file=new File(path);
        ResponseEntity<byte[]> resp=new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
        return resp;
    }

    @RequestMapping("hello")
    public String hello(){
        return "fileHandle";
    }
}

        文件过滤器:

package com.lxj.interceptor;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map;

public class FileInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean flag=true;
        if (request instanceof MultipartHttpServletRequest) {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
            //遍历文件
            Iterator<String> iterator = fileMap.keySet().iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                MultipartFile file = multipartRequest.getFile(key);
                String originalFilename = file.getOriginalFilename();
                String hz = originalFilename.substring(originalFilename.lastIndexOf("."));
                //判断后缀是否合法
                if (!hz.toLowerCase().equals(".png") && !hz.toLowerCase().equals(".jpg")) {
                    request.getRequestDispatcher("/jsp/fileTypeError.jsp").forward(request, response);
                    flag = false;
                }
            }
        }
        return flag;
    }
}

7.RESTful风格:

        不强制,但强烈建议。

        主要是用GET、POST、PUT、DELETE。他们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。

创建restful.jsp:

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2022/6/6
  Time: 20:24
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>result</title>
    <script src="/js/jquery-1.11.1.js"></script>
</head>
<body>
    <h1>result----------------</h1>
    <h3>test01------${teamName}---</h3>

    <h3>test02---request作用域获取:---${requestScope.team.teamName}--
        -${requestScope.team.teamId}---${requestScope.team.location}</h3>
    <h3>test02---session作用域获取:---${sessionScope.team.teamName}--
        -${sessionScope.team.teamId}---${sessionScope.team.location}</h3>

    <div>
        <button type="button" id="btn1">ajax请求自定义对象</button>
        <h3>ajax请求自定义对象的结果展示</h3>
        <p id="res"></p>
    </div>
    <script>
        $(function(){
            $("#btn1").click(function () {
                $.ajax({
                    type: "POST",
                    url: "/result/test03-3",
                    data: "",
                    success: function(msg){
                        alert( "Data Saved: " + msg );
                        var name=msg.teamName;
                        var id=msg.teamId;
                        var loc=msg.location;
                        $("#res").html("name:"+name+",id:"+id+",location:"+loc);
                    }
                });
            });
        });
    </script>

    <div>
        <button type="button" id="btn2">ajax请求自定义对象</button>
        <h3>ajax请求自定义对象的结果展示</h3>
        <p id="res2"></p>
    </div>
    <script>
        $(function(){
            $("#btn2").click(function () {
                $.ajax({
                    type: "POST",
                    url: "/result/test03-4",
                    data: "",
                    success: function(list){
                        alert( "Data Saved: " + list );
                        var str="";
                        for(var i=0;i<list.length;i++){
                            var obj=list[i];
                            str+="name:"+obj.teamName+",id:"+obj.teamId+",location:"+obj.location+"<br/>";
                        } $
                        ("#res2").html(str);
                    }
                });
            });
        });
    </script>

    <div>
        <button type="button" id="btn3">ajax请求Map</button>
        <h3>ajax请求Map的结果展示</h3>
        <p id="res3"></p>
    </div>
    <script>
        $(function() {
            $("#btn3").click(function () {
                $.ajax({
                    type: "POST",
                    url: "/result/test03-5",
                    data: "",
                    success: function (map) {
                        alert("Data Saved: " + map);
                        var str = "";
                        $.each(map, function (i, obj) {
                            str += "name:" + obj.teamName + ",id:" + obj.teamId + ",location:" + obj.location + "<br/>";
                        });
                        $("#res3").html(str);
                    }
                });
            });
        });
    </script>

</body>
</html>

        这里需要注意:在Ajax中,采用Restful风格PUT和DELETE请求传递参数无效,传递到后台的参数值为null,前端页面中的ajax发送请求的时候在url中加 &_method=”PUT” 或者 &_method=”DELETE” 即可。

        自己封装一个公用的响应结果实体类:

package com.lxj.pojo.com.lxj;

import java.util.List;

public class AjaxResultVo <T>{
    private Integer code;
    private String msg;
    private List<T> list;
    private T obj;

    public AjaxResultVo(){
        code=200;
        msg="ok";
        list=null;
        obj=null;
    }

    public AjaxResultVo(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public AjaxResultVo(Integer code, String msg, List<T> list) {
        this.code = code;
        this.msg = msg;
        this.list = list;
    }

    public AjaxResultVo(Integer code, String msg, T obj) {
        this.code = code;
        this.msg = msg;
        this.obj = obj;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

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

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

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}

        新建控制器:

package com.lxj.controller;

import com.lxj.pojo.com.lxj.Team;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

@Controller
@RequestMapping("result")
public class ResultController {
    //1、返回值是ModelAndView: 这种方式既有数据的携带还有资源的跳转,可以选择该种方式
    @RequestMapping("test01")
    public ModelAndView test01(){
        ModelAndView mv=new ModelAndView();//模型与视图
        //携带数据
        mv.addObject("teamName","湖人队");//相当于request.setAttribute("teamName","湖人队“);
        mv.setViewName("result");// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
        return mv;
    }
    //2、返回字符串
    @RequestMapping("test02")
    public String test02(HttpServletRequest request){
        Team team=new Team();
        team.setLocation("迈阿密");
        team.setTeamId(1002);
        team.setTeamName("热火");
        //携带数据
        request.setAttribute("team",team);
        request.getSession().setAttribute("team",team);
        //资源的跳转
        return "result";// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
    }
    //3、返回对象类型:Integer Double String 自定义类型 List Map 返回的不是逻辑视图的名称,而直接就是数据返回 ,一般是ajax请求搭配使用 ,将json格式的数据直接返回给响应体一定要与@ResponseBody
    @ResponseBody
    @RequestMapping("test03-1")
    public Integer test031(){
        return 666;
    }
    @ResponseBody
    @RequestMapping("test03-2")
    public String test032(){
        return "test";
    }
    @ResponseBody
    @RequestMapping("test03-3")
    public Team test033(){
        Team team=new Team();
        team.setLocation("迈阿密");
        team.setTeamId(1002);
        team.setTeamName("热火");
        return team;
    }

    @ResponseBody
    @RequestMapping("test03-4")
    public List<Team> test034(){
        List<Team> list=new ArrayList<>(5);
        for(int i=1;i<=5;i++) {
            Team team = new Team();
            team.setLocation("迈阿密"+i);
            team.setTeamId(1002+i);
            team.setTeamName("热火"+i);
            list.add(team);
        }
        return list;
    }

    @ResponseBody
    @RequestMapping("test03-5")
    public Map<String,Team> test035(){
        Map<String,Team> map=new HashMap();
        for(int i=1;i<=5;i++) {
            Team team = new Team();
            team.setLocation("金州"+i);team.setTeamId(1000+i);
            team.setTeamName("勇士"+i);
            //日期类型,在返回的时候是个数字,如果想要按日期格式展示需要在实体类对应属性添加注解@JsonFormat(pattern = "yyyy-MM-dd")
            team.setCreateTime(new Date());
            map.put(team.getTeamId()+"",team);
        }
        return map;
    }

    //通过 HttpServletRequest 做服务端跳转
    @RequestMapping("test04-1")
    public void test041(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        System.out.println("直接使用HttpServletRequest进行服务器端的转发");
        request.getRequestDispatcher("/jsp/ok.jsp").forward(request,response);
    }

    //通过 HttpServletResponse 做重定向
    @RequestMapping("test04-2")
    public void test042(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        System.out.println("直接使用HttpServletResponse重定向跳转");
        response.sendRedirect("/jsp/ok.jsp");
    }

    //通过 HttpServletResponse 给出响应
    @RequestMapping("test04-3")
    public void test043(HttpServletResponse response) throws ServletException,
            IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write("返回void类型测试---直接返回字符串");
        writer.flush();
        writer.close();
    }

    //也可以自己手动指定响应头去实现重定向:
    @RequestMapping("test04-4")
    public void test044(HttpServletResponse response) throws ServletException,
            IOException {
        response.setStatus(302);//设置响应码,302表示重定向
        response.setHeader("Location","/jsp/ok.jsp");
    }

}

        本文是学习了 “开课吧JAVAEE开发工程师” 课程相关内容后结合课堂笔记和代码总结的,如有意愿和兴趣进行更全面的学习和提升可参加开课吧相关课程培训学习:JavaEE商业项目架构就业班-开课吧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值