Java老技术整合

Servlet

核心概念

执行流程:http://localhost:8080/web-demo/demo1这个url中,http://localhost:8080这是访问的web服务器的,web-demo是你部署在服务器上的项目名称,demo1是你这个servlet的请求地址,此时web服务器会创建你访问的这个对应的servlet对象并执行重写的service()

服务器怎么知道servlet中一定有service方法? 因为你是实现了Servlet的接口,实现后一定会重写service(),所以服务器知道一定会有service()

生命周期:servlet的生命周期由容器管理,分为4个阶段:

  • 实例化:默认情况下,当servlet第一次被访问时,由容器创建servlet对象

  • 初始化:实例化后会直接调用init()来初始化这个对象,只调用一次

  • 处理请求:每次请求都会调用一次service()

  • 销毁:调用destroy(),只调用一次

可以改变创建servlet对象:@WebServlet(urlPatterns = "/demo", loadOnStartup = 1),小于0是第一次被访问时创建Servlet对象,大于等于0服务器启动时创建Servlet对象,数字越小优先级越高

使用

准备工作

把Tomcat先配置好,然后maven来构建项目,然后修改成web项目并添加依赖

<groupId>com.dx</groupId>
<artifactId>servlet-first</artifactId>
<version>1.0.0</version>
<packaging>war</packaging> <!-- 修改成web项目 -->
​
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope> <!-- scope标签是一定要加的,表示只在项目操作的时候提供依赖,因为tomcat继承了servlet,写了provided后,后续项目打成jar包后不会出现依赖冲突 -->
</dependency>

然后在main文件夹里面创建一个webapp的目录,然后刷新Maven

编写Servlet

编写servlet有三种方式:

  1. 实现Servlet接口 【javax.servlet包下,它会实现5个方法,包含初始化init()、service()、销毁方法destroy()】

  2. 继承GenericServlet抽象类 【javax.servlet包下,它实现了实现Servlet,只有service()核心方法没实现,所以它是抽象类】

  3. 继承HttpServlet抽象类【我们的请求绝大部分都是 HTTP 请求,因此我们在真正开发中使用的是继承 HttpServlet 这个类】

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
  *我们一般还是会选择重写它的下面两个方法
  */
public class FirstServlet extends HttpServlet {
    //对get请求的处理逻辑,通过浏览器直接敲url是get请求的方式
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("ok");
        resp.getWriter().write("ok ok");
    }
    
    //对post请求的处理逻辑
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

HttpServlet底层原理

它能够处理不同请求,正常情况下如果我们自己去编写的话

@Override
public void service(ServletRequest req,ServletResponse res) throws ServletException,IOException {
    //转成HTTP对象
    HttpservletRequest request = (HttpServletRequest) req;
    HttpservletResponse response = (HttpServletRequest) res;
    
    //获取请求方式
    String method = request.getMethod();
    
    //判断,根据不同请求写不同逻辑
    if("GET".equals(method)) {
        //get对应的处理逻辑
    }else if("POST".equals(method) {
        //post对应的处理逻辑
    }
}

但后续我们每个类都要这么写很麻烦,所以现在HttpServlet底层已经封装了上面这个逻辑了,它里面有两个service() :其中一个是完成的是强转,剩下一个就是获取并判断的逻辑了,如果是GET就用doGet(),以此类推(类似于模板设计模式)

配置Servlet

xml文件形式

要运行需要配置Servlet,这个文件的路径应该是在 src/main/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>servlet的名称,一般是类名首字母小写</servlet-name>
        <servlet-class>servlet的全类名</servlet-class>
        <!-- <load-on-startup>指定Servlet加载时机,一般在1之后,值越小越先加载</load-on-startup> -->
    </servlet>
    
    <!-- 配置Servlet映射 -->
    <servlet-mapping>
        <servlet-name>要和上面的名称对应</servlet-name>
        <url-pattern>写的请求路径,必须是以/线开头</url-pattern>
    </servlet-mapping>
</web-app>

注解形式

Servlet3.0开始支持注解开发,不用配置web.xml,就可以直接运行(推荐使用)

package com.dx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 //name指定名称,alue 和 urlPatterns 都可以指定访问的路径
@WebServlet(name = "fourServlet", value = "/four") 
public class FourServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("fourServlet");
    }
}

然后运行Tomcat,输入路径即可访问

HttpServletRequest

常用方法

package com.dx.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;


/**
 * 演示HttpServletRequest方法
 */
@WebServlet("/demo")
public class RequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 防止post请求中文解析乱码,Tomcat8开始get请求就不再乱码了
        req.setCharacterEncoding("utf-8");
        
        //路径演示:http://localhost:8080/javaweb-servlet/demo?username=zhangsan&password=123456
        
        /* 获取请求行 */
        System.out.println(req.getMethod()); // 获取请求方式:GET
        System.out.println(req.getContextPath()); // 动态获取项目访问路径:/javaweb-servlet
        System.out.println(req.getRequestURL().toString()); // 获取URL:完整路径
        System.out.println(req.getRequestURI()); // 获取URI: /javaweb-servlet/demo
        
        /* 获取请求头 */
        String header = req.getHeader("user-agent");
        System.out.println(header); // Mozilla/5.0......
        
        /* 通用获取请求体(参数) */
        //get和post都有专门获取参数的方式,但请求类型你也不确定,为了通用就用了getParamter
        String name = req.getParamter("name"); 
        System.out.println(name);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp); //推荐这种写法,因为不需要分开写逻辑,判断完是post请求把参数给到doGet()也是可以的
    }
}

