Spring MVC— 处理器(Handler)方法的返回值


1、演示项目环境搭建

1.1 演示项目工程结构

在IDEA中创建Web项目,具体项目工程结构如图所示:

controller:存放控制器(Controller)类。

model:存放JavaBean模型类。

config:存放Spring MVC核心配置文件等各种配置文件。

jsp:存放JSP页面文件。

jsp/user:存放该演示项目有关user模型的所有JSP文件。

lib:存放各种依赖的jar包。

1.2 演示项目依赖的基础jar包

该演示项目是在“Spring MVC使用篇”系列文章之前的项目工程的基础上搭建的,因此依赖的基础jar包于第二篇文章中已经介绍过了(点击链接即可查看:Spring MVC使用篇(二)—— 环境搭建),这里便不再赘述。

1.3 配置web.xml

此次出去在web.xml配置文件中配置Spring MVC的前端控制器(DispatcherServlet)外,还需要针对解决中文乱码问题设置过滤器。由于之前已经详细讲解,这里只贴出配置文件代码,详细请查看该系列第二篇文章(点击链接即可查看:Spring MVC使用篇(二)—— 环境搭建

<?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">
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/config/springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

    <!--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>
    </filter>

    <!--该配置表示,名为CharacterEncodingFilter的过滤器对所有请求进行过滤,然后该过滤器会
    以encoding指定的编码格式对请求数据进行统一编码-->
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

1.4 配置Spring MVC核心配置文件

在config文件夹下创建Spring MVC的核心配置文件“springmvc.xml”,并在配置文件中配置基于注解方式的处理器映射器和适配器、使用扫描配置和配置视图解析器。由于之前已经详细讲解,这里只贴出配置文件代码,详细请查看该系列第二篇文章(点击链接即可查看:Spring MVC使用篇(二)—— 环境搭建)具体代码如下:

<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

2、返回ModelAndView

若处理器方法处理完后,需要跳转到其他资源,且又要在跳转的资源间传递数据,此时处理器方法返回ModelAndView比较好。当然,若要返回ModelAndView,则处理器方法中需要定义ModelAndView对象。

例如要实现一个简单的处理用户注册请求的业务逻辑。在用户注册页面中要求用户输入用户编号、用户名和密码信息。当用户填写完毕后点击“用户注册”按钮后将请求和数据提交到后台进行处理,并返回处理结果(这里为了演示方便,处理用户注册数据的方式为直接显示用户注册时填写的全部信息)。

第一步,在“WEB- INF/jsp/user”下创建一个名为“login.jsp”的JSP页面,页面中通过一个表单收集用户输入的全部注册信息,并提交给“doLogin.action”进行注册业务逻辑的处理。login.jsp页面的代码如下所示:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>用户注册</title>
    </head>
    <body>
        <h3>用户注册</h3>
        <form action="doLogin.action" method="post">
            <table width="300px;" border=1>
                <tr>
                    <td>用户编号:</td>
                    <td><input type="text" name="userId" /></td>
                </tr>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username" /></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="password" name="password" /></td>
                </tr>
            </table>
            <br/>
            <input type="submit" value="用户注册" />
        </form>
    </body>
</html>

第二步,在controller文件夹下创建名为“UserController”的Controller类,该类用来实现所有的业务逻辑。首先创建login方法用来向用户显示注册页面(login.jsp)。然后创建doLogin方法用来处理前台页面通过表单传递过来的数据。Controller的具体代码如下所示:

package com.ccff.controller;

import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public ModelAndView login(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("user/login");
        return modelAndView;
    }

    @RequestMapping("/doLogin")
    public ModelAndView doLogin(User user){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("user",user);
        modelAndView.addObject("username",user.getUsername());
        modelAndView.addObject("userId",user.getUserId());
        modelAndView.addObject("password",user.getPassword());
        modelAndView.setViewName("user/doLogin");
        return modelAndView;
    }
}

第三步,由Controller中的代码可知,在Controller中的doLogin方法的形参采用的是接收引用类型的变量,这里便涉及到了在Spring MVC中关于各种类型参数的绑定问题(详细请查看该系列第七篇文章:Spring MVC使用篇(七)—— 参数绑定)和User这个JavaBean模型,具体代码如下所示:

package com.ccff.model;

