SpringMVC框架入门20-41:返回值的处理

课程链接:SpringMVC教程

开始时间:2022-01-23

RequestParam注解

实际开发过程中,请求参数名和处理器方法的形参名可能不一样
比如一个是前端工程师写的,提交的参数名和我们写的不一样,这个时候需要用RequestParam注解来统一。

例如index.jsp中写

<p>请求参数名和处理器方法的形参名不一样p>
<form action="receiveparam.do" method="post">
    姓名:<input type="text" name="rname"> <br/>
    年龄:<input type="text" name="rage"> <br/>
    <input type="submit" value="提交参数">
form>

在MyController里面进行处理
使用注解
@RequestParam(value=“传进来的参数名”,required=false) String “自己定义后面用的参数名”

required默认是true,代表着传参的时候必须有值,没有就报错

    @RequestMapping(value = "/receiveparam.do")
    public ModelAndView receiveParam(@RequestParam(value = "rname",required = false) String name,
                                     @RequestParam(value = "rage",required = false) Integer age){
        System.out.println("doSome, name="+name+"   age="+age);
        //可以在方法中直接使用 name , age
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",name);
        mv.addObject("myage",age);
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    }

还可以用对象来接收参数最常用
保存参数值到对象里面
属性名和请求名要一致

    /**
     * 处理器方法形参是java对象, 这个对象的属性名和请求中参数名一样的
     * 框架会创建形参的java对象, 给属性赋值。 请求中的参数是name,框架会调用setName()
     * @return
     */
    @RequestMapping(value = "/receiveobject.do")
    public ModelAndView receiveParam( Student myStudent){
        System.out.println("receiveParam, name="+myStudent.getName()+"   age="+myStudent.getAge());
        //可以在方法中直接使用 name , age
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",myStudent.getName());
        mv.addObject("myage",myStudent.getAge());
        mv.addObject("mystudent",myStudent);
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    }
<p>使用java对象接收请求参数p>
<form action="receiveobject.do" method="post">
    姓名:<input type="text" name="name"> <br/>
    年龄:<input type="text" name="age"> <br/>
    <input type="submit" value="提交参数">
form>

处理器方法的返回值

使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:
➢ 第一种: ModelAndView(既要跳转又需要传递数据才用)
➢ 第二种: String
➢ 第三种:无返回值 void
➢ 第四种:返回自定义类型对象

返回String

    @RequestMapping(value = "/returnString-view.do")
    public String doReturnView(HttpServletRequest request, String name, Integer age) {
        System.out.println("doReturnView, name=" + name + "   age=" + age);
        //可以自己手工添加数据到request作用域,这样功能就和ModelAndView重合了
        request.setAttribute("myname", name);
        request.setAttribute("myage", age);

        // show : 逻辑视图名称,项目中配置了视图解析器
        // 框架对视图执行forward转发操作
        return "show";
    }

完整视图路径,项目中不能配置视图解析器,需要把解析器注释掉

   @RequestMapping(value = "/returnString-view2.do")
    public String doReturnView2(HttpServletRequest request,String name, Integer age){
        System.out.println("===doReturnView2====, name="+name+"   age="+age);
        //可以自己手工添加数据到request作用域
        request.setAttribute("myname",name);
        request.setAttribute("myage",age);
      
        // 框架对视图执行forward转发操作
        
        
        return "/WEB-INF/view/show.jsp";
    }

返回Object

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

返回对象,需要使用@ResponseBody 注解, 将转换后的 JSON 数据放入到响应体中。
判断是返回值是否是返回逻辑视图,就看有没有@ResponseBody 注解
现在做ajax, 主要使用json的数据格式。 实现步骤三步

  • 加入处理json的工具库的依赖,springmvc默认使用的jackson。
  • 在sprigmvc配置文件之间加入 注解驱动。注解驱动实现的功能是 完成java对象到json,xml, text,二进制等数据格式的转换。
    在加入到springmvc配置文件后, 会自动创建HttpMessageConverter接口
    的7个实现类对象,不加的话处理不了json

HttpMessageConverter接口:消息转换器。
功能:定义了java转为json,xml等数据格式的方法。 这个接口有很多的实现类。
这些实现类完成 java对象到json, java对象到xml,java对象到二进制数据的转换

//不一定用json,这里以json为例
json  = om.writeValueAsString(student);
  • 在处理器方法的上面加入@ResponseBody注解
response.setContentType("application/json;charset=utf-8");
PrintWriter pw  = response.getWriter();
pw.println(json);

