Spring MVC 学习总结(三)——请求处理方法Action详解

Spring MVC中每个控制器中可以定义多个请求处理方法,我们把这种请求处理方法简称为Action,每个请求处理方法可以有多个不同的参数,以及一个多种类型的返回结果。

一、Action参数类型

如果在请求处理方法中需要访问HttpSession对象,则可以添加HttpSession作为参数,Spring会将对象正确的传递给方法,如:public  String action(HttpSession session);若需要访问客户端语言环境和HttpServletRequest对象,则可以在方法签名上包含这样的参数,如:public String action(HttpServletRequest request,Locale locale)。可以在请求中出现的参数类型有:

org.springframework.web.context.request.WebRequest
org.springframework.web.context.request.NativeWebRequest
java.util.Locale 当前请求的语言环境
java.util.TimeZone 时区
java.io.InputStream或java.io.Reader
java.io.OutputStream或java.io.Writer
org.springframework.http.HttpMethod
java.security.Principal
HttpEntity <?>参数用于访问Servlet的HTTP请求的标题和内容
java.util.Map / org.springframework.ui.Model / org.springframework.ui.ModelMap 视图隐含模型
org.springframework.web.servlet.mvc.support.RedirectAttributes 重定向
命令或表单对象
基本数据类型,如int,String,double...
复杂数据类型,如自定义的POJO对象
HandlerAdapter
org.springframework.validation.Errors / org.springframework.validation.BindingResult 验证结果
org.springframework.web.bind.support.SessionStatus 会话状态
org.springframework.web.util.UriComponentsBuilder
@PathVariable 注解参数访问URI模板变量。
@MatrixVariable 注释参数用于访问位于URI路径段键值对对,矩阵变量。
@RequestParam 注解参数访问特定的Servlet请求参数,请求参数绑定。
@RequestHeader 注解参数访问特定的se​​rvlet请求HTTP标头,映射请求头。
@RequestBody 注解参数访问HTTP请求主体,注解映射请求体
@RequestPart 注解参数访问“的multipart / form-data的”请求部分的内容。处理客户端上传文件,多部分文件上传的支持
@SessionAttribute 注解参数会话属性
@RequestAttribute 注解参数访问请求属性

1.1、自动参数映射

1.1.1、基本数据类型

方法的参数可以是任意基本数据类型,如果方法参数名与http中请求的参数名称相同时会进行自动映射,视图foo目录下的index.jsp与示例代码如下:

复制代码
    // 自动参数映射
    @RequestMapping("/action0")
    public String action0(Model model, int id, String name) {
        model.addAttribute("message", "name=" + name + ",id=" + id);
        return "foo/index";
    }
复制代码
复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Foo</title>
</head>
<body>
${message}
</body>
</html>
复制代码

 

运行结果如下:

包装类型也一样,但如果参数中没有对应名称与类型的数据则会异常。

1.1.2、自定义数据类型

除了基本数据类型,也可以自定义的数据类型,如一个自定义的POJO对象,Spring MVC会通过反射把请中的参数设置到对象中,转换类型,示例代码如下:

  View Code
复制代码
    // 自动参数映射自定义数据类型
    @RequestMapping("/action01")
    public String action01(Model model, Product product) {
        model.addAttribute("message", product);
        return "foo/index";
    }
复制代码

运行结果如下:

示例中使用的是的URL中的参数,其实也可以是客户端提交的任意参数,特别是表单中的数据。

1.1.3、复杂数据类型

这里指的复杂数据类型指的是一个自定义类型中还包含另外一个对象类型,如用户类型中包含产品对象:

复制代码
package com.zhangguo.springmvc03.entities;

public class User {
    private String username;
    private Product product;

    public String getUsername() {
        return username;
    }

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

    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }
}
复制代码

示例代码如下:

复制代码
    // 自动参数映射复杂数据类型
    @RequestMapping("/action02")
    public String action02(Model model, User user) {
        model.addAttribute("message", user.getUsername() + "," + user.getProduct().getName());
        return "foo/index";
    }
复制代码

测试运行结果:

为了方便这里我使用的是url,这里当然可以是一个表单,如下代码所示:

复制代码
<form method="post" action="foo/action02">
     username:<input name="username" /><br/>
     pdctname:<input name="product.name" /><br/>
    <button>提交</button>
</form>
复制代码

1.1.4、List集合类型

