B/S和C/S

C/S架构的程序:

B/S架构的程序:

Web服务器

对外提供web服务的软件。

我们要使用的web服务器:

  • tomcat 不要钱。

  • nginx 并发处理能力特强。

Tomcat

下载的网址:https://tomcat.apache.org/download-80.cgi

安装使用。 开箱即用...

在bin目录下双击:

启动

启动之后在浏览器访问: http://localhost:8080

Tomcat的端口修改:

端口被占用的情况:启动tomcat的时候会闪退。查看日志:

修改:打开

在tomcat上部署一个web程序:

将写好的web应用程序直接赋值到webapps中:

在浏览器中访问: http://localhost:8888/0107-demo/main.html

在IDEA中配置tomcat

 

 

 

 

 

  

在IDEA中创建web项目

创建新项目:

 

 

 

 

 

 

 

Servlet

创建servlet需要添加servlet需要的jar文件,和之前添加JDBC驱动的jar的操作方式一致。这次选择的是tomcat中的servlet-api.jar文件

自己定义一个类,继承HttpServlet

 public class HelloServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         resp.getWriter().write("<h1>Hello world!</h1>");
    }
 }

在项目的webapp/WEB-INF/web.xml中添加配置:

 <?xml version="1.0" encoding="UTF-8"?>
 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
          version="4.0">
 
     <!-- 配置servlet -->
     <servlet>
         <!-- 随便,但是不要太随便 -->
         <servlet-name>HellServlet</servlet-name>
         <!-- 要配置的servlet类的全限定类名 -->
         <servlet-class>com.qidian.web.servlet.HelloServlet</servlet-class>
     </servlet>
     <!-- 配置一个servlet映射 -->
     <servlet-mapping>
         <!-- 这里的servlet-name 要和上面的配置一致 -->
         <servlet-name>HellServlet</servlet-name>
         <!-- 访问这个servlet的时候使用的路径 -->
         <url-pattern>/hello</url-pattern>
     </servlet-mapping>
 </web-app>

启动tomcat在浏览器中访问: http://localhost8080/web/hello

serlvet执行流程分析

[1]启动tomcat

tomcat已启动就会读取我们的WEB-INF/web.xml文件。

[2]在浏览器中访问:

http://localhost:8080/web/hello

localhost 指向本机

8080: 找到了tomcat

/web : 找到当前的项目

/hello : 要访问/web项目的 /hello

[3]tomcat通过"/hello" 找打对应的servlet

tomcat找到对应的servlet类,加载这个类,创建这个类的类对象。执行其中的doGet方法:

[4]浏览器接收到响应结果

认识一下servlet

狭义上:就是一个接口

 package javax.servlet;
 
 import java.io.IOException;
 
 public interface Servlet {
     // 初始化servlet对象的方法
     void init(ServletConfig var1) throws ServletException;
  // 获取servletconfig对象
     ServletConfig getServletConfig();
  // 处理请求的方法
     void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
  // 得到servlet的字符串表达形式
     String getServletInfo();
  // 释放资源的方法
     void destroy();
 }

广义上说servlet就是我们自己实现的servlet类:

tomcat其实本身只是认识Servlet接口而已,根本就不知道我们自己写的类。

我们自己写的servlet,当tomcat加载之后,会把我们的servlet看作Servlet接口来使用。所以我们写的类只要实现了Servlet接口,tomcat就认识,就能加载运行,并不一定要继承HttpServlet和GenericServlet类。

servlet的API“研究”

先看接口源码:

 package javax.servlet;


 import java.io.IOException;

 public interface Servlet {
     // 初始化servlet对象的方法
     void init(ServletConfig var1) throws ServletException;
  // 获取servletconfig对象
     ServletConfig getServletConfig();
  // 处理请求的方法
     void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
  // 得到servlet的字符串表达形式
     String getServletInfo();
  // 释放资源的方法
     void destroy();
 }

tomcat加载和运行的过程:

[1]加载我们的HelloServlet类,根据这个类会创建一个HelloServlet对象。

[2]创建好对象之后立刻初始化。 执行方法:

 void init(ServletConfig var1) throws ServletException;

这个方法本身是在GenericServlet中实现的。

[3]当请求到达这个HelloServlet的时候,默认会执行:

 // 处理请求的方法
     void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

这个方法也是GenericServlet实现的

