SpringMVC 基础(二)

  • SpringMVC 基础 查看链接

一、AJAX

1.1 简介

  • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML);

  • AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术;

  • AJAX 不是一种新的编程语言,而是一种用于创建更好更快,以及交互性更强的 Web 应用程序的技术;

  • 在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来,Google Suggest 能够自动完成搜索单词;

  • Google Suggest 使用 AJAX 创造出动态性极强的 web 界面:当我们在谷歌的搜索框输入关键字时,JavaScript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表,如百度的搜索框:

  • 传统的网页(即不用 AJAX 技术的网页)想要更新内容或者提交一个表单,都需要重新加载整个网页;

  • 使用 AJAX 技术的网页,通过在后台服务器,进行少量的数据交换,就可以实现异步、局部更新;

  • 使用 AJAX,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的 Web 用户界面;

1.2 伪造 AJAX

  • 可以使用前端的一个标签,来伪造一个 ajax 的样子:iframe 标签

    • 新建模块,并导入 web 支持;
    • 配置 web.xml 及 springMVC 配置文件,运行 Tomcat 测试环境;
    • 编写 html 页面,使用 iframe 测试,感受下效果:
    
    
    
        
        iframe伪造ajax
        
    
    
    

    请输入要加载的地址:

    加载页面位置:

    • 使用 IDEA 打开浏览器进行测试;

小结:

  • 利用 AJAX 可以实现:
    • 注册时,输入用户名,自动检测用户是否已经存在;
    • 登陆时,提示用户名,密码错误;
    • 删除数据行时,将行 ID 发送到后台,后台在数据库中删除,数据库删除成功后,在页面 DOM 中,将数据行也删除;
    • ...等等;

1.3 jQuery.ajax

  • jQuery 3.6.0 开发版 下载链接
  • Ajax 的核心是 XMLHttpRequest 对象(XHR):
    • XHR 为向服务器发送请求和解析服务器响应,提供了接口,能够以异步方式,从服务器获取新数据;
  • jQuery 提供多个与 AJAX 有关的方法;
  • 通过 jQuery AJAX 方法,能够使用 HTTP Get 和 HTTP Post,从远程服务器上请求文本、HTML、XML 或 JSON,同时能够把这些外部数据,直接载入网页的被选元素中;
  • jQuery(是一个库) 不是生产者,而是大自然搬运工;
  • jQuery Ajax 本质就是 XMLHttpRequest,对它进行了封装,方便调用:
jQuery.ajax(...)
/*
    部分参数:
        url:请求地址
        type:请求方式,GET、POST(1.9.0之后用method)
        headers:请求头
        data:要发送的数据
        contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
        async:是否异步
        timeout:设置请求超时时间(毫秒)
        beforeSend:发送请求前执行的函数(全局)
        complete:完成之后执行的回调函数(全局)
        success:成功之后执行的回调函数(全局)
        error:失败之后执行的回调函数(全局)
        accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
        dataType:将服务器端返回的数据转换成指定类型
        "xml": 将服务器端返回的内容转换成xml格式
        "text": 将服务器端返回的内容转换成普通文本格式
        "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
        "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
        "json": 将服务器端返回的内容转换成相应的JavaScript对象
        "jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数
 */

测试一:HttpServletResponse 实现

  • 使用最原始的 HttpServletResponse 处理,最简单,最通用:
  • 配置 web.xml 和 springmvc 的配置文件:
    • 注意:静态资源过滤和注解驱动配置;


    
    
    
    
    
    
    
    
    
        
        
        
        
    

  • 创建 Controll:AjaxController
// 不走视图页面,直接返回字符串
@RestController
public class AjaxController {
@RequestMapping("/a1")
    public void ajax1(String name, HttpServletResponse response) throws IOException {
        System.out.println("前端传递参数:" + name);
        if ("admin".equals(name)) {
            response.getWriter().println("true");
        } else {
            response.getWriter().println("false");
        }
    }
}
  • 导入 jQuery,可以使用在线的 CDN,也可以下载导入:
<%----%>
    
  • 编写 index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    $Title$
    <%----%>
    
    


<%--onblur:失去焦点触发事件--%>
用户名:


  • 启动 Tomcat 测试:

    • 打开浏览器的控制台,当鼠标离开输入框时,可以看到发出了一个 ajax 的请求;
  • 流程分析:

测试二:SpringMVC、JSON 方式实现

  • 需要导入 Jackson 依赖:否则请求路径时,报错 406

    com.fasterxml.jackson.core
    jackson-databind
    2.13.2.2

  • 创建实体类:user
    • 使用 lombok,需要事先导入依赖;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private int age;
    private String sex;
}
  • 在 Controller 类中添加方法:
    • 获取一个集合对象,展示到前端页面;
@RequestMapping("/a2")
public List ajax2() {
    List list = new ArrayList<>();
    list.add(new User("test01", 20, "男"));
    list.add(new User("test02", 21, "女"));
    list.add(new User("test03", 20, "男"));
    // 类中使用@RestController注解,将list转成json格式返回
    return list;
}
  • 前端页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title
    <%--jQuery--%>
    
    



姓名 年龄 性别
  • 运行测试:

1.4 AJAX 注册提示

  • 在 Controller 类中,添加方法:
@RequestMapping("/a3")
public String ajax3(String name, String pwd) {
    String msg = "";
    if (name != null) {
        // admin:模拟数据库查询的数据
        if ("admin".equals(name)) {
            msg = "OK";
        } else {
            msg = "用户名有误";
        }
    }
    if (pwd != null) {
        // 123456:模拟数据库查询的数据
        if ("123456".equals(pwd)) {
            msg = "OK";
        } else {
            msg = "密码有误";
        }
    }
    // 类中使用@RestController注解,将msg转成json格式返回
    return msg;
}
  • 创建前端页面:login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    login
    
    


<%--onblur:失去焦点触发事件--%> 用户名:

密码:

  • 处理 JSON 乱码:SpringMVC 配置文件中进行配置


    
        
            
        
        
            
                
                    
                
            
        
    

  • 运行测试:

1.5 获取 baidu 接口 Demo




    
    JSONP百度搜索
    
    




二、拦截器

2.1 概述

  • SpringMVC 的处理器,拦截器,类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理,可以自定义拦截器,实现特定的功能;
  • 过滤器与拦截器的区别:拦截器是 AOP 思想的具体应用;
  • 过滤器
    • servlet 规范中的一部分,任何 Java web 工程都可以使用;
    • url-pattern 中配置了 /* 之后,可以对所有要访问的资源,进行拦截;
  • 拦截器
    • 拦截器是 SpringMVC 框架自有的,只有使用了 SpringMVC 框架的工程才能使用;
    • 拦截器只会拦截访问控制器方法,如果访问的是 jsp、html、css、image、js,是不会进行拦截的;

2.2 自定义拦截器

  • 要自定义拦截器,必须实现 HandlerInterceptor 接口;
  • 创建新模块,并添加 web 支持;
  • 配置 web.xml 和 springmvc 配置文件;
  • 创建拦截器:config 目录下,创建 MyInterceptor
public class MyInterceptor implements HandlerInterceptor {
    /*
        如果返回true执行下一个拦截器
        如果返回false就不执行下一个拦截器
     */
    // 在请求处理的方法之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("------------处理前------------");
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    // 在请求处理方法执行之后执行(一般用于处理日志)
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("------------处理后------------");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    // 在dispatcherServlet处理后执行,做清理工作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("------------清理------------");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
  • 在 SpringMVC 的配置文件中,配置拦截器:


    
        
        
        
        
    

  • 创建 Controller,接收请求:
@RestController
public class TestController {
    @RequestMapping("/interceptor")
    public String test2() {
        System.out.println("控制器中的方法执行了");
        return "hello";
}
  • 编写前端:index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    $Title$
  
  
  拦截器测试
  

  • 配置 Tomcat,启动测试:

2.3 验证用户是否登录 (认证用户)

实现思路:

  • 有一个登陆页面,需要写一个 controller 访问页面;
  • 登陆页面有一个提交表单的动作,需要在 controller 中处理,判断用户名、密码是否正确,如果正确,向 session 中写入用户信息,返回登陆成功信息;
  • 拦截用户请求,判断用户是否登陆,如果用户已经登陆,放行,如果用户未登陆,跳转到登陆页面;

测试:

  • 创建登陆页面:login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    首页


登录
成功页面


  • 创建 Controller 类,处理请求:
@Controller
@RequestMapping("/user")
public class LoginController {
    // 跳转到登录页面
    @RequestMapping("/toLogin")
    public String toLogin() {
        return "login";
    }

    // 跳转到成功页面
    @RequestMapping("/toSuccess")
    public String toSuccess() {
        return "success";
    }

    // 登陆提交
    @RequestMapping("/login")
    public String login(HttpSession session, String username, String pwd) {
        // 把用户的信息存在Session中
        session.setAttribute("user", username);
        return "success";
    }

    // 退出登陆
    @RequestMapping("/logout")
    public String logout(HttpSession session) {
        // 移除Session
        session.removeAttribute("user");
        // 手动注销Session
        // session.invalidate();
        return "login";
    }
}
  • 创建登陆成功的页面:success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    登录成功


登录成功页面


${user} 注销
  • 在 index 页面上测试跳转,启动 Tomcat 测试,未登录也可以进入主页:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    首页


登录
成功页面


  • 创建登录拦截器:
public class LoginInterceptor implements HandlerInterceptor {
    // 在请求处理的方法之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果是登陆页面则放行
        if (request.getRequestURI().contains("toLogin")) {
            return true;
        }
        if (request.getRequestURI().contains("login")) {
            return true;
        }

        HttpSession session = request.getSession();

        // 如果用户已登陆也放行
        if (session.getAttribute("user") != null) {
            return true;
        }

        // 用户没有登陆跳转到登陆页面
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false;
    }
}
  • 在 SpringMVC 的配置文件中,注册拦截器:


            
        
                
        
    

  • 再次重启 Tomcat 测试,可以实现登录拦截功能;

三、文件上传和下载

3.1 概述

  • 文件上传是项目开发中最常见的功能之一,springMVC 可以很好的支持文件上传,但是 SpringMVC 上下文中,默认没有装配 MultipartResolver,因此,默认情况下,不能处理文件上传工作;
  • 如果想使用 Spring 的文件上传功能,则需要在上下文中配置MultipartResolver;
  • 前端表单要求:为了能上传文件,必须将表单的 method 设置为 POST,并将 enctype 设置为 multipart/form-data,只有在这样的情况下,浏览器才会把用户选择的文件,以二进制数据发送给服务器;
  • 表单中的 enctype 属性说明:
    • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单,会将表单域中的值处理成 URL 编码方式;
    • multipart/form-data:以二进制流的方式,来处理表单数据,这种编码方式,会把文件域指定文件的内容,也封装到请求参数中,不会对字符编码;
    • text/plain:除了把空格转换为 + 号外,其他字符都不做编码处理,这种方式适用 直接通过表单发送邮件

  • 一旦设置了enctype 为 multipart/form-data,浏览器即会采用二进制流的方式,来处理表单数据,而对于文件上传的处理,则涉及在服务器端解析原始的 HTTP 响应;
  • 在 2003 年,Apache Software Foundation 发布了开源的 Commons FileUpload 组件,很快成为 Servlet/JSP 程序员上传文件的最佳选择;
    • Servlet3.0 规范已经提供方法来处理文件上传,但这种上传需要在 Servlet 中完成;
    • Spring MVC 提供了更简单的封装;
    • Spring MVC 为文件上传,提供了直接的支持,这种支持是用 即插即用 的 MultipartResolver 实现的;
    • Spring MVC 使用 Apache Commons FileUpload 技术实现了一个 MultipartResolver 实现类 CommonsMultipartResolver 因此,SpringMVC 的文件上传,还需要依赖 Apache Commons FileUpload 的组件