转发

在服务器内部进行资源跳转的方式

1)FromServlet.java

package com.dx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/from")
public class FromServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 存入值
        req.setAttribute("name", "zhang san");

        // 转发到 ToServlet 中
        // 转发不需要写项目路径
        req.getRequestDispatcher("/to").forward(req, resp);
    }
}

2)ToServlet.java

package com.dx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/to")
public class ToServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取 HttpServletRequest 对象中的 name 属性值
        String name = (String) req.getAttribute("name");
        System.out.println("name = " + name);

        // req.removeAttribute(String name); 删除数据
    }
}

输入 /from 后发现在控制台中输出了 zhang san,说明资源可共享

HttpServletResponse

常用方法

package com.dx.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 常用方法演示
 */
@WebServlet("/demo1")
public class ResponseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /* 获取响应行 */
        //设置响应状态码
        resp.setStatus(200);

        /* 设置响应头 */
        resp.setHeader("content-type", "application/json;charset=UTF-8");//这里是json,当然也可以:    resp.setContentType("application/json; charset=UTF-8"); 
        
        /* 设置响应体 */
        //获取字符输出流,流自动关
        PrintWriter writer = resp.getWriter();
        writer.write("你好");  //会放到响应体里面,最终写到页面上,后续可以ajax接收后进行拼接展示
        
        //获取字节输出流
        FileInputStream fis = new FileInputStream("d://a.jpg");
        ServletOutputStream os = resp.getOutputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            os.write(buf, 0, len);
        }
        fis.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

重定向

在任意位置实现资源跳转的方式

package com.dx.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/from")
public class FromServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("name", "zhang san");
        /*
        * 重定向原理:
        * 1.首先要设置状态码:`302`(告诉浏览器我处理不了,找别人)
        *   resp.setStatus(302);
        * 2.然后设置响应头:`location: 资源B的路径`(B资源可以解决,并给它路径让浏览器去找它)
        *   resp.setHeader("location","javaweb-servlet/demo2");
        */

        //重定向必须要要写项目路径,因为重定向的地址是浏览器使用,而不是像转发那样服务器内部使用
        //req.getContextPath()这样可以动态获取虚拟目录,写死的话不好改
        resp.sendRedirect(req.getContextPath() + "/to");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

ToServlet和转发一样没变,程序运行后的结果发现在 ToServlet 中不能成功获取到 name 属性的值,说明资源不可共享

一般而言,页面发生了数据的变化就需要使用重定向来重新发送一次请求,保证数据的实时更新

转发和重定向的区别

  1. 转发的方法是 HttpServletRequest 对象中的方法,而重定向是 HttpServletReponse 对象中的方法。

  2. 转发发送一次请求(资源可以使用request的共享数据),而重定向会发出两次或多次请求(资源不可使用request的共享数据)【通过 setAttribute、getAttribute、removeAttribute实现资源共享】

  3. 转发浏览器地址栏不会发生变化,而重定向浏览器地址栏会发生变化。

  4. 转发只能转发到当前服务器的内部资源,重定向可以重定向到任意位置的资源(比如从FromServlet重定向到百度)

  5. 在一个转发链中可以使用 HttpServletRequest 对象中的属性,而重定向不能使用 HttpServletRequest 对象中的属性。

异步Ajax + 回显

异步

原生对象 + JQuery + Axios (网上一搜就知道怎么用了)

回显

//jsonData是相应的Json数据,现在开始拼接数据
let str = '';
jsonData.forEach(person => {
    str += '<tr>'
    str += '<td>' + person.id + '</td>'
    str += '<td>' + person.name + '</td>'
    str += '<td>' + person.age + '</td>'
    str += '<td>' + person.gender + '</td>'
    str += '</tr>'
})
​
//把数据放到tbody
document.querySelector('tbody').innerHTML = str;
//users是响应的json数据,接下来进行拼接操作
let usersData = ""; 
for (let i = 0; i < users.length; i++) {
    let user = users[i];
    usersData += "<tr>\n" +
        "<td>"+user.id+"</td>\n" +
        "<td>"+user.username+"</td>\n" +
        "<td>"+user.password+"</td>\n" +
        "</tr>";
​
}
document.getElementById("tbody").innerHTML = usersData;  //设置在tbody上即可
//data就是请求返回的json格式的数据
let s = ''; //准备拼接
$(data).each(function (i, user) { //i表示索引,user其实就是拿到的一个个对象
    s += '<tr>';
    s += `<th scope="row">${user.id}</th>`;
    s += `<td>${user.name}</td>`
    s += `<td>${user.account}</td>`
    s += `<td>${user.password}</td>`
    s += `<td><img src="${user.avatar}" height="25"></td>`
    s += `<td><button type="button" class="btn btn-sm btn-info">修改</button>` +
        `<button type="button" class="btn btn-sm btn-danger">删除</button></td>`
    s += '</tr>';
});
​
//拼接完之后回显到页面上
$('.table > tbody').append(s);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值