tomcat就是通过“反射”调用HelloServlet对象的service方法,并且创建了两个对象ServletRequest和ServletResponse。 ServletRequest封装了所有的客户端的请求信息。 ServletResponse使用响应客户端的一个对象。

init方法的实现

在GenericServlet中实现:

 public abstract class GenericServlet implements Servlet, ServletConfig,
         java.io.Serializable {
     
     // 实现的接口中申明的init方法。
     @Override
     public void init(ServletConfig config) throws ServletException {
         this.config = config;
         // 调用另外一个init方法。
         this.init();
    }
     // 另外一个init方法。
     public void init() throws ServletException {
         // NOOP by default   do nothing
    }
             //..............
  }

init() : 空实现的方式,就让子类按需重写。

service方法的实现

在GenericServlet中并未实现这个方法:

 public abstract class GenericServlet implements Servlet, ServletConfig,
         java.io.Serializable {
             //..............
     public abstract void service(ServletRequest req, ServletResponse res)
             throws ServletException, IOException;
  }

肯定是在HttpServlet中实现的:

public abstract class HttpServlet extends GenericServlet {
	// 对父类/接口中的方法的实现
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {
        //HttpServletRequest 是 ServletRequest的子接口
        //HttpServletResponse 是 ServletResponse的子接口
		// 申明了两个对象。
        HttpServletRequest  request;
        HttpServletResponse response;

        try {
            // tomcat传入的req对象本身就是子接口HttpServletRequest的对象
            // 将父类对象强制类型转换为子类类型
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        // 如果没有异常,调用了另外一个重载的方法
        service(request, response);
    }
    // 在HttpServlet中自己定义的一个重载的service的方法
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
		// 获取HTTP的请求方法。HTTP请求有多个方法(GET,POST,PUT,DELETE,HEAD,TRACE,OPTIONS)
        String method = req.getMethod();
		// 如果请求方法是get
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                // 调用doGet
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    // 调用doGet
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            // 处理head请求
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            // 处理post请求
            doPost(req, resp);

        } else if (method.equals(METHOD_PUT)) {
            // 处理put请求
            doPut(req, resp);

        } else if (method.equals(METHOD_DELETE)) {
            // 处理Delete请求
            doDelete(req, resp);

        } else if (method.equals(METHOD_OPTIONS)) {
            
            doOptions(req,resp);

        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);

        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
                String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);

            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }
    
    // doXxxx的实现
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        // 这里的代码的作用是:当发送了get请求的时候,判断子类是否重写了这个方法,如果没有重写就报异常,如果重写了就执行子类的方法
        String msg = lStrings.getString("http.method_get_not_supported");
        sendMethodNotAllowed(req, resp, msg);
    } 
}

所以我们自己的servlet只要根据需要实现对应的doXxx方法即可,如果没有按照需求实现,就会出现405错误

之前的案例中地址栏直接输入 http://localhost:8080/web/hello 就是一个GET请求,我在servlet中要实现doGet处理GET请求。

destroy方法

destroy是在Servlet接口中申明的,使用卸载servlet对象之前调用的,专门用来释放资源优先象finally代码块。

这个方法在GenericServlet中实现的,是一个空实现。空实现,就是让我们自己按需重写的。

测试这些API的执行情况:

public class HelloServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("初始化HelloServlet");
    }

    @Override
    public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
        System.out.println("执行了service方法");
        // 通过super调用父类的service方法方法
        super.service(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("执行了doGet方法");
        resp.getWriter().write("<h1>Hello world!</h1>");
    }

    @Override
    public void destroy() {
        System.out.println("执行了destroy方法");
    }
}

启动tomcat,并且 重复访问这个servlet两次:

tomcat启动的时候,这些方法都没有执行。

停止tomcat:

tomcat的生命周期:

当tomcat加载servlet之后, 创建servlet类对象,对象已创建,立刻执行init方法,进行初始化。
当请求到大servlet的时候,tomcat会调用servlet的service方法处理请求。(service内部会自动调用对应的doXxxx方法)
当我们停止tomcat/卸载servlet的时候,在卸载之前会执行destroy方法释放资源。

HTTP协议

所谓HTTP协议就是,规定客户端和服务器端发送消息的格式和内容。