来看看示例

写MyController

     * 处理器方法返回一个Student,通过框架转为json,响应ajax请求
     *
     * @ResponseBody: 作用:把处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器。
     * 位置:方法的定义上面。 和其它注解没有顺序的关系。

    /**

     */
    @RequestMapping(value = "/returnStudentJson.do")

    //需要加这个注解 ResponseBody
    @ResponseBody
    public Student doStudentJsonObject(String name, Integer age) {
        //调用service,获取请求结果数据 , Student对象表示结果数据
        Student student = new Student();
        student.setName("李四同学");
        student.setAge(20);
        return student; // 会被框架转为json
    }

在SpringMVC.xml中添加配置

    <mvc:annotation-driven/>

index.jsp中写js代码

<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.4.1.js"></script>
    <script type="text/javascript">
        $(function () {
            $("button").click(function () {
                //alert("button click");
                $.ajax({
                    url: "returnStudentJson.do",
                    data: {
                        name: "zhangsan",
                        age: 20
                    },
                    type: "post",
                    dataType: "json",

                    success: function (resp) {
                        alert(resp.name + " " + resp.age);
                    }

                })
            })
        })
    </script>
</head>

看看效果
SpringMVC框架入门20-41:返回值的处理_第1张图片

 * 返回对象框架的处理流程:
 * 1. 框架会把返回Student类型,调用框架的中ArrayList中每个类的canWrite()方法
 * 检查那个HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter
 * 2.框架会调用实现类的write(), MappingJackson2HttpMessageConverter的write()方法
 * 把李四同学的student对象转为json, 调用Jackson的ObjectMapper实现转为json
 * contentType: application/json;charset=utf-8(这些都不用自己写)
 * 3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成

SpringMVC框架入门20-41:返回值的处理_第2张图片
不需要写啦!!!

返回一个List集合

MyController

@RequestMapping(value = "/returnStudentJsonArray.do")

    //需要加这个注解 ResponseBody
    @ResponseBody
    public List<Student> doStudentJsonObjectArray(String name, Integer age) {
        List<Student> list = new ArrayList<>();
        Student student = new Student();
        student.setName("李四同学");
        student.setAge(20);
        list.add(student);

        student = new Student();
        student.setName("张三");
        student.setAge(28);
        list.add(student);
        return list;
    }

index.jsp中修改

    <script type="text/javascript">
        $(function () {
            $("button").click(function () {
                //alert("button click");
                $.ajax({
                    url: "returnStudentJsonArray.do",
                    data: {
                        name: "zhangsan",
                        age: 20
                    },
                    type: "post",
                    dataType: "json",

                    success: function (resp) {
                    //依次拿出变量
                        $.each(resp, function (i, n) {
                            // i是循环变量,n是数组中的对象
                            alert(n.name + " " + n.age)
                        })
                    }

                })
            })
        })
    script>

返回String文本类型

MyController

   @RequestMapping("/returnStringData.do")
    @ResponseBody
    public String doStringData(String name, Integer age) {
        return "Hello SpringMVC 返回对象,表示数据";
    }

然后我们发现此时传的数据不再是json了

 <script type="text/javascript">
        $(function () {
            $("button").click(function () {
                //alert("button click");
                $.ajax({
                    url: "returnStringData.do",
                    data: {
                        name: "zhangsan",
                        age: 20
                    },
                    type: "post",
                    dataType: "text",

                    success: function (resp) {
                        alert(resp)
                    }

                })
            })
        })
    </script>

如果这个dataType还是json,那么就根本不显示
但我们改为text,有了显示,但还是有乱码

这个乱码和过滤器处理的乱码不一样。
过滤器是处理 Tomcat把结果写入响应头不乱码

这里是把结果返回给浏览器,浏览器解码方法错了导致的

解决方法
在MyController方法上添加produces

@RequestMapping(value = "/returnStringData.do", produces = "text/plain;charset=utf-8")

处理请求分析

我们写了很多子程序,那么分别是交给谁来处理的?

程序 处理器
index.jsp Tomcat(jsp会转为servlet)
js/jquery-3.4.1.js Tomcat
静态图片.jpg Tomcat
test.html(静态页面) Tomcat
some.do DispatcherServlet(在web.xml中配置可以判断出)SpringMVC框架处理

Tomcat本身能处理静态资源的访问,html,图片,js都属于静态资源

Tomcat本身默认带了一个default的servlet,可以处理静态资源,也可以处理没有映射到其他servlet的请求。
比如我们配置了俩servlet,aservlet和bservlet,此时要访问一个c,我们没有配置,那就访问默认的default的servlet