public class User {
    private int userId;
    private String username;
    private String password;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int 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;
    }
}

第四步,在“WEB-INF/jsp/user”下创建名为“doLogin.jsp”的JSP页面用来显示处理用户注册信息后的结果页面。具体代码如下所示:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>处理用户注册信息</title>
    </head>
    <body>
        <h3>使用user参数显示用户注册信息</h3>
        <table width="300px;" border=1>
            <tr>
                <td>用户编号:</td>
                <td>${user.userId}</td>
            </tr>
            <tr>
                <td>用户名:</td>
                <td>${user.username}</td>
            </tr>
            <tr>
                <td>密 码:</td>
                <td>${user.password}</td>
            </tr>
        </table>

        <br/>
        <hr/>

        <h3>使用userId、username和password参数显示用户注册信息</h3>
        <table width="300px;" border=1>
            <tr>
                <td>用户编号:</td>
                <td>${userId}</td>
            </tr>
            <tr>
                <td>用户名:</td>
                <td>${username}</td>
            </tr>
            <tr>
                <td>密 码:</td>
                <td>${password}</td>
            </tr>
        </table>
    </body>
</html>

第五步,将项目部署到Tomcat服务器上后,通过浏览器访问请求URL:http://localhost:8080/demo/user/login.action 即可得到login.jsp所展示出来的页面,具体结果如下图所示:

当用户输入全部信息点击用户注册按钮后,表单会把用户所有的数据自动转换为与Controller中doLogin方法中形参所对应的User类型变量,并提交给doLogin方法处理,处理后返回doLogin.jsp页面,具体结果如下图所示:

注意 :在使用ModelAndView时,若该方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的Ajax异步响应),此时若返回ModelAndView对象,则将总是有一部分多余:要么Model多余,要么View多余。此时返回ModelAndView对象将不再合适。

3、返回String

处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器可以将其转换为物理视图地址。

3.1 返回内部资源逻辑视图名

3.1.1 配置视图解析器

若要跳转的资源为内部资源,则视图解析器可以使用InternalResourceViewResolver内部资源视图解析器(在之前的配置中我们默认配置的视图解析器即为该视图解析器)。此时处理器方法返回的字符串就是要跳转页面的文件名去掉文件扩展名后的部分。这个字符串与视图解析器中的prefix、suffix相结合,即可形成要访问的URI。

视图解析器的配置如下:

<!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

这里将Controller中的login方法修改为返回值为String类型,修改后的Controller如下:

package com.ccff.controller;

import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    public ModelAndView doLogin(User user){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("user",user);
        modelAndView.addObject("username",user.getUsername());
        modelAndView.addObject("userId",user.getUserId());
        modelAndView.addObject("password",user.getPassword());
        modelAndView.setViewName("user/doLogin");
        return modelAndView;
    }
}

再次将项目部署到Tomcat服务器上后,在浏览器内访问请求URL:http://localhost:8080/demo/user/login.action ,仍然能够显示用户注册页面,说明修改正确,结果如下图所示:

当然,也可以直接返回资源的物理视图名称(如该演示项目中的“/WEB- INF/jsp/user/login.jsp”)。不过,此时就不需要再在视图解析器中再配置前缀与后缀了。而且,需要特别注意的是直接返回的资源的物理名称的请求路径书写问题(详细请查看该系列文章:Spring MVC使用篇(五)—— 请求路径问题)。

3.1.2 使用HttpServletRequest对象携带数据跳转

由于Controller中的doLogin方法需要向跳转的页面传递数据,因此该方法的形参中除去接收绑定的User对象外,还需要有能够传递数据的HttpServletRequest对象。通过调用HttpServletRequest对象中的setAttribute方法实现数据的传递。修改后的Controller代码如下:

package com.ccff.controller;

import com.ccff.model.User;
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("/user")
public class UserController {

    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    public String doLogin(User user, HttpServletRequest request){
        request.setAttribute("user",user);
        request.setAttribute("username",user.getUsername());
        request.setAttribute("userId",user.getUserId());
        request.setAttribute("password",user.getPassword());
        return "user/doLogin";
    }
}

将修改后的项目重新部署到Tomcat服务器上后,在浏览器输入请求URL:http://localhost:8080/demo/user/login.action 后输入用户注册信息后点击“用户注册”按钮将表单中的数据传递给Controller中的doLogin方法进行处理,处理后显示doLogin.jsp页面,若如下图一样能够显示处理用户输入的注册数据,则证明修改正确。