本质上客户端和服务端都是一台机器,通过一个软件进行通信(浏览器和tomcat)。为了让这两个软件可以通信,就规定了一套通信的消息格式。有了这个格式,它们相互就能”理解“相互发的消息。

研究HTTP协议,就是稍微看看HTTP的协议中的消息格式大致是啥样子?

我们请求一个网站:

请求头消息:

请求行: GET / HTTP/1.1

分为3部分:

  • GET 请求方法,请求方法分为7中:GET,POST,PUT,DELETE,OPTIONS,HEAD,TRACE

  • / 请求资源的路径。 / 表示请求首页。 /login.html 表示登陆页面

  • HTTP/1.1 请求协议版本

我们案例的请求头消息:

所有的请求头都是以 key : value的形式发送。具体的key : value是什么,是不确定。

响应头消息

响应行: HTTP/1.1 200

  • HTTP/1.1 协议版本

  • 200 响应状态码。

响应状态码的说明:

  • 200 表示响应正常。

  • 500 服务器内部错误,程序出异常,无法正常响应。

  • 404 表示请求的资源不存在。

  • 405 请求的方法不被支持。对应的doXxx方法没有被实现。

  • 406 响应的数据类型不正确,

  • 400 请求的数据类型不正确。

  • 304 获取的数据是从缓存中获取的,没有向服务器发送请求。

Request

当然我们说的是HttpServletRequest这个类型。

在我们自己写的doXxx方法中有一个参数HttpServletRequest类型,这个参数一个对象, 这个对象封装了所有的请求内容。所谓请求内容,就是客户端发送的请求行信息,以及请求头信息。tomcat会将客户端的请求内容进行解析,并且封装到HttpServletRequest对象中,并且将这个对象传递到我们的doXxx方法内部。

我们通过request可以轻松获取所有的请求内容:

请求内容:

  • 请求行中的内容: 请求方法,请求的资源的路径,协议版本。

  • 请求头的所有内容。

  • 请求参数

请求参数是什么?

我们在京东搜索一个商品

①search.jd.com 京东的域名。 域名就是我们写的 localhost:8080

② /Search 请求的资源路径 /web/hello

③ keyword=尤克里里&enc=utf-8

GET请求的请求参数是直接使用?连接在url后面的。 形式: key=value&key=value&....

POST请求的参数是放在一个专门的数据区域中,但是依然是key=value的形式。

使用tomcat传入的request对象获取所有的请求内容:

准备一个RequestTestServlet,在web.xml中添加配置:

<servlet>
    <servlet-name>RequestTest</servlet-name>
    <servlet-class>com.qidian.web.servlet.RequestTestServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RequestTest</servlet-name>
    <url-pattern>/requestTest</url-pattern>
</servlet-mapping>
public class RequestTestServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 从request中获取所有的请求内容
        // 获取请求方法
        String method = request.getMethod();
        System.out.println("请求方法是:"+method);
        // 获取请求路径
        String url = request.getRequestURL().toString();
        System.out.println("请求路径:"+url);
        // 获取请求头
        System.out.println("请求头:----------------");
        Enumeration<String> headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            System.out.println(name+":"+request.getHeader(name));
        }
        // 获取请求参数  username,age
        // 传入的是参数的名字,返回参数的值   这个方法返回的永远都是String类型
        String username = request.getParameter("username");
        String ageStr = request.getParameter("age");
        int age = Integer.parseInt(ageStr);
        System.out.println("请求参数:--------------");
        System.out.println("username = "+username);
        System.out.println("age = "+age);

    }
}

请求测试:

http://localhost:8080/web/requestTest?username=qimukakaxi&age=185

控制台输出的内容:

请求方法是:GET
请求路径:http://localhost:8080/web/requestTest
请求头:----------------
host:localhost:8080
connection:keep-alive
sec-ch-ua:" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
sec-ch-ua-mobile:?0
sec-ch-ua-platform:"Windows"
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site:none
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9,en;q=0.8
请求参数:--------------
username = qimukakaxi
age = 185

Response

HttpServletResponse 是tomcat创建的一个对象,这个对象直接连接者客户端,我们可以通过这个对象响应客户端。

// 使用response响应客户端
response.setCharacterEncoding("utf-8");// 防止中文乱码
response.getWriter().write("这是响应给客户端的内容,它可以是一段HTML代码 <h2>你看!是吧!</h2>");

图书管理

