Java 基础SpringMVC

SpringMVC 基础(二)

2022-04-12  本文已影响0人  yjtuuige

一、AJAX

1.1 简介

1.2 伪造 AJAX

小结:

1.3 jQuery.ajax

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 实现

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
    <!--配置SpringMVC-->
    <!-- 1. 开启SpringMVC注解驱动,注意导入mvc的头文件-->
    <mvc:annotation-driven/>
    <!--2. 静态资源过滤-->
    <mvc:default-servlet-handler/>
    <!--3. 扫描包:Controller-->
    <context:component-scan base-package="com.study.controller"/>
    <!--4. 视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>
// 不走视图页面,直接返回字符串
@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");
        }
    }
}
<%--<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>--%>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
    <%--<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>--%>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
    <script>
        function a1() {
            // post、get都是调用的ajax方法,可以直接用 $.ajax
            $.post({
                url: "${pageContext.request.contextPath}/a1",
                // data:传递给后端的数据,键值对的形式 name对应后端的name
                data: {"name": $("#userName").val()},
                // data:后端返回的数据 status:状态
                success: function (data, status) {
                    console.log(data);
                    console.log(status);
                }
            });
        }
    </script>
</head>
<body>
<%--onblur:失去焦点触发事件--%>
用户名:<input type="text" id="userName" onblur="a1()"/>
</body>
</html>

测试二:SpringMVC、JSON 方式实现

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.2.2</version>
</dependency>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private int age;
    private String sex;
}
@RequestMapping("/a2")
public List<User> ajax2() {
    List<User> 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" %>
<html>
<head>
    <title>Title</title>
    <%--jQuery--%>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
    <script>
        $(function () {
            $("#btn").click(function () {
                /*
                    简写方式:
                    $.post(url,param[可以省略(传递给后端的参数)],success[回调函数])
                 */
                $.post("${pageContext.request.contextPath}/a2", function (data) {
                    console.log(data);
                    let html = "";
                    for (let i = 0; i < data.length; i++) {
                        <%-- jsp中需要转义es6模板字符串${}:\${} --%>
                        html += `<tr>
                        <td>\${data[i].name}</td>
                        <td>\${data[i].age}</td>
                        <td>\${data[i].sex}</td>
                        </tr>`
                    }
                    $("#content").html(html);
                });

                /*
                $.post({
                    url: "${pageContext.request.contextPath}/a2",
                    success:function (data){
                        let html = "";
                        for (let i = 0; i < data.length; i++) {
                            html += `<tr>
                        <td>\${data[i].name}</td>
                        <td>\${data[i].age}</td>
                        <td>\${data[i].sex}</td>
                        </tr>`
                        }
                        $("#content").html(html);
                    }
                });
                */
            })
        })
    </script>
</head>
<body>
<input type="button" id="btn" value="获取数据"/>
<table>
    <tr>
        <td>姓名</td>
        <td>年龄</td>
        <td>性别</td>
    </tr>
    <tbody id="content"></tbody>
</table>
</body>
</html>

1.4 AJAX 注册提示

@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;
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
    <script>
        function a1() {
            $.post({
                url: "${pageContext.request.contextPath}/a3",
                data: {"name": $("#name").val()},
                success: function (data) {
                    if (data.toString() === "OK") {
                        $("#userInfo").css("color", "green");
                    }else {
                        $("#userInfo").css("color", "red");
                    }
                    $("#userInfo").html(data);
                }
            });
        }

        function a2() {
            $.post({
                url: "${pageContext.request.contextPath}/a3",
                data: {"pwd": $("#pwd").val()},
                success: function (data) {
                    if (data.toString() === "OK") {
                        $("#pwdInfo").css("color", "green");
                    }else {
                        $("#pwdInfo").css("color", "red");
                    }
                    $("#pwdInfo").text(data);
                }
            });
        }
    </script>
</head>
<body>
<p>
    <%--onblur:失去焦点触发事件--%>
    用户名:<input type="text" id="name" onblur="a1()"/>
    <span id="userInfo"></span>
</p>
<p>
    密码:<input type="text" id="pwd" onblur="a2()"/>
    <span id="pwdInfo"></span>
</p>
</body>
</html>
<!--JSON乱码统一解决(固定代码)-->
<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <constructor-arg value="UTF-8"/>
        </bean>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="failOnEmptyBeans" value="false"/>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

1.5 获取 baidu 接口 Demo

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>JSONP百度搜索</title>
    <style>
        #q {
            width: 500px;
            height: 30px;
            border: 1px solid #ddd;
            line-height: 30px;
            display: block;
            margin: 0 auto;
            padding: 0 10px;
            font-size: 14px;
        }

        #ul {
            width: 520px;
            list-style: none;
            padding: 0;
            border: 1px solid #ddd;
            margin: -1px auto 0;
            display: none;
        }

        #ul li {
            line-height: 30px;
            padding: 0 10px;
        }

        #ul li:hover {
            background-color: #f60;
            color: #fff;
        }
    </style>
    <script>

        // 2.步骤二
        // 定义demo函数 (分析接口、数据)
        function demo(data) {
            let Ul = document.getElementById('ul');
            let html = '';
            // 如果搜索数据存在 把内容添加进去
            if (data.s.length) {
                // 隐藏掉的ul显示出来
                Ul.style.display = 'block';
                // 搜索到的数据循环追加到li里
                for (let i = 0; i < data.s.length; i++) {
                    // es6 模板字符串
                    html += `<li>${data.s[i]}</li>`
                    // html += '<li>' + data.s[i] + '</li>';
                }
                // 循环的li写入ul
                Ul.innerHTML = html;
            }
        }

        // 1.步骤一
        window.onload = function () {
            // 获取输入框和ul
            let Q = document.getElementById('q');
            let Ul = document.getElementById('ul');

            // 事件鼠标抬起时候
            Q.onkeyup = function () {
                // 如果输入框不等于空
                if (this.value != '') {
                    // ☆☆☆☆☆☆JSONPz重点☆☆☆☆☆☆
                    // 创建标签
                    let script = document.createElement('script');
                    // 给定要跨域的地址 赋值给src
                    // 这里是要请求的跨域的地址 百度搜索的跨域地址
                    script.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=' + this.value + '&cb=demo';
                    // 将组合好的带src的script标签追加到body里
                    document.body.appendChild(script);
                }
            }
        }
    </script>