3.1.3 使用Model对象携带数据跳转

除了使用HttpServletRequest对象传递数据外,还可以使用Model对象传递数据。Model对象就是ModelAndView对象中的Model,它只负责传递数据,通过Model对象的addAttribute方法即可实现。修改后的Controller代码如下所示:

package com.ccff.controller;

import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    public String doLogin(User user, Model model){
        model.addAttribute("user",user);
        model.addAttribute("username",user.getUsername());
        model.addAttribute("userId",user.getUserId());
        model.addAttribute("password",user.getPassword());
        return "user/doLogin";
    }
}

将修改后的项目重新部署到Tomcat服务器上后,在浏览器输入请求URL:http://localhost:8080/demo/user/login.action 后输入用户注册信息后点击“用户注册”按钮将表单中的数据传递给Controller中的doLogin方法进行处理,处理后显示doLogin.jsp页面,若如下图一样能够显示处理用户输入的注册数据,则证明修改正确。

3.2 返回View对象名

若要跳转的资源为外部资源,则视图解析器可以使用BeanNameViewResolver,然后在配置文件中再定义一些外部视图资源View对象,此时处理器方法返回的字符串就是要跳转资源视图View的名称。当然,这些视图View对象也可以是内部资源视图View对象。

第一步,为了能够实现外部资源的跳转,在Spring MVC的核心配置文件springmvc.xml中添加BeanNameViewResolver视图解析器,并设置BeanNameViewResolver视图解析器与默认的InternalResourceViewResolver视图解析器的优先级(关于视图解析器的详细讲解,请参考该系列的第四篇文章:Spring MVC使用篇(四)—— 视图解析器)。修改后的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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!--基于注解的方式配置处理器映射器和适配器方法一-->
    <!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
        <property name="order" value="2"/>
    </bean>
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="1"/>
    </bean>

    <!--定义一个内部资源-->
    <bean id="doLoginInternal" class="org.springframework.web.servlet.view.InternalResourceView">
        <property name="url" value="/WEB-INF/jsp/user/doLogin.jsp"/>
    </bean>
    <!--定义一个外部资源-->
    <bean id="baidu" class="org.springframework.web.servlet.view.RedirectView">
        <property name="url" value="https://www.baidu.com/"/>
    </bean>

</beans>

为了测试内部资源视图的跳转,将Controller中的doLogin方法修改如下:

package com.ccff.controller;

import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }   
    @RequestMapping("/doLogin")
    public String doLogin(User user, Model model){
        model.addAttribute("user",user);
        model.addAttribute("username",user.getUsername());
        model.addAttribute("userId",user.getUserId());
        model.addAttribute("password",user.getPassword());
        return "doLoginInternal";
    }
}

将修改后的项目重新部署到Tomcat服务器上后,在浏览器输入请求URL:http://localhost:8080/demo/user/login.action 后输入用户注册信息后点击“用户注册”按钮将表单中的数据传递给Controller中的doLogin方法进行处理,处理后显示doLogin.jsp页面。

由于在springmvc.xml配置文件中设置的BeanNameViewResolver视图解析器的优先级最高(Order值最小),因此默认会首先尝试采用BeanNameViewResolver视图解析器解析,得到如下结果,即说明修改正确。

接下来为了测试外部资源视图的跳转,将Controller中的doLogin方法修改如下:

package com.ccff.controller;

import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }
    @RequestMapping("/doLogin")
    public String doLogin(User user){
        return "baidu";
    }
}

将修改后的项目重新部署到Tomcat服务器上后,在浏览器输入请求URL:http://localhost:8080/demo/user/login.action 后输入用户注册信息后点击“用户注册”按钮将表单中的数据传递给Controller中的doLogin方法进行处理,处理后直接跳转到外部资源(百度首页)。

由于在springmvc.xml配置文件中设置的BeanNameViewResolver视图解析器的优先级最高(Order值最小),因此默认会首先尝试采用BeanNameViewResolver视图解析器解析。BeanNameViewResolver通过返回的视图名(“baidu”)找到在springm.xml文件中配置的外部资源,能够直接跳转到百度首页即说明修改正确。

4、返回void