添加图书

web项目添加驱动:在WEB-INF目录下创建一个lib文件夹,将驱动文件放在lib中,添加到classpath

添加一个POJO类:

public class Book {
    // 图书编号,对应g_book的isbn
    private String isbn;
    // 图书标题,对应g_book的title
    private String title;
    // 图书成本,对应g_book的cost
    private float cost;
    // 图书售价,对应g_book的price
    private float price;
    // 图书出版社编号,对应g_book的pid
    private String pid;
    // 图书类别编号,对应g_book的categoryId
    private int categoryId;
	// setter和getter省略
}

添加BookDAO接口:

public interface BookDAO {
    // 保存一本图书
    int save(Book book);
    // 根据isbn查询一本图书信息
    Book getByIsbn(String isbn);
    // 修改一本图书信息
    int update(Book book);
    // 查询所有的图书
    ArrayList<Book> queryAll();
    // 分页查询
    ArrayList<Book> queryByPage(int page, int size);
    // 查询总条数
    int queryTotal();
}

在web目录下创建一个book-add.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加图书</title>
</head>
<body>
<!-- 添加一个表单 -->
<form method="post" action="book-add">
    <p>
        图书编号:<input type="text" name="isbn">
    </p>
    <p>
        图书标题: <input type="text" name="title">
    </p>
    <p>
        成本:<input type="text" name="cost">
    </p>
    <p>
        价格: <input type="text" name="price">
    </p>
    <p>
        出版社编号: <input type="text" name="pid">
    </p>
    <p>
        类别编号: <input type="text" name="categoryId">
    </p>
    <p>
        <input type="submit" value="提交">
    </p>
</form>
</body>
</html>

输入内容,点击提交按钮

请求头:

 

由于是POST请求,请求参数不在url后, 而是在一个专门的数据区域

 

使用一个Servlet获取这些请求参数,并且将这些数据保存到数据库

web.xml的配置:

在servlet中使用request.getParamter(" 参数名"); 这里的参数名,就是表单的input中的name属性的值。

public class BookSaveServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse resposne) throws ServletException, IOException {
        // 获取所有的请求参数
        String isbn = request.getParameter("isbn");
        String title = request.getParameter("title");
        String costStr = request.getParameter("cost");
        float cost = Float.parseFloat(costStr);
        String priceStr = request.getParameter("price");
        float price = Float.parseFloat(priceStr);
        String pid = request.getParameter("pid");
        String categoryIdStr = request.getParameter("categoryId");
        int categoryId = Integer.parseInt(categoryIdStr);
        // 准备一个Book对象
        Book book = new Book();
        // 将获取的请求参数数据全部设置到book对象中
        book.setIsbn(isbn);
        book.setTitle(title);
        book.setCategoryId(categoryId);
        book.setCost(cost);
        book.setPid(pid);
        book.setPrice(price);
        // 准备一个BookDAO对象
        BookDAO bookDAO = new BookDAOImpl();
        int result = bookDAO.save(book);
        String info = "保存失败";
        if(result == 1){
            info = "保存成功";
        }
        resposne.setCharacterEncoding("gbk");
        resposne.getWriter().write(info);
    }
}

整个流程:

 

 

乱码问题

两种情况的乱码:

情况1:数据库与应用程序之间乱码。

解决方案:在数据库连接的url中添加字符集的设置。

情况2:web请求响应中的乱码问题

响应的乱码解决:

①如果响应的是HTML: resp.setContentType("text/html;charset=utf-8");

②如果响应的是字符串: resp.setCharacterEncoding("utf-8");

请求中的乱码:

产生的原因是:客户端提交的编码和服务的编码不一致导致的。

tomcat8以前 tomcat的默认编码是 iso8859-1 . 无论请求是什么格式,在请求中中文参数都会乱码。

tomcat8之后,tomcat的默认编码为utf-8。 我们现在使用的是8.5. 默认就是utf-8。

目前的tomcat8.5中 GET请求的中文不乱码。 POST请求会乱。

POST请求中乱码的解决:

在获取请求参数之前,设置request对象的编码为utf-8.

 

web项目打包发布

在idea中:

最终tomcat看到的是out这个文件夹下的内容。

Ajax

常说的异步请求。。

第一个ajax应用

我们使用ajax来完成一个简单的请求。

