Spring MVC总结 02

 

第1章 响应数据和结果视图

1.1 返回值分类

1.1.1 返回字符串

什么情况下用这种方式:(以后的开发基本上都是这样的开发方式)
开发思路:你发请求,我后台把数据查出来,我存到这个Model对象,它帮我存到request转发到页面,前端jsp从request域里面把值取出来。(以后即可用Model这个对象代替HttpServletRequest对象,达到简写的目的,再也不用像HttpServletRequest那么麻烦了...且使用Servlet原生API会时程序耦合很高,具体原因见:SpringMC 总结 01)

    @RequestMapping("/testString")
    public String testString(Model model) {
        System.out.println("execute testString()...");
        //模拟从数据库中查询出User对象
        User u = new User();
        u.setUsername("JTL");
        u.setPassword("123");
        u.setAge(17);
        model.addAttribute("user", u);
        return "success";
    }

前端界面:通过EL表达式从request域对象中取值

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h3>执行成功</h3>
${user.username}
${user.password}
${user.age}
</body>
</html>

1.1.2 返回值是void

    @RequestMapping("/testVoid")
    public void testVoid(Model model) {
        System.out.println("execute testVoid()...");
    }

默认情况它会去找这个路径下的与你请求路径同名的jsp文件:这样非常不好,因为你又的创建一个名为testVoid.jsp。(默认值)

正确方式:

p.s.区别:
请求转发:请求转发是一次请求,不用编写项目的名称。
重定向:重定向是两次请求,需要编写项目的名称。
注意:
1、你自己手动去调转发的方法,它不会再帮你去执行视图解析器。也就不会自动跳转到/WEB-INF目录下(自己配置的)去找jsp。需要你自己提供完整的目录,不会再使用视图解析器的对象(/称为组件)。
2、当你转发层写完,如果后面还有代码的话它会继续执行,如果你不想让后面代码执行,可手动加一个return;

方式1:请求转发

    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        System.out.println("execute testVoid()...");
        //编写请求转发的程序
        req.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(req, resp);
        return;
    }

方式2:重定向
1、通过request.getContextPath()获取到项目名称
2、重定向等于又发了一个新的请求,你直接发请求是不能直接请求/WEB-INF/pages里面的页面,/WEB-INF里面的东西不能直接请求,转发是可以的。你只能请求到/webapp根目录下的jsp如index.jsp

    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        System.out.println("execute testVoid()...");
        //重定向
        resp.sendRedirect(req.getContextPath()+"/index.jsp");
        return;
    }

方式3:直接会进行响应
说明:上面两种方式都是先跳到某个jsp(跳页面),最终由Tomcat服务器帮你生成html,最终帮你响应给用户。还有这样一种情况:你可能直接发请求,控制台/控制器直接通过输出流,把数据响应给浏览器。response.getWrite()拿到输出流。

    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        System.out.println("execute testVoid()...");
        // 解决响应中文乱码
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        //直接会进行响应
        resp.getWriter().print("你好!");
        return;
    }

1.1.3 返回值是ModelAndView对象

说明:由SpringMVC框架提供的一个对象。它也可以通过视图解析器帮你跳转到某个页面。与返回字符串那个方式的功能是一样的,查到一个JavaBean放到Model中然后返回给View视图;ModelAndView也可以存储JavaBean对象,也可存储你想往哪个页面作 跳转,与前面那个代码做的功能是一样的,只是写法有点不一样。且它底层也会把user对象存入到request域对象中,因为ModelAndView源码中就有ModelMap这个属性Model这个接口的实现类里就有:

特别注意:这种方式和反回字符串方式没什么区别,写法有点不一样而已。其实返回字符串这个方式,它的底层最终也会选择ModelAndView这个方式!底层源码还是用的ModelAndView这个类。

    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView() {
        System.out.println("execute testModelAndView()...");
        //创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        //模拟从数据库中查询出User对象
        User u = new User();
        u.setUsername("JT.L");
        u.setPassword("123");
        u.setAge(17);

        // 把user对象存储到mv对象中,它底层也会把user对象存入到request域对象中
        mv.addObject("user", u);
        // 跳转到哪个页面
        mv.setViewName("success");
        return mv;
    }

1.2 转发和重定向

还有一种写法(SpringMVC框架提供的转发和重定向),用一些关键字来表示转发和重定向,这个方式用的比较少,且当用关键字去做转发或重定向时,它是用不了视图解析器这个对象(组件)的。

1.2.1 forward请求转发

    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect() {
        System.out.println("execute testForwardOrRedirect()...");
        
        // 请求的转发
        return "forward:/WEB-INF/pages/success.jsp";
    }