对于处理器方法返回void的应用场景,主要有以下两种:

4.1 通过ServletAPI传递数据并完成跳转

通过在处理器方法的参数中放入的ServletAPI参数,来完成资源跳转时所要传递的数据及跳转。

可在方法参数中放入HttpServletRequest或HttpSession,使方法中可以直接将数据放入到request、session的域中,也可通过request.getServletContext()获取到ServletContext,从而将数据放入到application的域中。

可在方法参数中放入HttpServletRequest与HttpServletResponse,使方法可以完成请求转发与重定向。注意,重定向是无法完成对/WEB- INF/下的资源的访问的。

请求转发:request.getRequestDispatcher(“目标页面”).forward(request,response);

重定向:response.sendRedirect(“目标页面”);

对于本演示项目中,将Controller中的doLogin方法的返回值改为void,同时在方法的形参中添加两个参数,具体的修改如下:

package com.ccff.controller;

import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

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

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    public void doLogin(User user, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("user",user);
        request.setAttribute("username",user.getUsername());
        request.setAttribute("userId",user.getUserId());
        request.setAttribute("password",user.getPassword());
        //请求转发
        request.getRequestDispatcher("/WEB-INF/jsp/user/doLogin.jsp").forward(request,response);
    }
}

将项目重新部署在Tomcat上后,在浏览器输入请求URL:http://localhost:8080/demo/user/login.action 后,输入用户注册信息,点击“用户注册”按钮后,显示处理注册信息界面,则证明修改正确,具体结果如下:

4.2 AJAX响应

如果将目前的演示项目的前台页面采用AJAX的方式实现与后台的交互,则需要进行以下修改:

第一步,在web文件中创建一个名为“js”的文件夹用于存放JQuery文件,在前台使用JQuery库中的方法实现AJAX访问。

第二步,在lib文件夹中添加处理JSON数据所依赖的jar包。添加的JQuery依赖库和jar包如下图所示:

第三步,修改login.jsp页面。通过JavaScript脚本代码,利用JQuery依赖库获取表单中填写的数据,然后利用AJAX的异步请求来将表单数据提交。具体修改后的JSP代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>用户注册</title>
        <script type="text/javascript" src="../js/jquery-1.8.3.js" />
    </head>
    <body>
        <script type="text/javascript">
            $(function () {
                $("#login_button").click(function () {
                    var userId = $("#userId").val();
                    var username = $("#username").val();
                    var password = $("#password").val();
                    $.ajax({
                        url: "user/doLogin.action",
                        data: {
                            userId: userId,
                            username: username,
                            password: password
                        },
                        success: function (data) {
                            var myJson = eval("(" + data + ")");
                            alert(myJson.userId+" "+myJson.username+" "+myJson.password);
                        }
                    });
                });
            });    
        </script>
        <h3>用户注册</h3>
        <form action="doLogin.action" method="post">
            <table width="300px;" border=1>
                <tr>
                    <td>用户编号:</td>
                    <td><input type="text" name="userId" id="userId" /></td>
                </tr>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username" id="username" /></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="password" name="password" id="password" /></td>
                </tr>
            </table>
            <br/>
            <input type="button" id="login_button" value="用户注册" />
        </form>
    </body>
</html>

第四步,修改Controller中的doLogin方法。将表单提交过来的参数作为一个对象整体接收,需要保证AJAX请求参数接收的对象类型属性同名。具体修改的代码如下:

package com.ccff.controller;

import com.ccff.model.User;
import net.sf.json.JSONObject;
import org.codehaus.jackson.map.util.JSONPObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
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.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    public void doLogin(User user, HttpServletResponse response) throws ServletException, IOException {
        //将数据存放到map中
        Map<String,Object> map = new HashMap<>();
        map.put("userId",user.getUserId());
        map.put("username",user.getUsername());
        map.put("password",user.getPassword());
        //将map转为JSON
        JSONObject myJson = JSONObject.fromObject(map);
        String jsonString = myJson.toString();
        //将数据发送回客户端
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        out.print(jsonString);
        out.close();
    }
}

将项目重新部署在Tomcat上后,在浏览器输入请求URL:http://localhost:8080/demo/user/login.action 后,输入用户注册信息,点击“用户注册”按钮后,显示处理注册信息界面,则证明修改正确,具体结果如下:

5、返回Object