[1]准备一个web项目, 添加一个servlet,可以接收请求参数name和age,给客户端响应一个字符串。

[2]准备一个HTML页面, 添加下面的程序

我们向服务器发送请求的方式

  • 浏览器地址栏直接输入访问地址,开始请求

  • 超链接(和直接写地址是一样的)

  • JS实现超链接 location.href=xxxx?xxx

  • 提交表单

上面的所有的提交数据的方式都是由浏览器完成具体的请求。

Ajax的测试程序分析

[1]这个程序中Servlet有没有特殊的要求?

Ajax本身和后端的任何技术都是没有关系。

[2]Ajax不是通过浏览器发送的请求,而是通过XMLHttpRequest对象发送的请求。

[3]XMLHttpRequest的状态(设置回调函数)

 

XMLHttpRequest本身是有状态的,状态属性是:readyState,有如下几个值:

 

  • 0 (uninitialized) or (request not initialized)(请求对象还没有被创建)

  • 1 (loading) or (server connection established)(和服务器完成连接)

  • 2 (loaded) or (request received)(请求已经发送)

  • 3 (interactive) or (processing request)(正在请求中)

  • 4 (complete) or (request finished and response is ready)(请求完成, 响应结果已经收到)

 

readyState的值一旦发送改变就会触发XMLHttpRequest上的一个事件:onreadystatechange。

 

所以我们通过设置onreadystatechange的函数,来设置回调函数。

 

[4]请求发送

    // 打开请求   (请求方法,请求的url路径,是否异步请求)
    httpRequest.open("GET","ajax?name=kakaxi&age=222",true);

请求方法一般都是GET/POST

GET请求,请求参数在url后面。

第三个参数表示是否异步。

如果是true:表示异步,请求发送之后,响应回来之前,后面的处理程序继续执行。

如果是false:表示同步,请求发送之后,响应回来之前,后面的处理程序不能执行。

// 发送请求 (POST请求的时候,这个参数才有用)
httpRequest.send(null);

post请求携带的参数: "name=kakaix&age=180"

httpRequest.send('name=kakaix&age=180');

Ajax的POST请求

按照GET请求的方式写POST请求:

这样的请求参数在后端无法获取。

如果参数依然写在URL后面,是可以携带的。

但是如果参数是在专门的数据区域 send(xxxx)。必须设置一个请求头:

在opne之后,send之前:

// 设置一个Header
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

跨域的问题

[1]将我们在idea中写的前端的程序直接复制到VSCode中。将url地址修改为完整的访问地址:

[2]在VSCode中或者其他的前端编辑器也一样:

确保我们的HTML页面是在服务器上运行的,不是本地文件打开的

[3]请求服务器测试

 

 浏览器告诉我们,不允许跨域请求。

解释这个问题:

①域名

俗话说的网址: www.baidu.com

其中.com 顶级域名。 baidu 一级域名,从运行商哪里租的。 www是二级域名,二级域名是我们自己随便写的。

任何一个域名都要绑定到一个ip地址上,我们在浏览器中输入的域名,会被DNS服务器解析为IP地址。

②跨域 (一级域名)

所谓跨域请求的意思是:从a域名下的程序中发出ajax请求去请求b域名下的数据

而跨域是不被允许的......... 浏览器不允许跨域请求数据。

JSONP

[1]script标签的跨域

浏览器不允许跨域请求,但是允许script标签跨域请求。

当前的服务器是:127.0.0.1:5500下

 <script src="http://localhost:8080/web/abc.js"></script>

这个可以请求。

在idea中添加一个JS文件

启动tomcat。

在VSCode的某一个页面中使用script引入上面写的JS文件

页面效果:

 

 [2]利用jsonp实现跨域请求数据

需求,根据用户的id跨域请求用户的名字。在后端实现一个servlet:

public class UserGetNameServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userId = req.getParameter("userId");
System.out.println("userId = "+userId);
// 响应客户端
resp.getWriter().write("卡卡西");
}
}

在前端的任何页面中加入如下的script标签:

 

 tips:script标签的 src就是要请求的接口的url,并且get请求携带参数。

script理论获取的是script的代码,但是这个服务器端返回的数据是一个字符串。

如果我们返回一个可执行的script代码,是不是就可以直接执行了???

思路:

在前端定义一个js函数,这个函数接收一个参数,参数就是username,然后在后端返回调用这个函数的js代码,并且将后端的用户名传入即可。

前端的实现:

     <script>
         let uname = undefined;
         function getUsername(username){
             uname = username;
        }
         // 手动调用
         // getUsername("卡卡西");
     </script>
     <script src="http://localhost:8080/web/getName?userId=789"></script>
     <script>
         console.log("uname = " + uname);
     </script>

修改后端的返回值:

原理:

通过后端的设置允许跨域

前端请求:不需要做任何修改, 就按照常规的请求操作即可。

ajax相关请求的封装

[1]封装一个基础的ajax

在任意一个页面引入上面的js文件:

<!-- 引入ajax封装的文件 -->
<script src="js/qidian-ajax.js"></script>
<script>
function doAjax(){
// 调用我们自己分装的ajax请求的函数
qdAjax({
type:"GET",
url:"ajax",
data:"name=卡卡西&age=222",
success:function(res){
document.getElementById("result").value=res;
}
});
}
</script>
</head>
<body>
<input type="text" id="result"><input type="button" value="请求" onclick="doAjax()">
<p></p>
<script>
function doPostAjax(){
qdAjax({
type:"POST",
url:"ajax",
data:"name=佐助&age=18",
success:function(res){
document.getElementById("spanResult").innerText=res;
}
})
}
</script>
<span id="spanResult"></span> | <a href="javascript:doPostAjax()">POSTAjax请求</a>
</body>
</html>

JSON的基本的语法:

所有的属性都应该使用“”包裹。属性值:字符串必须使用“”包裹,数字可以不使用“”。

一个对象:{"name":"卡卡西","age":28,"skill":"千年杀"}

[
{"name":"卡卡西","age":28,"skill":"千年杀"},
{"name":"卡卡西","age":28,"skill":"千年杀"},
....
]

一个复杂的对象:

{
"name":"大锤",
"age": 28,
"dog":{"name":"大黄","age":5},
"girlfriends":[
{"name":"如花","age":18},
{"name":"翠花","age":19},
......
]
}

JS中JSON的处理

将JSON字符串转换为对象:

<script>
let stu = '{"name":"佐助","age":18,"skill":"写轮眼"}';
console.log(typeof stu);
// 将字符串转换为对象
let student = JSON.parse(stu);
console.log(typeof student);
// 当转换为对象之后,就可以使用其中的属性了
console.log(student.name);
// 将对象转换为json字符串
let dog = new Object();
dog.name = "大黄";
dog.age = 5;
console.log(typeof dog);
let dogStr = JSON.stringify(dog);
console.log(typeof dogStr);
</script>

在java中json字符串和对象之间的转换

在java中将对象转换字符串:拼接字符串。 将字符串转换为对象:解析字符串,创建新的对象,并且赋值。

于是乎,我们考虑使用第三方工具:我们用jackson。

登陆和登陆状态校验

session知识点

一句话:HTTP协议是无状态的协议。所谓无状态就是服务器不记录客户端的访问状态。在通俗一些,就是你每次对服务器的访问,服务器都不知道你是谁。它只知道有一个请求,然后就按照请求给出正确响应。

一个现象:在网页上登陆的淘宝,选了商品加入购物车,准备结算。这时室友喊你去吃饭,吃完饭回来,发现这个淘宝需要重新登陆。

如果服务器不记录状态:你请求购物车页面是一次请求。请求登陆也是一次请求。对于服务器来说这两次请求是没有关系的。显示情况是有关系的。

web项目就是靠session解决HTTP协议无状态的问题。

session处理“会话跟踪”:

当客户端第一次请求服务器的时候,服务器会在服务器端创建一个session(会话)对象,并且给session一个编号(sessionid)。将个这个编号放在cookie中,并且将这个cookie发送给客户端(浏览器,手机端)。客户端下次来访问的时候会带上这个cookie,带上session编号。服务器就根据session编号找到之前的session对象。session本身是一个容器,可以存储一些信息。比如登陆状态信息。如果浏览器清空cookie,再访问服务器的时候,就是一个新的请求,之前的session就失效了。还有个问题,服务器无法检测客户端是否清理了cookie。所以session是否还能继续使用服务器不知道。所以为了防止session一致存在在服务中。如果超过了半小时没有使用的session,直接销毁。

cookie是不能跨域的。