3.2 文件上传

  • 创建新模块,并添加 web 框架支持;
  • 配置 web.xml 及 SpringMVC 配置文件;
  • 配置 Tomcat,启动测试环境;
  • 导入文件上传的 jar 包,commons-fileupload 或 Maven 依赖:


    commons-fileupload
    commons-fileupload
    1.4



    javax.servlet
    javax.servlet-api
    4.0.1

  • 在 SpringMVC 配置文件中配置 bean:multipartResolver
    • id 必须为:multipartResolver,否则报400错误


    
    
    
    
    

  • CommonsMultipartFile 的常用方法:
    • String getOriginalFilename():获取上传文件的原名;
    • InputStream getInputStream():获取文件流;
    • void transferTo(File dest):将上传文件,保存到一个目录文件中;
  • 编写前端页面:index.jsp
  • 创建 Controller 类:FileController

上传方式一:

@Controller
public class FileController {
    // 上传方式 1:
    // @RequestParam("file"):将name=file控件得到的文件封装成CommonsMultipartFile对象
    // 批量上传,CommonsMultipartFile则为数组即可
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        // 获取文件名:file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();
        // 如果文件名为空,直接回到首页!
        if ("".equals(uploadFileName)) {
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名 : " + uploadFileName);
        // 上传路径保存设置
        String path = request.getServletContext().getRealPath("/upload");
        // 如果路径不存在,创建一个
        File realPath = new File(path);
        if (!realPath.exists()) {
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:" + realPath);
        // 文件输入流
        InputStream is = file.getInputStream();
        // 文件输出流
        OutputStream os = new FileOutputStream(new File(realPath, uploadFileName));
        // 读取写出
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }
}
  • 测试上传文件;

上传方式二:

  • 采用 file.transferTo 来保存上传的文件;
  • 在 FileController 类中添加方法:
/*
    上传方式 2:
    采用file.transferTo来保存上传的文件
 */
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file,
                          HttpServletRequest request) throws IOException {
    // 上传路径保存设置
    String path = request.getServletContext().getRealPath("/upload");
    File realPath = new File(path);
    if (!realPath.exists()) {
        realPath.mkdir();
    }
    // 上传文件地址
    System.out.println("上传文件保存地址:" + realPath);
    // 通过CommonsMultipartFile的方法直接写文件(注意这个时候)
    file.transferTo(new File(realPath + "/" +
            file.getOriginalFilename()));
    return "redirect:/index.jsp";
}
  • 修改前端表单提交地址;
  • 运行测试;

3.3 文件下载

  • 文件下载步骤:

    • 设置 response 响应头;
    • 读取文件:InputStream;
    • 写出文件:OutputStream;
    • 执行操作;
    • 关闭流(先开后关);
  • 代码实现:

// 文件下载
@RequestMapping("/download")
public String downloads(HttpServletResponse response, HttpServletRequest request) throws Exception {
    // 要下载的图片地址
    String path = request.getServletContext().getRealPath("/upload");
    String fileName = "1.png";
    // 1. 设置response 响应头
    // 设置页面不缓存,清空buffer
    response.reset();
    // 字符编码
    response.setCharacterEncoding("UTF-8");
    // 二进制传输数据
    response.setContentType("multipart/form-data");
    // 设置响应头
    response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
    File file = new File(path, fileName);

    // 2. 读取文件:输入流
    InputStream input = new FileInputStream(file);

    // 3. 写出文件:输出流
    OutputStream out = response.getOutputStream();
    byte[] buff = new byte[1024];
    int index = 0;

    // 4. 执行写出操作
    while ((index = input.read(buff)) != -1) {
        out.write(buff, 0, index);
        out.flush();
    }
    out.close();
    input.close();
    return null;
}
  • 创建对应目录及需要下载的文件:

  • 对应前端页面:

点击下载
  • 运行测试;

四、SSM 回顾

你可能感兴趣的:(SpringMVC 基础(二))