处理器方法也可以返回Object对象。但返回的这个Object对象不是作为逻辑视图出现的,而是直接在页面显示的数据出现的。

返回Object对象,需要使用@ResponseBody注解,将转换后的JSON数据放入到响应体中。

5.1 补充演示项目环境搭建

由于返回Object数据,一般都是将数据转化为了JSON对象后传递给浏览器页面的。而这个由Object转换为JSON,是由Jackson工具完成的。所以需要导入Jackson的相关jar包。添加的具体jar包如下:

5.2 注册注解驱动

将Object数据转换为JSON数据,需要由Http消息转换器HttpMessageConverter完成。而转换器开启,需要由 < mvc:annotation-driven />来完成的。

当Spring容器进行初始化过程中,在< mvc:annotation-driven />处创建注解驱动时,默认创建了七个HttpMessageConverter对象。也就是说,我们注册< mvc:annotation-driven />,就是为了让容器为我们创建HttpMessageConverter对象。配置如下:

<mvc:annotation-driven/>

5.3 返回数值型对象

对于返回数值型对象的演示案例,我们在之前的用户注册的案例基础上稍作修改,当用户输入注册信息后,点击“用户注册”按钮后将注册数据提交到后台处理,处理后返回给客户端这是第几个注册成功的用户。

首先,修改名为“login.jsp”的JSP页面如下所示:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>用户注册</title>
        <script type="text/javascript" src="../js/jquery-1.8.3.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            $(function () {
                $("#login_button").click(function () {
                    var userId = $("#userId").val();
                    var username = $("#username").val();
                    var password = $("#password").val();
                    $.ajax({
                        url: "doLogin.action",
                        data: {
                            userId: userId,
                            username: username,
                            password: password
                        },
                        success: function (data) {
                            alert("您是第"+data+"个注册的用户");
                        }
                    });
                });
            });
        </script>
        <h3>用户注册</h3>
        <form action="" method="post">
            <table width="300px;" border=1>
                <tr>
                    <td>用户编号:</td>
                    <td><input type="text" name="userId" id="userId" /></td>
                </tr>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username" id="username" /></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="password" name="password" id="password" /></td>
                </tr>
            </table>
            <br/>
            <input type="button" id="login_button" value="用户注册" />
        </form>
    </body>
</html>

然后修改Controller中的doLogin方法如下:

package com.ccff.controller;

import com.ccff.model.User;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    private List<User> loginedUsersList = new ArrayList<>();

    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    @ResponseBody
    public Object doLogin(User user) {
        //模拟已经注册好的用户的集合信息
        loginedUsersList = initLoginedUsers();
        //处理用户注册信息
        int count = -1;
        for (int i = 0; i < loginedUsersList.size(); i++) {
            User u = loginedUsersList.get(i);
            if (u.getUserId() != user.getUserId()){
                count = loginedUsersList.size()+1;
                break;
            }
        }
        return count;
    }

    private List<User> initLoginedUsers() {
        List<User> list = new ArrayList<>();

        User user1 = new User();
        user1.setUserId(1);
        user1.setUsername("tom");
        user1.setPassword("123456");

        User user2 = new User();
        user2.setUserId(2);
        user2.setUsername("jack");
        user2.setPassword("123456");

        list.add(user1);
        list.add(user2);

        return list;
    }
}

最后,将项目重新部署到Tomcat服务器上后,在浏览器内输入请求URL:http://localhost:8080/demo/user/login.action 后输出用户注册信息,点击“用户注册”按钮后得到如下结果,即证明修改正确。

5.4 返回字符串对象

若要返回非中文字符串,将前面返回数值类型数据的返回值直接修改为字符串即可。

但若要返回的字符串中带有中文字符,则接收方页面将会出现乱码,此时需要使用@RequestMapping的produces属性指定字符集。

例如在用户注册案例中,当用户注册成功后,返回欢迎语句“注册成功,欢迎您***”。

