12_JavaWebAjax

文章目录

  • Ajax
  • [1. 同步请求异步请求](#1. 同步请求异步请求)
  • [2. Ajax实现方式](#2. Ajax实现方式)
  • [3. 日程管理第四期](#3. 日程管理第四期)
  • [4. 响应JSON串](#4. 响应JSON串)
    • [4.1 响应JSON串格式的一般格式](#4.1 响应JSON串格式的一般格式)
  • Appendix

Ajax

发送请求的一些方式

1.输入浏览器回车

2.html>head>script/link

​ img标签

3.a标签form表单标签等

用户手动控制提交产生;

4.通过js代码产生请求;

Ajax的原理,通过js技术向后端发送请求,通过响应来进行判断是否 进行页面跳转,是否生成数据展示到dom树中

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

1. 同步请求异步请求

2. Ajax实现方式

  • 假如按钮触发了一个名为getmesssgae的js函数

  • script部分

    复制代码
      <script>
          function getmessage(){
              // 1.实例化一个xmlHttpRequest对象
              var req  = new XMLHttpRequest;
    
              // 2.设置xmlHttpRequest回调函数
    
              // 3.设置发送请求的方式和请求资源路径
              req.open("GET","/hello?username=zhangsan");
    
              // 4.发送请求
              req.send();
          }
      </script>

第二部分的代码有点多,很难写

  • 往页面上做出响应的代码*

    req.onreadystatechange = function(){
    if(req.readyState==4&&req.status==200);
    // alert("后端响应了")
    console.log(req.responseText)

    复制代码
      //将信息放到指定的位置
      var inputEle = document.getElementById("message")
      inputEle.value = req.responseText

    }

  • 进行页面跳转*

    window.location.href="http://www.atguigu.com"

3. 日程管理第四期

注册提交前进行校验用户名是否占用功能;

也就是前端checkUsername函数 校验完格式后,继续进行是否占用校验 并修改 usernameMsg信息

  • 创建XMLHTTPRequest对象

    var req = new XMLHTTPRequest()

  • 设置回调函数

    req.openstatechange = function(){

    ​ if(req.status ==200 && req.readyState = 4){

    ​ usernameMsg.innerText = req.responseText;

    ​ }

    }

  • 设置请求方式和 资源路径映射

    req.open("GET","user/checkUserUsed?username="+username)

  • 发送请求

    req.send()

使用Ajax技术在不跳转的情况下响应到前端页面

复制代码
//控制层新增函数checkUsernameUsed
    /**
     * 注册时接收要注册的username,目的是检测其是否 合法是否被占用
     * @param req
     * @param resp
     */
    protected void  checkUsernameUsed(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//        接收用户名
        String username = req.getParameter("username");
//        服务层进行查询该用户名是否存在用户
        int username1 = userService.findUsername(new SysUser(null, username, "******"));

//        如果有响应已占有
//        如果没有响应可用
        /**
         * 0表示没查出来 username
         * 1表示 占用
         */
        String info = null;
        if (username1==0){
            info="可用";
        }else if (username1==1){
            info="不可用";
        }
        resp.getWriter().write(info);

    }

注意:本次开发传参仅传入username,但是会设置一个密码,这个密码必须不为空,因为后续代码逻辑会送入MD5校验,为空报错;

密码直接设置为

复制代码
******

前端代码 会进行校验格式;用户无法起此代码

4. 响应JSON串

JSON串解决问题如下

  • 响应乱码问题

  • 响应信息格式问题

​ 后端响应的信息应该是JSON格式,前后端共同尊守;

​ 如果响应可用不可用;前后端需要保持一致,就很麻烦,后端代码进行修改了,那么前端也需要跟着改;

​ 统一的格式是前后端商量好的

  • 校验不通过无法阻止表单提交

4.1 响应JSON串格式的一般格式

{

​ 响应行 状态码200,404...

​ 响应头

​ 响应体 { code:"1成功/0失败", message:业务状态码,"data":{} }

}

复制代码
响应报文如上图所示;
所谓的JSON串格式写的是 响应体中的东西
响应行必须触发,把东西响应回来,因此响应行状态码必须是200
响应体中的码是前后端提前商量好的;

code		业务状态码
message		业务状态码的补充说明
data		本次响应数据			具体内容根据业务相关
  • 具体流程

我们使用jacksonlib包 转化json格式,减少后端程序员拼写字符串的难度

后端程序员撰写响应体的 class ,后续使用,直接new对象,将我们业务数据封装进去即可

复制代码
public class Result<T> {
    private Integer code;
    private String message;
    private T data;
}
  • 后续会将Result对象使用jackon转化为json串

  • 关于业务码code使用枚举形式进行定义,用的时候直接拿来用即可

    public enum ResultCodeEnum {
    /**
    * 此处创建枚举对象,自动的调用下面的构造器;
    */
    SUCCESS(200,"success"),
    USER_ERROR(501,"usernameError"),
    PASSWORD_ERROR(503,"passwordError"),
    NOT_LOGIN(504,"notLogin"),
    USER_USED(505,"usernameUsed");

    复制代码
      private Integer code;
      private String message;
    
      ResultCodeEnum(Integer code, String message) {
          this.code = code;
          this.message = message;
      }

    }

  • 此处创建枚举对象,自动的调用下面的构造器;

  • 枚举常量通常使用大写字母表示,默认常量 不可修改;

  • 枚举本身是一个类,具有类的所有成分,每一个枚举常量都是枚举类的实例,因此可以看出上面写法;

  • 创建Result类 未来后端传递数据使用Result对象即可;

    package schedule.common;

    /**

    • 全局统一响应的JSON格式处理类

    */
    public class Result<T> {
    // 返回码
    private Integer code;
    // 返回消息
    private String message;
    // 返回数据
    private T data;

    复制代码
      public Result(){}
      // 返回数据
      protected static <T> Result<T> build(T data) {
          Result<T> result = new Result<T>();
          if (data != null)
              result.setData(data);
          return result;
      }
    
    
      /**
       * 对上一个build的重载,除了设置data以外,还要进行code,message的设置;
       * @param body
       * @param code
       * @param message
       * @return
       * @param <T>
       */
      public static <T> Result<T> build(T body, Integer code, String message) {
          Result<T> result = build(body);
          result.setCode(code);
          result.setMessage(message);
          return result;
      }
    
      public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
          Result<T> result = build(body);
          result.setCode(resultCodeEnum.getCode());
          result.setMessage(resultCodeEnum.getMessage());
          return result;
      }
      /**
       * 操作成功,默认是将数据传进去,设置成功的状态码;
       * @param data  baseCategory1List
       * @param <T>
       * @return
       */
      public static<T> Result<T> ok(T data){
          Result<T> result = build(data);
          return build(data, ResultCodeEnum.SUCCESS);
      }
      public Result<T> message(String msg){
          this.setMessage(msg);
          return this;
      }
      public Result<T> code(Integer code){
          this.setCode(code);
          return this;
      }

    // ------------------------------下面是常规的GetSet方法------------------------------

    复制代码
      public Integer getCode() {
          return code;
      }
      public void setCode(Integer code) {
          this.code = code;
      }
      public String getMessage() {
          return message;
      }
      public void setMessage(String message) {
          this.message = message;
      }
      public T getData() {
          return data;
      }
      public void setData(T data) {
          this.data = data;
      }

    }

  • 因此在后端传递的时候,传递码可以如下表示

    复制代码
          Result result = Result.ok();
          String info = null;
          if (username1==0){
              result = result.ok(null);
          }else if (username1==1){
              result = result.build(null, ResultCodeEnum.USER_USED);
          }
  • 接下来将result转化为JSON串

  • 导入jar包

  • 导入jar包后使用ObjectMapper进行 对象-->JSON串转化

    // 接下来将result转化为json串响应给客户端
    ObjectMapper objectMapper = new ObjectMapper();
    String info = objectMapper.writeValueAsString(result);
    resp.getWriter().write(info);

对象转JSON串步骤

​ --导jackson包;

​ --实例化ObjectMapper对象

​ --直接使用writeValueAsString即可

  • 最终还需要告诉客户端响应json串格式

    resp.setContentType("application/json;charset=UTF-8");

  • 响应结果如下所示

  1. 创建WebJson工具类

    public class WebJson {
    private static ObjectMapper objectMapper;

    复制代码
     static {
         objectMapper = new ObjectMapper();
     }
     public static void  writeJson(HttpServletResponse resp, Result result){
         resp.setContentType("application/json;charset=UTF-8");
         try {
             String s = objectMapper.writeValueAsString(result);
             resp.getWriter().write(s);
         } catch (JsonProcessingException e) {
             throw new RuntimeException(e);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
    
     }

    }

因此所有代码一句话即可

writeJson是一个静态方法,因此这个工具包,调的不是类,是静态方法;可以直接类名.方法进行调用

Appendix

复制代码
//回调函数不会阻止表单提交;未来使用vue axios 结合promise处理;
相关推荐
互联网搬砖老肖5 小时前
Web 架构之攻击应急方案
前端·架构
zizisuo5 小时前
9.3.云原生架构模式
云原生·架构
风虎云龙科研服务器10 小时前
英伟达Blackwell架构重构未来:AI算力革命背后的技术逻辑与产业变革
人工智能·重构·架构
像风一样自由202010 小时前
MQTT协议详解:物联网通信的轻量级解决方案
物联网·struts·servlet
邪恶的贝利亚12 小时前
《Docker 入门与进阶:架构剖析、隔离原理及安装实操》
docker·容器·架构
xlsw_13 小时前
servlet-api
servlet
bing_15813 小时前
Spring Boot 的自动配置为 Spring MVC 做了哪些事情?
spring boot·spring·mvc
kaikaile199515 小时前
Jenkins集成Maven
servlet·jenkins·maven
镜舟科技16 小时前
湖仓一体架构在金融典型数据分析场景中的实践
starrocks·金融·架构·数据分析·湖仓一体·物化视图·lakehouse
Ramseyuu17 小时前
Mybatis-plus
微服务·云原生·架构