说明:Controller方法在提供了String类型的返回值之后,默认就是请求转发。我们也可以像上面例子,使用forward关键字显式进行请求转发。但是,一旦用了forward:则路径必须写成实际视图url,不能写逻辑视图,因为它用不了视图解析器。它相当于requestl.getRequestDispathcher("url").forward(request,response)。使用请求转发,既可以转发到jsp,也可以转发到其他的控制器方法
补充,转发到其他控制器:

    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect() {
        System.out.println("execute testForwardOrRedirect()...");

        // 请求的转发
        return "forward:testModelAndView";
    }

说明:必须加上forward关键字,虽然Controller方法在提供了String类型的返回值之后,默认就是请求转发,但是你不加forward直接写其他控制器的RequestMapping如:testModelAndView是转发不成功的。

1.2.2 Redirect 重定向

说明:使用关键字的重定向,不需要像response.sendRedirect(url)方式通过request.getContextPath()加上项目名称。因为它底层帮你把项目名加上了,以后在用关键字作重定向的时候,不用再去加项目的名称,框架已经默认帮你加好了。

    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect() {
        System.out.println("execute testForwardOrRedirect()...");

        // 重定向
        return "redirect:/index.jsp";
    }

重定向也可以定向到其他控制器的方法:

    @RequestMapping("/testForwardOrRedirect")    
    public String testForwardOrRedirect() {
        System.out.println("execute testForwardOrRedirect()...");

        // 重定向到其他控制器方法
        return "redirect:testModelAndView";
    }

总结对比:

1、关键字+String返回类型:请求转发或重定向到jsp或其他控制器方法的对比

    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect() {
        System.out.println("execute testForwardOrRedirect()...");

        // 请求的转发
        // return "forward:/WEB-INF/pages/success.jsp";
        // 请求转发到其他控制器的方法
        // return "forward:testModelAndView";

        // 重定向
        // return "redirect:/index.jsp";
        // 重定向到其他控制器方法
        return "redirect:testModelAndView";
    }

2、返回值void类型:另一种方式请求转发或重定向到其他控制器方法:
(一)请求转发:

    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        System.out.println("execute testVoid()...");
        // 请求转发
        req.getRequestDispatcher("testModelAndView").forward(req,resp);
        return;
    }

(二)重定向:
   说明:重定向其他控制器方法也不需要写项目名称,但是到其他jsp一定要加上项目名称:

​
    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        System.out.println("execute testVoid()...");
        // 重定向 注意这里也不需要写项目名称
        resp.sendRedirect("testModelAndView");
        return;
    }

​

1.3 ResponseBody响应json数据

说明:之前都是用的转发或者重定向跳转到jsp再去作响应,可能有这样一个场景:页面发送一个ajax请求,明显是一个异步请求,那我的后台需要把一些对象转换成json的字符串,然后给你响应回去。如果有这样一个需求,那么用ResponseBody这个注解就可以完成这个事。

1、先搭建一个异步的环境。

1)引入jquery.min.js

2)存在的问题:在web.xml中配置了前端控制器,拦截了:/,意思就是任何资源都会被拦截到,在jsp中引入js文件其实它也会去请求服务器中对应的那个js文件,现在就存在这样一个问题:DispatcherServlet这个前端控制器会把这些静态的资源文件给拦截了。解决方式:告诉前端控制器这些静态资源(静态资源:js、css、图片)不要去拦截;在springmvc.xml文件中配置:
请求js文件截图:(被拦截了)


springmvc.xml中的配置:

    <!--告诉前端控制器,哪些静态资源不拦截-->
    <mvc:resources location="/js/" mapping="/js/**"/>

说明:location="/js/"  -- js文件夹下面的任何文件都可以不拦截
           mapping="/js/**" -- 跟你的映射请求是有关的,以后你请求路径带/js下面任何文件都会不会对它进行拦截,如:

在jsp中的请求:

    <script src="js/jquery.min.js"></script>

在浏览器中的表现:

补充其他的:

    <!-- 设置静态资源不过滤 -->
    <mvc:resources location="/css/" mapping="/css/**"/>  <!-- 样式 -->
    <mvc:resources location="/images/" mapping="/images/**"/>  <!-- 图片 -->
    <mvc:resources location="/js/" mapping="/js/**"/>  <!-- javascript -->

特别注意:

jsp中js路径的两种写法:

1)相对路径方式

<script src="js/jquery.min.js"></script>

2)这种写法记得把isELIgnored="false"设置上,因为用了EL表达式的$符号