不能直接在action的参数中指定List<T>类型,定义一个类型包装List集合在其中,ProductList类如下所示:

复制代码
package com.zhangguo.springmvc03.entities;

import java.util.List;

//产品集合
public class ProductList {
    private List<Product> items;

    public List<Product> getItems() {
        return items;
    }

    public void setItems(List<Product> items) {
        this.items = items;
    }
}
复制代码

定义的action代码如下所示:

复制代码
    // 集合类型
    @RequestMapping("/action03")
    public String action03(Model model, ProductList products) {
        model.addAttribute("message", products.getItems().get(0) + "<br/>" + products.getItems().get(1));
        return "foo/index";
    }
复制代码

在url中模拟表单数据,提交后的结果如下所示:

这里同样可以使用一个表单向服务器提交数据。

1.1.5、Map集合类型

Map与List的实现方式基本一样,这里先定义了一个包装Map的类型ProductMap,代码如下所示:

复制代码
package com.zhangguo.springmvc03.entities;

import java.util.Map;

/**
 * * 产品字典
 */
public class ProductMap {
    private Map<String, Product> items;

    public Map<String, Product> getItems() {
        return items;
    }

    public void setItems(Map<String, Product> items) {
        this.items = items;
    }
}
复制代码

Action的定义如下:

复制代码
    // Map类型
    @RequestMapping("/action04")
    public String action04(Model model, ProductMap map) {
        model.addAttribute("message", map.getItems().get("p1") + "<br/>" + map.getItems().get("p2"));
        return "foo/index";
    }
复制代码

测试运行结果如下:

集合类型基本都一样,set也差不多,问题是如果为了获得一个集合需要刻意去包装会很麻烦,可以通过@RequestParam结合@RequestBody等注解完成。

1.2、@RequestParam参数绑定

简单的参数可以使用上一节中讲过的自动参数映射,复杂一些的需使用@RequestParam完成,虽然自动参数映射很方便,但有些细节是不能处理的,如参数是否为必须参数,名称没有办法指定,参数的默认值就没有有办法做到了。如果使用@RequestParam可以实现请求参数绑定,Spring MVC会自动查找请求中的参数转类型并将与参数进行绑定,示例代码如下:

1.2.1、基本数据类型绑定与注解属性

复制代码
package com.zhangguo.springmvc03.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/foo")
public class FooController {
    @RequestMapping("/action1")
    public String action1(Model model, @RequestParam(required = false, defaultValue = "99") int id) {
        model.addAttribute("message", id);
        return "foo/index";
    }
}
复制代码

@RequestParam共有4个注解属性,required属性表示是否为必须,默认值为true,如果请求中没有指定的参数会报异常;defaultValue用于设置参数的默认值,如果不指定值则使用默认值,只能是String类型的。name与value互为别名关系用于指定参数名称。

运行结果:

1.2.2、List与数组绑定基本数据类型

在上一节中我们使用自动参数映射是不能直接完成List与数组绑定的,结合@RequestParam可以轻松实现,示例代码如下所示:

复制代码
    // List集合与数组类型
    @RequestMapping("/action05")
    public String action05(Model model, @RequestParam("u") List<String> users) {
        model.addAttribute("message", users.get(0) + "," + users.get(1));
        return "foo/index";
    }
复制代码

运行结果:

直接在URL中输入测试数据可以绑定成功,使用表单同样可行,页面脚本如下:

复制代码
<form action="bar/action11" method="post">
    <p>
        <label>爱好:</label> 
        <input type="checkbox" value="15" name="id" />阅读
         <input type="checkbox" value="20" name="id" />上网
         <input type="checkbox" value="73" name="id" />电游
    </p>
    <button>提交</button>
</form>
复制代码

请求处理方法action代码如下:

复制代码
    // List与数组绑定基本数据类型
    @RequestMapping("/action11")
    public String action11(Model model, @RequestParam("id") List<Integer> ids) {
        model.addAttribute("message", Arrays.deepToString(ids.toArray()));
        return "bar/index";
    }
复制代码

运行结果:

@RequestParam("id")是必须的,因为页面中的表单name的名称为id,所有服务器在收集数据时应该使用id页非ids,如果同名则可以省去。

1.2.3、List与数组直接绑定自定义数据类型与AJAX