首先修改login.jsp页面如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>用户注册</title>
        <script type="text/javascript" src="../js/jquery-1.8.3.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            $(function () {
                $("#login_button").click(function () {
                    var userId = $("#userId").val();
                    var username = $("#username").val();
                    var password = $("#password").val();
                    $.ajax({
                        url: "doLogin.action",
                        type: "post",
                        contentType: "application/x-www-form-urlencoded; charset=utf-8",
                        data: {
                            userId: userId,
                            username: username,
                            password: password
                        },
                        success: function (data) {
                            alert("注册成功!欢迎您"+data+"!");                          
                        }
                    });
                });
            });
        </script>
        <h3>用户注册</h3>
        <form action="" method="post">
            <table width="300px;" border=1>
                <tr>
                    <td>用户编号:</td>
                    <td><input type="text" name="userId" id="userId" /></td>
                </tr>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username" id="username" /></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="password" name="password" id="password" /></td>
                </tr>
            </table>
            <br/>
            <input type="button" id="login_button" value="用户注册" />
        </form>
    </body>
</html>

然后修改Controller中的doLogin方法,修改如下:

package com.ccff.controller;

import com.ccff.model.User;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping(value = "/doLogin", produces = "text/html;charset=utf-8")
    @ResponseBody
    public Object doLogin(User user) {
        System.out.println(user.getUsername());
        return user.getUsername();
    }
}

最后,将项目重新部署到Tomcat服务器上后,在浏览器内输入请求URL:http://localhost:8080/demo/user/login.action 后输出用户注册信息,点击“用户注册”按钮后得到如下结果,即证明修改正确。

5.5 返回自定义类型对象

返回自定义类型对象时,不能以对象的形式直接返回给客户端浏览器,而是将对象转换为JSON格式的数据发送给浏览器的。

由于转换器底层使用了Jackson转换方式将对象转换为JSON数据,所以需要导入Jackson的相关jar包。

首先,修改login.jsp页面如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>用户注册</title>
        <script type="text/javascript" src="../js/jquery-1.8.3.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            $(function () {
                $("#login_button").click(function () {
                    var userId = $("#userId").val();
                    var username = $("#username").val();
                    var password = $("#password").val();
                    $.ajax({
                        url: "doLogin.action",
                        type: "post",
                        contentType: "application/x-www-form-urlencoded; charset=utf-8",
                        data: {
                            userId: userId,
                            username: username,
                            password: password
                        },
                        success: function (data) {
                            alert("用户编号:"+data.userId+"\n用户名:"+data.username+"\n用户密码:"+data.password);                         
                        }
                    });
                });
            });
        </script>
        <h3>用户注册</h3>
        <form action="" method="post">
            <table width="300px;" border=1>
                <tr>
                    <td>用户编号:</td>
                    <td><input type="text" name="userId" id="userId" /></td>
                </tr>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username" id="username" /></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="password" name="password" id="password" /></td>
                </tr>
            </table>
            <br/>
            <input type="button" id="login_button" value="用户注册" />
        </form>
    </body>
</html>

然后,修改Controller中的doLogin方法如下:

package com.ccff.controller;

import com.ccff.model.User;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping(value = "/doLogin")
    @ResponseBody
    public Object doLogin(User user) {
        return user;
    }  
}

最后,将项目重新部署到Tomcat服务器上后,在浏览器内输入请求URL:http://localhost:8080/demo/user/login.action 后输出用户注册信息,点击“用户注册”按钮后得到如下结果,即证明修改正确。

5.6 返回Map集合

首先,修改login.jsp页面如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>用户注册</title>
        <script type="text/javascript" src="../js/jquery-1.8.3.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            $(function () {
                $("#login_button").click(function () {
                    var userId = $("#userId").val();
                    var username = $("#username").val();
                    var password = $("#password").val();
                    $.ajax({
                        url: "doLogin.action",
                        type: "post",
                        contentType: "application/x-www-form-urlencoded; charset=utf-8",
                        data: {
                            userId: userId,
                            username: username,
                            password: password
                        },
                        success: function (data) {
                            var str1 = "用户编号:"+data.user1.userId+"  用户名:"+data.user1.username+"  用户密码:"+data.user1.password+"\n";
                            var str2 = "用户编号:"+data.user2.userId+"  用户名:"+data.user2.username+"  用户密码:"+data.user2.password+"\n";
                            var str3 = "用户编号:"+data.user3.userId+"  用户名:"+data.user3.username+"  用户密码:"+data.user3.password+"\n"
                            alert(str1+str2+str3);                           
                        }
                    });
                });
            });
        </script>
        <h3>用户注册</h3>
        <form action="" method="post">
            <table width="300px;" border=1>
                <tr>
                    <td>用户编号:</td>
                    <td><input type="text" name="userId" id="userId" /></td>
                </tr>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username" id="username" /></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="password" name="password" id="password" /></td>
                </tr>
            </table>
            <br/>
            <input type="button" id="login_button" value="用户注册" />
        </form>
    </body>