<script src="${pageContext.request.contextPath}/js/jquery.min.js">

2、编写ajax请求

    <script>
        // 页面加载,绑定单击事件
        $(function () {
            //#btn id选择器
            $("#btn").click(function () {
                // alert("hello btn");
                // 发送ajax请求
                $.ajax({
                    // 编写json格式,设置属性和值
                    url:"user/testAjax",
                    //json的maime类型???
                    contentType:"application/json;charset=UTF-8",
                    // ''可以往里面再做嵌套 json键值对
                    data:'{"username":"JTL","password":"123","age":"17"}',
                    dataType:"json",
                    type:"post",
                    success:function (data) {
                        // data服务器端响应的json数据,进行解析
                        alert(data);// 会弹出一个对象,因为返回的是一个json的对象
                        // 解析这个对象 取属性
                        alert(data.username);
                        alert(data.password);
                        alert(data.age);
                    }
                })
            })
        })
    </script>

3、把发过来的json封装到一个JavaBean的对象当中

说明:这个事非常好做,SpringMVC的框架已经帮我们做好了。你发过来的是一串Json的字符串,我能拿到,如果你发的串的key值跟我JavaBean里面的属性名是相同的,那么框架可以帮你把串直接封装到对象当中。但是在做这个转换的时候,把这个key封装到对象的时候,需要用到以下Jar包。这个Jar的作用:把串转成对象;或者将对象转换成Json字符串。

        <!-- json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </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-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>

有了以上的Jar包之后,后端是直接能把前端传过来的Json数据封装到JavaBean对象当中去,它是一个自动的过程!只需要你加一个@RequestBody的注解即可。

    @RequestMapping("/testAjax")
    public void testAjax(@RequestBody User user) {
        System.out.println("execute testAjax()...");
        // 客户端发送ajax的请求,传的是json字符串,后端(自动)把json字符串封装到user对象中了
        System.out.println(user);
    }

控制台输出结果:

进一步编写Controller方法:
说明:
@RequestBody:接收的
@ResponseBody:响应的,返回(return user)的时候直接讲user对象转成一个json的字符串,转完了直接帮你响应

    @RequestMapping("/testAjax")
    public @ResponseBody User testAjax(@RequestBody User user) {
        System.out.println("execute testAjax()...");
        // 客户端发送ajax的请求,传的是json字符串,后端(自动)把json字符串封装到user对象中了(你只需要加一个@RequestBody注解)
        System.out.println(user);
        // 做响应,模拟查询数据库
        user.setUsername("JT.L");
        user.setAge(18);
        // 做响应(查出来跟数据库不一样) -- MVC框架已经把事全做好了,只需要返回一个User对象即可
        // 但是你返回的是一个对象,但是最终给前端的还是一个json数据,因为设置了返回的数据类型dataType:json
        // 反对象不行得把对象转成json,但也不用你自己转,只需要加一个@ResponseBody注解
        return user;
    }

总结:整个的发送请求获得响应的过程都完成了,这就是以后用异步发送json数据开发方式。

第2章 SpringMVC实现文件上传

2.1 文件上传的回顾

2.1.1 文件上传的必要前提

1、form表单的enctype取值必须是:multipart/form-data(指定传输数据为二进制数据,例如图片、mp3、文件。http请求中的multipart/form-data,会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。 既可以上传键值对,也可以上传文件)
默认值:application/x-www-form-urlencoded(会将表单内的数据转换为键值对)
2、method属性取值必须是post:如果是get会把你请求的东西放在地址栏上,地址栏的大小是有限制的,装不了多少数据;大数据的提交必须选post。
3、提供一个文件选择域<input type=”file” /> 

2.1.2 文件上传的原理分析

当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。
enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:key=value&key=value&key=value 
当form表单的enctype 取值为Mutilpart/form-data时,请求正文内容就变成:
每一部分都是 MIME 类型描述的正文,如下:

-----------------------------7de1a433602ac   分界符 
Content-Disposition: form-data; name="userName"  协议头 
  
aaa              协议的正文 
-----------------------------7de1a433602ac 
Content-Disposition: form-data; name="file"; 
filename="C:\Users\zhy\Desktop\fileupload_demofile\b.txt" 
Content-Type: text/plain         协议的类型(MIME 类型) 
 
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 
-----------------------------7de1a433602ac-- 

2.1.3 借助第三方组件实现文件上传

这些组件给我们提供了api,可以很方面的解析上传文件的请求体,不需要我们过于细节的去解析那个请求体(不需要我们知道请求体的格式也能正确解析)。这个组件是Apache提供的。

注:剩余内容见另一个博客

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值