上一小节中我们绑定的集合中存放的只是基本数据类型,如果需要直接绑定更加复杂的数据类型则需要使用@RequestBody与@ResponseBody注解了,先解释一下他们的作用:

@RequestBody 将HTTP请求正文转换为适合的HttpMessageConverter对象。
@ResponseBody 将内容或对象作为 HTTP 响应正文返回,并调用适合HttpMessageConverter的Adapter转换对象,写入输出流。

AnnotationMethodHandlerAdapter将会初始化7个转换器,可以通过调用AnnotationMethodHandlerAdapter的getMessageConverts()方法来获取转换器的一个集合 List<HttpMessageConverter>,7个转换器类型分别是

ByteArrayHttpMessageConverter 
StringHttpMessageConverter 
ResourceHttpMessageConverter 
SourceHttpMessageConverter 
XmlAwareFormHttpMessageConverter 
Jaxb2RootElementHttpMessageConverter 
MappingJacksonHttpMessageConverter

@RequestBody默认接收的Content-Type是application/json,因此发送POST请求时需要设置请求报文头信息,否则Spring MVC在解析集合请求参数时不会自动的转换成JSON数据再解析成相应的集合,Spring默认的json协议解析由Jackson完成。要完成这个功能还需要修改配置环境,具体要求如下:

a)、修改Spring MVC配置文件,启用mvc注解驱动功能,<mvc:annotation-driven />

b)、pom.xml,添加jackson依赖,添加依赖的配置内容如下:

复制代码
    <!-- jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.2</version>
    </dependency>
复制代码

c)、ajax请求时需要设置属性dataType 为 json,contentType 为 'application/json;charse=UTF-8',data 转换成JSON字符串,如果条件不满足有可能会出现415异常。

Action定义的示例代码如下:

复制代码
    // List与数组直接绑定自定义数据类型与AJAX
    @RequestMapping("/action21")
    public void action21(@RequestBody List<Product> products, HttpServletResponse response) throws IOException {
        response.setCharacterEncoding("UTF-8");
        System.out.println(Arrays.deepToString(products.toArray()));
        response.getWriter().write("添加成功");
    }
复制代码

action21的参数@RequestBody List<Product> products是接收从客户端发送到服务器的产品集合,默认的请求内容并非是application/json,而是:application/x-www-form-urlencoded,在参数前增加@RequestBody的作用是让Spring MVC在收到客户端请求时将选择合适的转换器将参数转换成相应的对象。action22的返回值为List<Product>,且在方法上有一个注解@ResponseBody,系统会使用jackson将该对象自动序列化成json字符;在客户端请求时设置内容类型为application/json,定义一个myform21.jsp页面,页面的脚本如下所示:

复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>List与数组直接绑定自定义数据类型与AJAX</title>
</head>
<body>
    <button type="button" onclick="addPdts_click1();">向服务器发送json</button>
    <button type="button" onclick="addPdts_click2();">接收服务器返回的json</button>
    <p id="msg"></p>
    <script type="text/javascript"
        src="<c:url value="/scripts/jQuery1.11.3/jquery-1.11.3.min.js"/>"></script>
    <script type="text/javascript">
        var products = new Array();
        products.push({
            id : 1,
            name : "iPhone 6 Plus",
            price : 4987.5
        });
        products.push({
            id : 2,
            name : "iPhone 7 Plus",
            price : 5987.5
        });
        products.push({
            id : 3,
            name : "iPhone 8 Plus",
            price : 6987.5
        });
        function addPdts_click1() {
            $.ajax({
                type : "POST",
                //请求谓词类型
                url : "bar/action21",
                data : JSON.stringify(products), //将products对象转换成json字符串
                contentType : "application/json;charset=UTF-8",
                //发送信息至服务器时内容编码类型,(默认: "application/x-www-form-urlencoded")
                dataType : "text", //预期服务器返回的数据类型
                success : function(result) {
                    $("#msg").html(result);
                }
            });
        }
        function addPdts_click2() {
            $.ajax({
                type : "POST",
                //请求谓词类型
                url : "bar/action22",
                data : JSON.stringify(products), //将products对象转换成json字符串
                contentType : "application/json;charset=UTF-8",
                //发送信息至服务器时内容编码类型,(默认: "application/x-www-form-urlencoded")
                dataType : "json", //预期服务器返回的数据类型
                success : function(result) {
                    var str = "";
                    $.each(result, function(i, obj) {
                        str += "编号:" + obj.id + ",名称:" + obj.name + ",价格:"+ obj.price + "<br/>";
                    });
                    $("#msg").html(str);
                }
            });
        }
    </script>