我们现在回过来看配置的web.xml

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

使用斜杠的话,会代替Tomcat的default,把交给Tomcat的东西给拦截了
导致静态资源也交给dispatcherServlet处理,但是他能处理吗?他处理不了,他没那个能力你知道吧。
动态资源能处理,因为有MyController去处理。

那我们想解决这个问题,就可以考虑能不能让dispatcherServlet收到的请求再转发回Tomcat进行处理呢?
第一种方式
只需要在SpringMVC.xml配置文件中添加

<mvc:default-servlet-handler/>

== 第二种方式来配置==
可以在SpringMVC.xml文件中写上

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

这样也可以实现静态资源的访问
但是如果我们有很多静态资源,这样一个个写肯定不方便

所以一般把所有静态资源放到一个文件夹static里面
这样仅需要配置

    <mvc:resources mapping="/static/**" location="/static/"/>

绝对路径和相对路径

这里讨论了一下绝对路径和相对路径
相对路径中加斜杠的问题

首先来看情况1

Case 1

1) 在你的页面中的,访问地址不加 “/”

<a href="user/some.do">

访问的是: http://localhost:8080/ch06_path/index.jsp
路径: http://localhost:8080/ch06_path/ (注意,这里的ch06_path就是我们在Tomcat服务器发布的那个名称)
资源: index.jsp

在index.jsp发起 user/some.do请求,访问地址变为 http://localhost:8080/ch06_path/user/some.do
当你的地址 没有斜杠开头,例如 user/some.do , 当你点击链接时, 访问地址是
当前页面的地址 加上 链接的地址
http://localhost:8080/ch06_path/ + user/some.do

Case 2

在页面中的,访问地址加 “/”

<a href="/user/some.do">

访问的是: http://localhost:8080/ch06_path/index.jsp
路径: http://localhost:8080/ch06_path/
资源: index.jsp

点击 /user/some.do, 访问地址变为 http://localhost:8080/user/some.do
参考地址是 你的服务器地址, 也就是 http://localhost:8080

缺一个ch06_path
所以我们要解决的话,可以选择在href后面填上这一句
但是这样处理不够灵活

如果你的资源不能访问: 加入

${pageContext.request.contextPath}
<a href="${pageContext.request.contextPath}/user/some.do">发起user/some.do的get请求</a>

这样粗看有些麻烦,不如直接去掉斜杠,但是这样还是比较规范的,我们可以看到下面这种情况

index.jsp 访问 user/some.do , 返回后现在的地址: http://localhost:8080/ch06_path/user/some.do
这个很好理解
http://localhost:8080/ch06_path/user/some.do
路径: http://localhost:8080/ch06_path/user/
资源: some.do

在此之后,在index.jsp中 user/some.do ,就变为 http://localhost:8080/ch06_path/user/user/some.do
有两个user了,我们就没办法访问到想访问的页面了
因为我们上面说过

当你的地址 没有斜杠开头,例如 user/some.do , 当你点击链接时, 访问地址是
当前页面的地址 加上 链接的地址。 http://localhost:8080/ch06_path/ + user/some.do
在点击一次后,路径变为了
http://localhost:8080/ch06_path/user/

如果再次加上 链接的地址user/some.do,就出现了刚才的情况。

解决方案:
1.加入${pageContext.request.contextPath} (变成加斜杠的方式)
2.加入一个base标签, 是html语言中的标签。 表示当前页面中访问地址的基地址。
你的页面中所有 == 没有==“/”开头的地址,都是以base标签中的地址为参考地址
使用base中的地址 + user/some.do 组成访问地址

这样不管怎么跳转,还是以base地址为基础
我们这里不管加没加斜杠,都是相对地址,那么这个相对地址相对的是谁,就通过设置base把他固定下来
获取指定路径

<%
    String basePath = request.getScheme() + "://" +
            request.getServerName() + ":" + request.getServerPort() +
            request.getContextPath() + "/";
%>
<head>
    <title>Titletitle>
    <base href="<%=basePath%>" />
head>
<body>
     <p>第一个springmvc项目p>
     <p><a href="user/some.do">发起user/some.do的get请求a> p>
     <br/>
body>

string的四段分别是获取协议 服务器ip 端口号 以及访问路径的

此时链接上就没有第一个斜杠了
结束时间:2022-01-28

你可能感兴趣的:(锦到说SpringMVC,java,前端,restful)