</html>

然后,修改Controller中的doLogin方法如下:

package com.ccff.controller;

import com.ccff.model.User;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    private List<User> loginedUsersList = new ArrayList<>();

    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    @ResponseBody
    public Object doLogin(User user) {
        //模拟已经注册好的用户的集合信息
        loginedUsersList = initLoginedUsers();
        //处理用户注册信息
        loginedUsersList.add(user);
        Map<String,User> map = new HashMap<>();
        for (int i = 0; i < loginedUsersList.size(); i++) {
            map.put("user"+(i+1),loginedUsersList.get(i));
        }
        return map;
    }

    private List<User> initLoginedUsers() {
        List<User> list = new ArrayList<>();

        User user1 = new User();
        user1.setUserId(1);
        user1.setUsername("tom");
        user1.setPassword("123456");

        User user2 = new User();
        user2.setUserId(2);
        user2.setUsername("jack");
        user2.setPassword("123456");

        list.add(user1);
        list.add(user2);

        return list;
    }
}

最后,将项目重新部署到Tomcat服务器上后,在浏览器内输入请求URL:http://localhost:8080/demo/user/login.action 后输出用户注册信息,点击“用户注册”按钮后得到如下结果,即证明修改正确。

5.7 返回List集合

首先,修改login.jsp页面如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!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=UTF-8">
        <title>用户注册</title>
        <script type="text/javascript" src="../js/jquery-1.8.3.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            $(function () {
                $("#login_button").click(function () {
                    var userId = $("#userId").val();
                    var username = $("#username").val();
                    var password = $("#password").val();
                    $.ajax({
                        url: "doLogin.action",
                        type: "post",
                        contentType: "application/x-www-form-urlencoded; charset=utf-8",
                        data: {
                            userId: userId,
                            username: username,
                            password: password
                        },
                        success: function (data) {
                            var string = "";
                            $(data).each(function (index) {
                                string += "用户编号:"+data[index].userId+"  用户名:"+data[index].username+"  用户密码:"+data[index].password+"\n";
                            })
                            alert(string)                         
                        }
                    });
                });
            });
        </script>
        <h3>用户注册</h3>
        <form action="" method="post">
            <table width="300px;" border=1>
                <tr>
                    <td>用户编号:</td>
                    <td><input type="text" name="userId" id="userId" /></td>
                </tr>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username" id="username" /></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="password" name="password" id="password" /></td>
                </tr>
            </table>
            <br/>
            <input type="button" id="login_button" value="用户注册" />
        </form>
    </body>
</html>

然后,修改Controller中的doLogin方法如下:

package com.ccff.controller;

import com.ccff.model.User;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    private List<User> loginedUsersList = new ArrayList<>();

    @RequestMapping("/login")
    public String login(){
        return "user/login";
    }

    @RequestMapping("/doLogin")
    @ResponseBody
    public Object doLogin(User user) {
        //模拟已经注册好的用户的集合信息
        loginedUsersList = initLoginedUsers();
        //处理用户注册信息
        for (int i = 0; i < loginedUsersList.size(); i++) {
            User u = loginedUsersList.get(i);
            if (u.getUserId() != user.getUserId()){
                loginedUsersList.add(user);
                break;
            }
        }
        return loginedUsersList;
    }

    private List<User> initLoginedUsers() {
        List<User> list = new ArrayList<>();

        User user1 = new User();
        user1.setUserId(1);
        user1.setUsername("tom");
        user1.setPassword("123456");

        User user2 = new User();
        user2.setUserId(2);
        user2.setUsername("jack");
        user2.setPassword("123456");

        list.add(user1);
        list.add(user2);

        return list;
    }
}

最后,将项目重新部署到Tomcat服务器上后,在浏览器内输入请求URL:http://localhost:8080/demo/user/login.action 后输出用户注册信息,点击“用户注册”按钮后得到如下结果,即证明修改正确。


原文链接:https://blog.csdn.net/weixin_36378917/article/details/83751890?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1