</body>
</html>
复制代码

页面中有两个方法,第一个方法是实现将一个json集合发送到服务器并映射成一个List集合;第二个方法是实现接收服务器返回的json对象。

点击按钮1时的运行结果如下:

控制台输出:

[编号(id):1,名称(name):iPhone 6 Plus,价格(price):4987.5, 编号(id):2,名称(name):iPhone 7 Plus,价格(price):5987.5, 编号(id):3,名称(name):iPhone 8 Plus,价格(price):6987.5]

点击按钮2时的运行结果如下:

1.3、重定向与Flash属性

在一个请求处理方法Action中如果返回结果为“index”字符则表示转发到视图index,有时候我们需要重定向,则可以在返回的结果前加上一个前缀“redirect:”,可以重定向到一个指定的页面也可以是另一个action,示例代码如下:

复制代码
    // 重定向
    @RequestMapping("/action2")
    public String action2(Model model) {
        return "foo/index";
    }

    @RequestMapping("/action3")
    public String action3(Model model) {
        model.addAttribute("message", "action3Message");
        return "redirect:action2";
    }
复制代码

当请求http://localhost:8087/SpringMVC02/foo/action3时运行结果如下:

在action3中返回的结果为redirect:action2,则表示重定向到action2这个请求处理方法,所有重定向都是以当前路径为起点的,请注意路径。在action3向model中添加了名称message的数据,因为重定向到action2中会发起2次请求,为了保持action3中的数据Spring MVC自动将数据重写到了url中。为了实现重定向时传递复杂数据,可以使用Flash属性,示例代码如下:

复制代码
    // 接收重定向参数
    @RequestMapping("/action2")
    public String action2(Model model, Product product) {
        model.addAttribute("message", product);
        System.out.println(model.containsAttribute("product")); // true
        return "foo/index";
    } 

//重定向属性 @RequestMapping("/action3") public String action3(Model model, RedirectAttributes redirectAttributes) { Product product = new Product(2, "iPhone7 Plus", 6989.5); redirectAttributes.addFlashAttribute("product", product); return "redirect:action2"; }
复制代码

当访问action3时,首先创建了一个product产口对象,将该对象添加到了Flash属性中,在重定向后取出,个人猜测应该暂时将对象存入了Session中。当请求foo/action3时运行结果如下:

url地址已经发生了变化,product对象其实也已经被存入了model中,在action的视图中可以直接拿到。

 1.4、@ModelAttribute模型特性

@ModelAttribute可以应用在方法参数上或方法上,他的作用主要是当注解在方法中时会将注解的参数对象添加到Model中;当注解在请求处理方法Action上时会将该方法变成一个非请求处理的方法,但其它Action被调用时会首先调用该方法。

1.4.1、注解在参数上

当注解在参数上时会将被注解的参数添加到Model中,并默认完成自动数据绑定,示例代码如下:

 

复制代码
    @RequestMapping("/action6")
    public String action6(Model model, @ModelAttribute(name = "product", binding = true) Product entity) {
        model.addAttribute("message", model.containsAttribute("product") + "<br/>" + entity);
        return "foo/index";
    }
复制代码

 

运行结果:

其实不使用@ModelAttribute我也样可以完成参数与对象间的自支映射,但使用注解可以设置更多详细内容,如名称,是否绑定等。

1.4.2、注解在方法上

用于标注一个非请求处理方法,通俗说就是一个非Action,普通方法。如果一个控制器类有多个请求处理方法,以及一个有@ModelAttribute注解的方法,则在调用其它Action时会先调用非请求处理的Action,示例代码如下:

 

复制代码
    @RequestMapping("/action7")
    public String action7(Model model) {
        Map<String, Object> map = model.asMap();
        for (String key : map.keySet()) {
            System.out.println(key + ":" + map.get(key));
        }
        return "foo/index";
    }

    @ModelAttribute
    public String noaction() {
        System.out.println("noaction 方法被调用!");
        String message = "来自noaction方法的信息";
        return message;
    }
复制代码

 

当访问http://localhost:8087/SpringMVC03/foo/action7时,控制台显示结果如下:

非请求处理方法可以返回void,也可以返回一个任意对象,该对象会被自动添加到每一个要被访问的Action的Model中,key从示例中可以看出为类型名称。

二、Action返回值类型

ModelAndView
Model
Map 包含模型的属性
View
String 视图名称
void
HttpServletResponse
HttpEntity<?>或ResponseEntity<?>
HttpHeaders
Callable<?>
DeferredResult<?>
ListenableFuture<?>
ResponseBodyEmitter
SseEmitter
StreamingResponseBody
其它任意类型,Spring将其视作输出给View的对象模型

2.1、视图中url问题

新增一个action5,代码如下:

    @RequestMapping("/action5")
    public String action5(Model model) {
        return "foo/action5";
    }

在foo目录下添加视图action5.jsp,内容如下:

复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>action5的视图</title>
</head>
<body>
    <img alt="风景" src="../../images/3.jpg">
</body>
</html>
复制代码

目标结构如下:

访问结果:

这里图片访问不到的原因是因为:action5.jsp视图此时并非以它所在的目录为实际路径,他是以当前action所在的控制器为起始目录的,当前控制器的url为:http://localhost:8087/SpringMVC02/foo/,而图片的src为:../../images/3.jpg,向上2级后变成:http://localhost:8087/images/3.jpg,但我们的项目实际路径中并没有存放3.jpg这张图片,解决的办法是在视图中使用“绝对”路径;另外一个问题是我们将静态资源存放到WEB-INF下不太合理,因为该目录禁止客户端访问,修改后的视图如下:

复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>action5的视图</title>
</head>
<body>
    <img alt="风景" src="<c:url value="/images/3.jpg"></c:url>">
</body>
</html>
复制代码

目录结构变化后如下所示:

 

运行结果:

小结:主要是借助了标签<c:url value="/images/3.jpg"></c:url>,将路径转换成“绝对路径”;建议在引用外部资源如js、css、图片信息时都使用该标签解析路径。

2.2、返回值为String

2.2.1、String作为视图名称

默认如果action返回String,此时的String为视图名称,会去视图解析器的设定的目录下查找,查找的规则是:URL= prefix前缀+视图名称 +suffix后缀组成,示例代码如下:

复制代码
    //返回值为String
    @RequestMapping("/action31")
    public String action31(Model model)
    {
        model.addAttribute("message","action31");
        return "bar/action31";
    }
复制代码

Spring MVC的配置文件内容如下:

复制代码
    <!-- 视图解析器 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/views/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>
复制代码

实际url=/WEB-INF/views/bar/action31.jsp

2.2.2、String作为内容输出

如果方法声明了注解@ResponseBody ,将内容或对象作为 HTTP 响应正文返回,并调用适合HttpMessageConverter的Adapter转换对象,写入输出流。些时的String不再是路径而是内容,示例脚本如下:

复制代码
    @RequestMapping("/action32")
    @ResponseBody
    public String action32()
    {
        return "not <b>path</b>,but <b>content</b>";
    }
复制代码

测试运行结果:

2.3、返回值为void

void在普通方法中是没有返回值的意思,但作为请求处理方法并非这样,存在如下两种情况:

2.3.1、方法名默认作为视图名

当方法没有返回值时,方法中并未指定视图的名称,则默认视图的名称为方法名,如下代码所示:

    @RequestMapping("/action33")
    public void action33()
    {
    }

直接会去访问的路径是:url=/WEB-INF/views/bar/action33.jsp,bar是当前控制器映射的路径,action33是方法名,上面的代码等同于:

复制代码
    @RequestMapping("/action33")
    public String action33()
    {
        return "bar/action33";  //bar是控制器的路径
    }
复制代码

可见URL= prefix前缀+控制器路径+方法名称 +suffix后缀组成。

2.3.2、直接响应输出结果

当方法的返回值为void,但输出流中存在输出内容时,则不会去查找视图,而是将输入流中的内容直接响应到客户端,响应的内容类型是纯文本,如下代码所示:

复制代码
    @RequestMapping("/action34")
    public void action34(HttpServletResponse response) throws IOException
    {
        response.getWriter().write("<h2>void method</h2>");
    }
复制代码

运行结果如下:

 可以看到h2标签并未渲染成标题。

2.4、返回值为ModelAndView

 在旧的Spring MVC中ModelAndView使用频率非常高,它可以同时指定须返回的模型与视图对象或名称,示例代码如下:

复制代码
    @RequestMapping("/action35")
    public ModelAndView action35() 
    {
        //1只指定视图
        //return new ModelAndView("/bar/index");
        
        //2分别指定视图与模型
        //Map<String, Object> model=new HashMap<String,Object>();
        //model.put("message", "ModelAndView action35");
        //return new ModelAndView("/bar/index",model);
        
        //3同时指定视图与模型
        //return new ModelAndView("/bar/index","message","action35 ModelAndView ");
        
        //4分开指定视图与模型
        ModelAndView modelAndView=new ModelAndView();
        //指定视图名称
        modelAndView.setViewName("/bar/index");
        //添加模型中的对象
        modelAndView.addObject("message", "<h2>Hello ModelAndView</h2>");
        return modelAndView;
    }
复制代码

ModelAndView有个多构造方法重载,单独设置属性也很方便,运行结果如下:

2.5、返回值为Map

当返回结果为Map时,相当于只是返回了Model,并未指定具体的视图,返回视图的办法与void是一样的,即URL= prefix前缀+控制器路径+方法名称 +suffix后缀组成,示例代码如下:

复制代码
    @RequestMapping("/action36")
    public Map<String, Object> action36()
    {
        Map<String, Object> model=new HashMap<String,Object>();
        model.put("message", "Hello Map");
        model.put("other", "more item");
        return model;
    }
复制代码

 

实际访问的路径是:/SpringMVC03/WEB-INF/views/bar/action36.jsp,返回给客户端的map相当于模型,在视图中可以取出。

2.6、返回值为任意类型

 2.6.1、返回值为基本数据类型

当返回结果直接为int,double,boolean等基本数据类型时的状态,测试代码如下:

复制代码
    @RequestMapping("/action37")
    public Integer action37()
    {
        return 9527;
    }
复制代码

测试运行的结果是:exception is java.lang.IllegalArgumentException: Unknown return value type异常。

如果确实需要直接将基本数据类型返回,则可以使用注解@ReponseBody。

复制代码
    @RequestMapping("/action38")
    @ResponseBody
    public int action38()
    {
        return 9527;
    }
复制代码

运行结果:

2.6.2、当返值为自定义类型

当返回值为自定义类型时Spring会把方法认为是视图名称,与返回值为void的类似办法处理URL,但页面中获得数据比较麻烦,示例代码如下:

复制代码
    @RequestMapping("/action39")
    public Product action39()
    {
        return new Product(1,"iPhone",1980.5);
    }
复制代码

如果存在action39对应的视图,页面还是可以正常显示。

如果在action上添加@ResponseBody注解则返回的是Product本身,而非视图,Spring会选择一个合适的方式解析对象,默认是json。示例代码如下:

复制代码
    @RequestMapping("/action39")
    @ResponseBody
    public Product action39()
    {
        return new Product(1,"iPhone",1980.5);
    }
复制代码

运行结果:

 

如果是接收json值,则需要使用注解@RequestBody指定在相应参数上。

2.7、返回值为Model类型

 该接口Model定义在包org.springframework.ui下,model对象会用于页面渲染,视图路径使用方法名,与void类似。示例代码如下:

复制代码
    @RequestMapping("/action40")
    public Model action40(Model model)
    {
        model.addAttribute("message", "返回类型为org.springframework.ui.Model");
        return model;
    }
复制代码

运行结果:

 

返回的类型还有许多如view等,通过view可指定一个具体的视图,如下载Excel、Pdf文档,其实它们也修改http的头部信息,手动同样可以实现,如下代码所示:

复制代码
    @RequestMapping("/action41")
    @ResponseBody
    public String action41(HttpServletResponse response)
    {
        response.setHeader("Content-type","application/octet-stream");         
        response.setHeader("Content-Disposition","attachment; filename=table.xls");
        return "<table><tr><td>Hello</td><td>Excel</td></tr></table>";
    }
复制代码

运行结果:

2.8、小结

使用 String 作为请求处理方法的返回值类型是比较通用的方法,这样返回的逻辑视图名不会和请求 URL 绑定,具有很高的灵活性,而模型数据又可以通过Model控制。

使用void,map,Model时,返回对应的逻辑视图名称真实url为:prefix前缀+控制器路径+方法名 +suffix后缀组成。