</head>

<body>
<input type="text" id="q"/>
<ul id="ul">

</ul>
</body>
</html>

二、拦截器

2.1 概述

2.2 自定义拦截器

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);
    }
}
<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--
            /**:包括路径及其子路径
            /admin/*:拦截的是/admin/add等等这种,/admin/add/user不会被拦截
            /admin/**:拦截的是/admin/下的所有
        -->
        <mvc:mapping path="/**"/>
        <!--bean配置的就是拦截器-->
        <bean class="com.study.config.MyInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>
@RestController
public class TestController {
    @RequestMapping("/interceptor")
    public String test2() {
        System.out.println("控制器中的方法执行了");
        return "hello";
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/interceptor">拦截器测试</a>
  </body>
</html>

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

实现思路:

测试:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/user/toLogin">登录</a>
<a href="${pageContext.request.contextPath}/user/toSuccess">成功页面</a>
</body>
</html>
@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";
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录成功</title>
</head>
<body>
<h3>登录成功页面</h3>
<hr>
${user}
<a href="${pageContext.request.contextPath}/user/logout">注销</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/user/toLogin">登录</a>
<a href="${pageContext.request.contextPath}/user/toSuccess">成功页面</a>
</body>
</html>
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;
    }
}
<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>        
        <mvc:mapping path="/user/**"/>
        <!--bean配置的就是拦截器-->        
        <bean class="com.study.config.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

三、文件上传和下载

3.1 概述

<!--编码方式:文件上传-->
<form action="" enctype="multipart/form-data" method="post">
    <input type="file" name="file"/>
    <input type="submit">
</form>

3.2 文件上传

<!--文件上传:自动导入commons-io-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>
<!--文件上传配置:id必须为:multipartResolver,否则报400错误-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 请求的编码格式,必须和jsp的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
    <property name="defaultEncoding" value="utf-8"/>
    <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
    <input type="file" name="file"/>
    <input type="submit" value="upload">
</form>

上传方式一:

@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";
    }
}

上传方式二:

/*
    上传方式 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 文件下载

// 文件下载
@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;
}
<a href="${pageContext.request.contextPath}/download">点击下载</a>

四、SSM 回顾

上一篇下一篇

猜你喜欢

热点阅读