使用String,ModelAndView返回视图名称可以不受请求的url绑定,ModelAndView可以设置返回的视图名称。

另外在非MVC中使用的许多办法在Action也可以使用。

三、示例下载

点击下载示例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 第一部分spring的核心 第1章开始spring之旅 1.1spring是什么 1.2开始spring之旅 1.3理解依赖注入 1.3.1依赖注入 1.3.2di应用 1.3.3企业级应用中的依赖注入 1.4应用aop 1.4.1aop介绍 1.4.2aop使用 1.5小结 第2章基本bean装配 2.1容纳你的bean 2.1.1beanfactory介绍 2.1.2使用应用上下文 2.1.3bean的生命 2.2创建bean 2.2.1声明一个简单的bean 2.2.2通过构造函数注入 2.3注入bean属性 2.3.1注入简单的数值 2.3.2使用其他的bean 2.3.3装配集合 2.3.4装配空值 2.4自动装配 2.4.1四种自动装配类型 2.4.2混合使用自动和手动装配 2.4.3何时采用自动装配 2.5控制bean创建 2.5.1bean范围化 2.5.2利用工厂方法来创建bean 2.5.3初始化和销毁bean 2.6小结 第3章高级bean装配 3.1声明父bean和子bean 3.1.1抽象基bean类型 3.1.2抽象共同属性 3.2方法注入 3.2.1基本的方法替换 3.2.2获取器注入 3.3注入非springbean 3.4注册自定义属性编辑器 3.5使用spring的特殊bean 3.5.1后处理bean 3.5.2bean工厂的后处理 3.5.3配置属性的外在化 3.5.4提取文本消息 3.5.5程序事件的解耦 3.5.6让bean了解容器 3.6脚本化的bean 3.6.1给椰子上lime 3.6.2脚本化bean 3.6.3注入脚本化bean的属性 3.6.4刷新脚本化bean 3.6.5编写内嵌的脚本化bean 3.7小结 第4章通知bean 4.1aop简介 4.1.1定义aop术语 4.1.2spring对aop的支持 4.2创建典型的spring切面 4.2.1创建通知 4.2.2定义切点和通知者 4.2.3使用proxyfactorybean 4.3自动代理 4.3.1为spring切面创建自动代理 4.3.2自动代理@aspectj切面 4.4定义纯粹的pojo切面 4.5注入aspectj切面 4.6小结 第二部分企业spring 第5章使用数据库 5.1spring的数据访问哲学 5.1.1了解spring数据访问的异常体系 5.1.2数据访问的模板化 5.1.3使用dao支持类 5.2配置数据源 5.2.1使用jndi数据源 5.2.2使用数据源连接池 5.2.3基于jdbc驱动的数据源 5.3在spring里使用jdbc 5.3.1处理失控的jdbc代码 5.3.2使用jdbc模板 5.3.3使用spring对jdbc的dao支持类 5.4在spring里集成hibernate 5.4.1选择hibernate的版本 5.4.2使用hibernate模板 5.4.3建立基于hibernate的dao 5.4.4使用hibernate3上下文会话 5.5spring和java持久api 5.5.1使用jpa模板 5.5.2创建一个实体管理器工厂 5.5.3建立使用jpa的dao 5.6spring和ibatis 5.6.1配置ibatis客户模板 5.6.2建立基于ibatis的dao 5.7缓存 5.7.1配置缓存方案 5.7.2缓存的代理bean 5.7.3注解驱动的缓存 5.8小结 第6章事务管理 6.1理解事务 6.1.1仅用4个词解释事务 6.1.2理解spring对事务管理的支持 6.2选择事务管理器 6.2.1jdbc事务 6.2.2hibernate事务 6.2.3jpa事务 6.2.4jdo事务 6.2.5jta事务 6.3在spring中编写事务 6.4声明式事务 6.4.1定义事务参数 6.4.2代理事务 6.4.3在spring2.0里声明事务 6.4.4定义注释驱动事务 6.5小结 第7章保护spring 7.1springsecurity介绍 7.2验证用户身份 7.2.1配置providermanager 7.2.2根据数据库验证身份 7.2.3根据ldap仓库进行身份验证 7.3控制访问 7.3.1访问决策投票 7.3.2决定如何投票 7.3.3处理投票弃权 7.4保护web应用程序 7.4.1代理springsecurity的过滤器 7.4.2处理安全上下文 7.4.3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值