JavaWeb面试题

JavaWeb面试题

1-10

1.说一说Servlet的生命周期?

Servlet的生命周期包括以下几个阶段:

  1. 初始化阶段(Initialization):在容器启动时,Servlet容器会调用Servlet的init()方法来进行初始化操作。在这个阶段,可以进行一些必要的设置和资源加载,例如数据库连接的建立。

  2. 请求处理阶段(Request Handling):一旦Servlet初始化完成后,它就可以接受客户端的请求,并根据请求的类型执行相应的操作。每个请求都会由Servlet容器创建一个新的线程来处理,并调用Servlet的service()方法来处理请求。

  3. 服务阶段(Service):在服务阶段,Servlet容器会根据请求的类型,调用合适的doGet()、doPost()、doPut()等方法来处理请求并生成响应。开发者需要根据具体的需求,在这些方法中编写相应的业务逻辑代码。

  4. 销毁阶段(Destruction):当Servlet容器关闭或卸载Web应用程序时,会调用Servlet的destroy()方法来进行一些清理工作,例如释放占用的资源、关闭数据库连接等。

需要注意的是,Servlet的init()方法和destroy()方法只会被调用一次,而service()方法则会根据每个请求的类型多次调用。

以上就是Servlet的基本生命周期。通过合理地利用生命周期方法,可以实现一些初始化、清理、资源管理等功能,以及处理不同类型的请求。

为了测试Servlet处理请求的流程,我们重写了从HttpServlet继承的多个方法:

  • init

  • service(ServletRequest,ServletResponse)

  • service(HttpServletRequest,HttpServletResponse)

  • doGet

  • doPost

  • destroy

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
​
/**
 *
 * 创建servlet类的步骤:
 * 1.创建一个命名为 **Servlet
 * 2.继承javax.servlet.http.HttpServlet类
 * 3.重写doGet和doPost方法
 * 4.配置当前Servlet类的访问路径
 */
public class TestServlet  extends HttpServlet {
​
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("------------init");
        super.init(config);
    }
​
    @Override
    public void service(ServletRequest req, ServletResponse res) 
        throws ServletException, IOException {
        System.out.println("------------Servlet接口定义的service");
        super.service(req, res);
    }
​
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
        System.out.println("------------HttpServlet类定义的service");
        super.service(req, resp);
    }
​
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
        System.out.println("------------doGet");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
        System.out.println("------------doPost");
    }
​
    @Override
    public void destroy() {
        System.out.println("------------destroy");
        super.destroy();
    }
}

2.Servlet API中forward()与redirect()的区别?

  1. 从地址栏显示来说

    forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址

    redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.所以redirect等于客户端向服务器端发出两次request,同时也接受两次response。

  2. 从数据共享来说 forward:转发页面和转发到的页面可以共享request里面的数据.

    redirect:不能共享数据.

    redirect不仅可以重定向到当前应用程序的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源. forward方法只能在同一个Web应用程序内的资源之间转发请求.forward 是服务器内部的一种操作.

    redirect 是服务器通知客户端,让客户端重新发起请求. 所以,你可以说 redirect 是一种间接的请求, 但是你不能说”一个请求是属于forward还是redirect “

  3. 从运用地方来说 forward:一般用于用户登陆的时候,根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.

  4. 从效率来说 forward:高. redirect:低.

转发和重定向

当客户端请求到了某个Servlet类之后,Servlet类进行处理,但是并不使用这个Servlet来响应客户端,而是要使用另一个Servlet来响应。

转发
1. 转发跳转流程
2. 转发的特点
  • 转发是在服务器端,两个Servlet之间的请求行为;

  • 浏览器只对服务器进行了一次请求;

  • 浏览器的地址不会改变,浏览器请求ServletA,ServletA转到ServletB由ServletB响应浏览器,浏览器显示的是ServletA的访问地址;

  • 转发过程中,可以通过request对象传递数据;

3. 转发的代码实现
  • ServletA 转发到 ServletB

在ServletA中:
request.getRequestDispatcher("ServletB的URL").forward(request,response);
4. 数据传递
  • ServletA 转发到 ServletB,并传递参数

  • 传数据

//ServletA:在转发操作之前,将需要传递给ServletB的参数设置到request对象中,可以传递不同类型数据
//设置转发传递的数据
request.setAttribute("stuNum","10001");
request.setAttribute("stuAge",21);  //如果直接给简单类型数据,则会自动装箱为对应的封装类对象
request.setAttribute("stu",new Student(...));
//转发
request.getRequestDispatcher("ServletB的URL").forward(request,response);
  • 取数据

//ServletB:在ServletB的doGet/doPost方法中,通过request对象获取ServletA传递的参数
//Object obj = request.getAttribute(String key);
String snum = (String)request.getAttribute("stuNum");
int sage = (Integer)request.getAttribute("stuAge");
Student stu = (Studennt)request.getAttribute("stu");

重定向
1. 重定向跳转流程
  • 客户端请求ServletA,ServletA响应给客户端一个新的请求地址ServletB,让客户端重新向ServeltB发送请求。

2. 重定向特点
  • 重定向是客户端的行为

  • 浏览器对服务器发送了两次请求;

  • 重定向是由浏览器再次发送请求,浏览器地址会改变为转发的地址;

  • 不能通过request对象将ServletA中的数据传递给ServletB

  • 如果ServletA重定向到ServletB的时候有数据要传递到ServletB该如何实现?——url传值

3. 重定向代码实现
在ServletA中
response.sendRedirect("ServletB访问URL");
4. 数据传递
//ServletA:在响应浏览器重定向地址的时候,在URL声明参数
response.sendRedirect("ServletB?key=value");
//ServletB: 获取浏览器请求的参数
String value = request.getParameter("key");

3.request.getAttribute()和 request.getParameter()有何区别?

  1. request.getParameter()取得是通过容器的实现来取得通过类似post,get等方式传入的数据。request.setAttribute()和getAttribute()只是在web容器内部流转,仅仅是请求处理阶段。

  2. getAttribute是返回对象,getParameter返回字符串

  3. getAttribute()一向是和setAttribute()一起使用的,只有先用setAttribute()设置之后,才能够通过getAttribute()来获得值,它们传递的是Object类型的数据。而且必须在同一个request对象中使用才有效。,而getParameter()是接收表单的get或者post提交过来的参数

4.jsp静态包含和动态包含的区别?

使用静态包含只会产生一个class文件,而使用动态包含会产生多个class文件

静态引入和动态引入的区别:

  • 静态引入,使用<%@include file=""%>编译指令将HTML或者JSP页面引入到当前文件,静态引入是先引入再执行,因此被引入的页面可以是一个HTML片段,也可在被引入的页面中访问主页面定义的Java变量;

  • 动态引入,使用<jsp:include page=""/>动作指令将JSP页面引入到当前文件,动态引入是先独立编译执行被引入的页面,将执行结果引入到当前页面,被引入的页面需要独立执行因此必须是一个完成的JSP,同时在被引入的JSP中不能访问主页面定义的Java变量。

<%@ include %>

在当前JSP中引用其他的资源(JSP\HTML)作为当前JSP的一部分,被引入的页面不会单独作为一个JSP编译,而是将引入的页面中的代码插入到当前JSP之后作为一个整体进行编译。

被引入的页面只需要是一个HTML片段即可。

静态引入:将被页面引入到当前JSP之后再进行整体的编译,被引入的页面不会单独编译。

  • header.jsp

    <div style="height: 100px; background: deepskyblue" >header</div>
  • footer.jsp

    <div style="height: 50px; background: lightgray" >footer</div>
  • index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ page import="java.util.Date"%>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
       
        <%@ include file="header.jsp"%>
        <div style="height: 400px; background: orange">index</div>
        <%@ include file="footer.jsp"%>
      </body>
    </html>
jsp:include
<%-- 动态引入 --%>
<jsp:include page="test1.jsp"/>

动态引入JSP文件文件:被引入的JSP文件先单独编译执行,将执行的结果引入到当前JSP文件。

因为被引入的JSP页面需要独立的编译执行,因此被引入的页面需要是一个完整的JSP文件。

在动态引入的页面中不能访问主页面中定义的Java变量。

静态引入和动态引入的区别:

  • 静态引入,使用<%@include file=""%>编译指令将HTML或者JSP页面引入到当前文件,静态引入是先引入再执行,因此被引入的页面可以是一个HTML片段,也可在被引入的页面中访问主页面定义的Java变量;

  • 动态引入,使用<jsp:include page=""/>动作指令将JSP页面引入到当前文件,动态引入是先独立编译执行被引入的页面,将执行结果引入到当前页面,被引入的页面需要独立执行因此必须是一个完成的JSP,同时在被引入的JSP中不能访问主页面定义的Java变量。

5.MVC的各个部分都有那些技术来实现?如何实现?

MVC是Model-View-Controller的简写。Model代表的是应用的业务逻辑(通过JavaBean,EJB组件实现),View是应用的表示面(由JSP页面产生),Controller是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。

6.jsp有哪些内置对象?作用分别是什么?

JSP有9个内置对象:

  • request:封装客户端的请求,其中包含来自GET或POST请求的参数;

  • response:封装服务器对客户端的响应;

  • pageContext:通过该对象可以获取其他对象;

  • session:封装用户会话的对象;

  • application:封装服务器运行环境的对象;

  • out:输出服务器响应的输出流对象;

  • config:Web应用的配置对象;

  • page:JSP页面本身(相当于Java程序中的this);

  • exception:封装页面抛出异常的对象

7.session 和 cookie 有什么区别?

  • Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中

  • Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。

将浏览器与服务器之间的多次交互作为一个整体处理,通过服务器数据存储和浏览器数据存储集合的形式实现状态管理:

  • 客户端状态管理:cookie技术 (在浏览器缓存数据)

  • 服务器状态管理:session技术(在服务器存储用户信息,基于cookie)

8.jsp 和 servlet 有什么区别?

  1. jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)

  2. jsp更擅长表现于页面显示,servlet更擅长于逻辑控制。

  3. Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到。

  4. Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。

9.tomcat容器是如何创建servlet类实例?用到了什么原理?

当容器启动时,会读取在webapps目录下所有的web应用中的web.xml文件,然后对xml文件进行解析,并读取servlet注册信息。然后,将每个应用中注册的servlet类都进行加载,并通过反射的方式实例化。(有时候也是在第一次请求时实例化) 在servlet注册时加上1如果为正数,则在一开始就实例化,如果不写或为负数,则第一次请求实例化。

10.如何避免 sql 注入?

  1. 预编译PreparedStatement(简单又有效的方法)

  2. 使用正则表达式过滤传入的参数

  3. 字符串过滤

  4. JSP中调用该函数检查是否包函非法字符

  5. JSP页面判断代码

什么是SQL注入问题?

在JDBC操作SQL指令编写过程中,如果SQL指令中需要数据,我们可以通过字符串拼接的形式将参数拼接到SQL指令中,如String sql = "delete from books where book_id="+s;(s就是拼接到SQL中的变量)

使用字符串拼接变量的形式来设置SQL语句中的数据,可能会导致因变量值的改变引起SQL指令的原意发生改变,这就被称为SQL注入。SQL注入问题是需要避免的。

例如:

  • 如果s的值为1,SQL指令 : delete from books where book_id=1

  • 如果s的值为1 or 1=1,SQL指令:delete from books where book_id=1 or 1=1

如何解决SQL注入问题?

使用PreparedStatement进行SQL预编译解决SQL注入问题:

  • 在编写SQL指令时,如果SQL指令中需要参数,一律使用?参数占位符

  • 如果SQL指令中有?,在JDBC操作步骤中不再使用Statement,而是从Conection对象获取PreparedStatement对SQL指令进行预编译 PreparedStatement preparedStatement = connection.prepareStatement(sql);

  • 预编译完成之后,通过PreparedStatement对象给预编译后的SQL指令的?复制

    • prepareadStatement.setInt(参数占位符序号,值);

    • prepareadStatement.setString(参数占位符序号,值);

  • SQL指令中的所有?完成赋值之后,通过PreparedStatement执行SQL执行SQL时不再加载SQL

    • int i = prepareadStatement.executeUpdate();

    • ResultSet rs = preparedStatement.executeQuery();

11-20

11.什么是 XSS 攻击,如何避免?

XSS攻击又称CSS,全称Cross Site Script (跨站脚本攻击),其原理是攻击者向有XSS漏洞的网站中输入恶意的 HTML 代码,当用户浏览该网站时,这段 HTML 代码会自动执行,从而达到攻击的目的。XSS 攻击类似于 SQL 注入攻击,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制,获取用户的一些信息。XSS是 Web 程序中常见的漏洞,XSS 属于被动式且用于客户端的攻击方式。

XSS防范的总体思路是:对输入(和URL参数)进行过滤,对输出进行编码。

12.JDBC访问数据库的基本步骤是什么?

1,加载驱动 2,通过DriverManager对象获取连接对象Connection 3,通过连接对象获取会话 4,通过会话进行数据的增删改查,封装对象 5,关闭资源

13.说说preparedStatement和Statement的区别?

1,效率:预编译会话比普通会话对象,数据库系统不会对相同的sql语句不会再次编译

2,安全性:可以有效的避免sql注入攻击!sql注入攻击就是从客户端输入一些非法的特殊字符,而使服务器端在构造sql语句的时候仍然能够正确构造,从而收集程序和服务器的信息和数据。 比如:“select * from t_user where userName = ‘” + userName + “ ’ and password =’” + password + “’”

如果用户名和密码输入的是’1’ or ‘1’=’1’; 则生产的sql语句是: “select * from t_user where userName = ‘1’ or ‘1’ =’1’ and password =’1’ or ‘1’=’1’这个语句中的where 部分没有起到对数据筛选的作用。

14.说说事务的概念,在JDBC编程中处理事务的步骤。

1,事务是作为单个逻辑工作单元执行的一系列操作。 2,一个逻辑工作单元必须有四个属性,称为原子性、一致性、隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务 事务处理步骤: 3,conn.setAutoComit(false);设置提交方式为手工提交 4,conn.commit()提交事务 5,出现异常,回滚 conn.rollback();

  1. 一个事务中的多个DML操作需要基于同一个数据库连接;

  2. 创建连接之后,设置事务手动提交(关闭自动提交);connection.setAutoCommit(false);

  3. 当当前事务中的所有DML操作完成之后手动提交;connection.commit();

  4. 当事务中的任何一个步骤出现异常,在catch代码块中执行事务回滚。connection.rollback();

package com.qfedu.jdbc.dao;
​
import com.qfedu.jdbc.utils.DBHelper;
​
import java.sql.*;
​
/**
 * @Descript
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 */
public class BookDAO {
​
    /**
     * 借书:
     * @param stuNum 借书的学生学号
     * @param bookId 借书的图书编号
     * @param num   借书的数量
     * @return
     */
    public boolean borrowBook(String stuNum,int bookId,int num){
        boolean flag = false;
        Connection connection = null;
        PreparedStatement preparedStatement1 = null;
        PreparedStatement preparedStatement2 = null;
        try {
            connection = DBHelper.getConnectin();
            //设置使用当前Connection连接操作数据库自动提交关闭
            connection.setAutoCommit(false);
​
            //1.向`records`表添加借书记录
            String sql1 = "insert into records(snum,bid,borrow_num,is_return,borrow_date) values(?,?,?,0,sysdate())";
            preparedStatement1 = connection.prepareStatement(sql1);
            preparedStatement1.setString(1,stuNum);
            preparedStatement1.setInt(2,bookId);
            preparedStatement1.setInt(3,num);
            int i = preparedStatement1.executeUpdate();
​
            int k = 10/0;  //造异常:算术异常
​
            //2.修改`books`表中的库存
            String sql2 = "update books set book_stock=book_stock-? where book_id=?";
            preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement2.setInt(1,num);
            preparedStatement2.setInt(2,bookId);
            int j = preparedStatement2.executeUpdate();
​
            // 提交事务
            connection.commit();
            flag = i>0 && j>0;
        }catch (Exception e){
            try {
                //一旦事务执行过程中出现异常,执行回滚
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }finally {
            DBHelper.close(preparedStatement1,null);
            DBHelper.close(preparedStatement2,connection);
        }
        return flag;
    }
   
}

15.数据库连接池的原理,为什么要使用连接池?

连接池:存放数据库连接对象的容器

连接池作用:对数据库连接进行管理,减少因重复创建、销毁连接导致的系统开销

16.JDBC的脏读是什么?哪种数据库隔离级别能防止脏读?

读未提交(read uncommitted)脏读,一个事务读取到了另一个事务中未提交的数据

读已提交(read committed)T2只能读取T1已经提交的数据;避免了脏读,但可能会导致不可重复度(虚读): 在同一个事务中,两次查询操作读取到数据不一致

可重复读(repeatable read)避免了(虚读),但可能会导致幻读。修改的时候遇到添加,以为修改成功了,读出不一样

串行化(serializable) 同时只允许一个事务对数据表进行操作;避免了脏读、虚读、幻读问题

17.JDBC的DriverManager是用来做什么的?

注册驱动,获得连接

//1.注册驱动(驱动jar包中的驱动类(Driver)的路径:com.mysql.cj.jdbc.Driver)
Class.forName("com.mysql.cj.jdbc.Driver");
​
//2.创建连接:通过数据库驱动管理器 DriverManager(java.sql.Driver)获取连接
//  JDBC JDK提供的数据库连接的规范 --- java.sql
//  java.sql.Connection接口  一个对象就表示一个数据库连接
//  url 数据库的统一资源定位器(定位数据库连接资源)
//  url参数
//      characterEncoding 设置编码
//      useSSL=true  使用SSL通信
//      useTimezone=true  设置客户端和服务端时区转换
String url = "jdbc:mysql://localhost:3306/db_test3";
Connection connection = DriverManager.getConnection(url,"root","@QFedu123");
​

18.execute,executeQuery,executeUpdate的区别是什么?

  1. Statement的execute(String query)方法用来执行任意的SQL查询,如果查询的结果是一个ResultSet,这个方法就返回true。

    如果结果不是ResultSet,比如insert或者update查询,它就会返回false。我们可以通过它的getResultSet方法来获取ResultSet,或者通过getUpdateCount()方法来获取更新的记录条数。

  2. Statement的executeQuery(String query)接口用来执行select查询,并且返回ResultSet。即使查询不到记录返回的ResultSet也不会为null。

    我们通常使用executeQuery来执行查询语句,这样的话如果传进来的是insert或者update语句的话,它会抛出错误信息为 “executeQuery method can not be used for update”的java.util.SQLException。 ,

  3. Statement的executeUpdate(String query)方法用来执行insert或者update/delete(DML)语句,或者 什么也不返回,对于DDL语句,返回值是int类型,如果是DML语句的话,它就是更新的条数,如果是DDL的话,就返回0。

    只有当你不确定是什么语句的时候才应该使用execute()方法,否则应该使用executeQuery或者executeUpdate方法。

增删改

//5.执行SQL获取执行结果
int i = statement.executeUpdate(sql);  

查询一条记录

//通过executeQuery方法执行查询语句,并且将查询的结果存放到一个ResultSet对象中(结果集)
ResultSet rs = statement.executeQuery(sql);
//处理结果:从rs中获取查询结果
if(rs.next()){
            int bookId = rs.getInt("book_id");
            String bookName = rs.getString("book_name");
            String bookAuthor = rs.getString("book_author");
            double bookPrice = rs.getDouble("book_price");
            int bookStock = rs.getInt("book_stock");
            String bookDesc = rs.getString("book_desc");
            System.out.println(bookId+"\t"+bookName+"\t"+bookAuthor+"\t"+bookPrice+"\t"+bookStock+"\t"+bookDesc);
}

查询多条记录

 ResultSet rs = statement.executeQuery(sql);
        while(rs.next()){
            int bookId = rs.getInt("book_id");
            String bookName = rs.getString("book_name");
            String bookAuthor = rs.getString("book_author");
            double bookPrice = rs.getDouble("book_price");
            int bookStock = rs.getInt("book_stock");
            String bookDesc = rs.getString("book_desc");
            System.out.println(bookId+"\t"+bookName+"\t"+bookAuthor+"\t"+bookPrice+"\t"+bookStock+"\t"+bookDesc);

19.JDBC的ResultSet是什么?

在查询数据库后会返回一个ResultSet,它就像是查询结果集的一张数据表。 ResultSet对象维护了一个游标,指向当前的数据行。开始的时候这个游标指向的是第一行。

如果调用了ResultSet的next()方法游标会下移一行,如果没有更多的数据了,next()方法会返回false。可以在for循环中用它来遍历数据集。

默认的ResultSet是不能更新的,游标也只能往下移。也就是说你只能从第一行到最后一行遍历一遍。不过也可以创建可以回滚或者可更新的ResultSet

当生成ResultSet的Statement对象要关闭或者重新执行或是获取下一个ResultSet的时候,ResultSet对象也会自动关闭。

可以通过ResultSet的getter方法,传入列名或者从1开始的序号来获取列数据。

20.AJAX有哪些优点和缺点?

优点:

1、最大的一点是页面无刷新,用户的体验非常好。

2、使用异步方式与服务器通信,具有更加迅速的响应能力。

3、可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。

4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。

缺点:

1、ajax不支持浏览器back按钮。

2、安全问题 AJAX暴露了与服务器交互的细节。

3、对搜索引擎的支持比较弱。

4、破坏了程序的异常机制。

5、不容易调试。

21-30

21.AJAX应用和传统Web应用有什么不同?

在传统的Javascript编程中,如果想得到服务器端数据库或文件上的信息,或者发送客户端信息到服务器,需要建立一个HTML form然后GET或者POST数据到服务器端。用户需要点击”Submit”按钮来发送或者接受数据信息,然后等待服务器响应请求,页面重新加载。

因为服务器每次都会返回一个新的页面, 所以传统的web应用有可能很慢而且用户交互不友好。

使用AJAX技术, 就可以使Javascript通过XMLHttpRequest对象直接与服务器进行交互。

通过HTTP Request, 一个web页面可以发送一个请求到web服务器并且接受web服务器返回的信息(不用重新加载页面),展示给用户的还是同一个页面,用户感觉页面刷新,也看不到到Javascript后台进行的发送请求和接受响应,体验非常好。

22.Ajax的实现流程是怎样的?

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.

(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.

(3)设置响应HTTP请求状态变化的函数.

(4)发送HTTP请求.

(5)获取异步调用返回的数据.

(6)使用JavaScript和DOM实现局部刷新.

regist.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
    <script type="text/javascript" src="js/test.js"></script>
  </head>
  <body>
    <h3>用户注册</h3>
    <form action="" method="post">
      <p>
        帐号:<input type="text" id="userName"/><label id="tipsLabel"></label>
        <input type="button" value="检测" οnclick="checkUserName()"/>
      </p>
      <p>密码:<input type="password"/></p>
      <p>确认密码:<input type="password"/></p>
      <p>姓名:<input type="text"/></p>
      <p>电话:<input type="text"/></p>
      <p><input type="submit" value="提交注册"/></p>
    </form>
  </body>
</html>
test.js
var ajaxReq;
​
function checkUserName(){
    //发送ajax请求到CheckUserNameServlet,并将用户名传递
    //1、创建ajax请求对象
    if(window.XMLHttpRequest){
        ajaxReq = new XMLHttpRequest();
    }else{
        ajaxReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    console.log("---------"+ajaxReq.readyState);
​
    //2、封装ajax请求数据(初始化)
    var userName = document.getElementById("userName").value;
    var method = "GET";
    var url = "CheckUserNameServlet?userName="+userName;
    var async = true;
    ajaxReq.open(method,url,async);
    console.log("---------"+ajaxReq.readyState);
​
    //3、指定ajax请求的回调函数
    // ajaxReq请求对象是有状态的,可以通过ajaxReq.readyState获取状态值
    // ajaxReq请求对象的不同状态值表示异步交互的不同阶段
    // ajaxReq.readyState == 0  表示ajax请求对象完成创建但并未初始化
    // ajaxReq.readyState == 1  表示ajax请求对象完成初始化但未发送请求
    // ajaxReq.readyState == 2  表示ajax请求已经发送并到达服务器
    // ajaxReq.readyState == 3  表示服务器正在处理ajax请求(通信....)
    // ajaxReq.readyState == 4  表示服务器正处理完成,ajax请求对象已经成功获取响应结果
​
    // 只要ajax请求状态发送变化,就会触发这个回调函数的执行
    ajaxReq.onreadystatechange = callback;
​
    //4、发送请求
    ajaxReq.send(null);
}
​
//回调函数:处理结果
function callback(){
    //获取服务器响应结果的两个条件:
    //1.异步请求完成 ajaxReq.readyState == 4
    //2.http状态为200  ajaxReq.status == 200
    if(ajaxReq.readyState == 4 && ajaxReq.status == 200){
        //获取结果
        // 如果服务器响应的是文本数据(字符串),使用responseText属性接收
        var result = ajaxReq.responseText;
        // 如果服务器响应的是XML文件,使用responseXML属性接收
        // var doc = ajaxReq.responseXML;
        // 将获取的响应结果显示到网页的标签中
        document.getElementById("tipsLabel").innerHTML = result;
    }
}

23.什么是JDBC?

JDBC的全称是Java DataBase Connection,也就是Java数据库连接,我们可以用它来操作关系型数据库。 JDBC接口及相关类在java.sql包和javax.sql包里。 我们可以用它来连接数据库,执行SQL查询,存储过程,并处理返回的结果。

24.常见的JDBC异常有哪些?

  • java.sql.SQLException:JDBC异常的基类。

  • java.sql.BatchUpdateException:当批处理操作执行失败的时候可能会抛出这个异常。这取决于具体的JDBC驱动的实现,它也可能直接抛出基类异常java.sql.SQLException中。

  • java.sql.SQLWarning:SQL操作出现的警告信息。

  • java.sql.DataTruncation:字段值由于某些非正常原因被截断了

25.JDBC的DataSource是什么,有什么好处?

在Java中,DataSource是一个接口,它提供了一种标准方式来获取数据库连接。DataSource的实现类通常由数据库厂商或第三方框架提供,它封装了数据库连接池的功能,并提供了一些额外的优势。

DataSource的好处如下:

  1. 连接池管理:DataSource可以通过连接池管理数据库连接,连接池维护了一定数量的数据库连接,可以重复使用已经创建的连接,避免了频繁地创建和关闭数据库连接的开销,提高了性能。

  2. 连接资源控制:DataSource可以对数据库连接进行资源控制,例如最大连接数、最小连接数、连接超时等配置,防止因为连接过多而导致数据库负荷过大或资源耗尽的情况。

  3. 连接的可靠性:DataSource可以自动检测连接的可用性,在连接异常或失效时自动重新连接或从连接池中移除不可用的连接,提高了数据库连接的可靠性。

  4. 事务管理:DataSource可以与事务管理器(例如Java中的JTA)配合使用,提供了对分布式事务的支持,确保数据库操作的一致性和完整性。

  5. 配置的灵活性:DataSource通常提供了丰富的配置选项,可以根据应用程序的需求进行灵活的配置,例如连接超时时间、连接池大小、连接验证等,使得应用程序可以根据实际情况进行优化和配置调整。

使用DataSource需要以下步骤:

  1. 配置DataSource:根据具体的DataSource实现类提供的方式,配置数据库连接的相关参数,例如数据库URL、用户名、密码、连接池大小等。

  2. 获取Connection对象:通过调用DataSource的getConnection方法获取一个数据库连接,该方法会从连接池中获取可用的连接或创建一个新的连接。

  3. 执行SQL操作:使用获取到的Connection对象执行数据库的相关操作,例如执行查询、更新等操作。

  4. 关闭连接:在使用完Connection后,需要将其归还给连接池,通过调用Connection的close方法来释放连接资源。

总之,使用DataSource可以实现对数据库连接的管理和优化,提高了数据库访问的性能和可靠性,并且提供了更灵活的配置选项。这使得应用程序在处理数据库连接时更加方便和高效。

26.HTTP中重定向和请求转发的区别?

本质区别:

  • 转发是服务器行为

  • 重定向是客户端行为

重定向特点:两次请求,浏览器地址发生变化,可以访问自己 web 之外的资源,传输的数据会丢失。

请求转发特点:一次强求,浏览器地址不变,访问的是自己本身的 web 资源,传输的数据不会丢失。

27.如何利用实现自动登录?

当用户在某个网站注册后,就会收到一个唯一用户ID的cookie。客户后来重新连接时,这个用户ID会自动返回,服务器对它进行检查,确定它是否为注册用户且选择了自动登录,从而使用户务需给出明确的用户名和密码,就可以访问服务器上的资源。

28.Cookie的过期和Session的超时有什么区别?

Cookie的过期和Session的超时(过期),都是对某个对象设置一个时间,然后采用轮训机制(或者首次访问时)检查当前对象是否超时(当前对象会保存一个开始时间),如果超时则进行移除。 cookie保存在浏览器中,不安全。而session是保存在服务端的。cookie的生命周期很长,而session很短,一般也就几十分钟。

cookie是保存在客户端,session保存在服务器端,cookie保存着session相关信息。 如果cookie没有超时,那么浏览器每次请求都会带上该cookie信息,服务器端根据cookie信息从session缓存中获取相对应的session。这两个信息有一个超时,用户连接即宣告关闭。

会话的超时由服务器来维护,它不同于Cookie的失效日期。 首先,会话一般基于驻留内存的cookie,不是持续性的cookie,因而也就没有截至日期。 即使截取到JSESSIONID cookie,并为它设定一个失效日期发送出去。浏览器会话和服务器会话也会截然不同。

29.在单点登录中,如果 cookie 被禁用了怎么办?

单点登录的原理是后端生成一个 session ID,然后设置到 cookie,后面的所有请求浏览器都会带上 cookie,然后服务端从 cookie 里获取 session ID,再查询到用户信息。 所以,保持登录的关键不是 cookie,而是通过cookie 保存和传输的 session ID,其本质是能获取用户信息的数据。 除了 cookie,还通常使用 HTTP 请求头来传输。但是这个请求头浏览器不会像 cookie 一样自动携带,需要手工处理。

30.session何时被删除?

  • 程序调用HttpSession.invalidate()

  • 距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间

  • 服务器进程被停止

  • 注意关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象失效。

31-40

31.什么是过滤器?

过滤器(Filter)是位于客户端与服务器资源之间的一道过滤技术,可以在客户端请求到达目标资源之前进行预处理业务。

过滤器使用

创建过滤器

在doFilter编写过滤业务规则,如果允许继续访问,则通过filterChain.doFilter(servletRequest,servletResponse);让客户端请求继续访问;如果不允许通行则可以通过servletResponse直接响应客户端(转发、重定向)。

package com.qfedu.filters;
​
import javax.servlet.*;
import java.io.IOException;
​
/**
 * @Description
 * @Author 千锋涛哥
 * 公众号: Java架构栈
 * 1.创建一个类实现javax.servlet.Filter接口
 * 2.实现Filter接口中的init、doFilter、destroy抽象方法
 *    init 是过滤器初始化方法,用于获取过滤器的初始化参数等
 *    destory 是过滤器的销毁方法,用以释放资源
 *    doFilter 方法 用于定义过滤器的业务
 * 3.在doFilter实现过滤器业务
 */
public class MyFilter01 implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("~~~~~~MyFilter01");
        //放行:运行继续执行浏览器请求的目标资源
        filterChain.doFilter(servletRequest,servletResponse);
    }
​
    @Override
    public void destroy() {
    }
}
​
配置过滤器

配置过滤器拦截哪些服务器资源

  • xml配置

    <filter>
        <filter-name>MyFilter01</filter-name>
        <filter-class>com.qfedu.filters.MyFilter01</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter01</filter-name>
        <!--过滤器的拦截规则-->
        <url-pattern>/FirstServlet</url-pattern>
    </filter-mapping>
  • 注解配置:在过滤器类添加@WebFilter注解

    @WebFilter("/*")
    public class MyFilter01 implements Filter {
        //...
    }

过滤器路径配置规则

精确过滤: 配置过滤器拦截指定的请求url

例如:/FirstServlet,/index.html

后缀过滤: 配置过滤器拦截指定的后缀的请求url

例如:*.jpg 、 *.html

通配符过滤

  • /* 拦截所有请求

  • /aaa/bbb/* 拦截项目名后 demo8/aaa/bbb/FirstServlet 或者 demo8/aaa/bbb/a.html

前置过滤器与后置过滤器

根据过滤器在目标资源执行的时机,我们可以将过滤器分为三类:

  • 前置过滤器:过滤器在目标资源之前执行

  • 后置过滤器:过滤器在目标资源之后执行

  • 环绕过滤器:执行目标资源之前会执行过滤器,目标资源执行之后还会执行过滤器

如何设置前置、后置、环绕过滤器?

  • 在过滤器的doFilter方法中,写在放行代码(filterChain.doFilter(...))业务会在目标资源执行之前执行,写在放行代码后面的业务,则会在目标资源执行之后执行

@WebFilter("/FirstServlet")
public class MyFilter01 implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("~~~~~~before");
        //放行:运行继续执行浏览器请求的目标资源
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("~~~~~~after");
    }
​
    @Override
    public void destroy() {
    }
}

32.什么是监听器?

定义:: 实现了javax.servlet.ServletContextListener 接口的服务器端程序; 随web应用的启动而启动;只初始化一次; 随web应用的停止而销毁;

作用:: 做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。如SpringMVC的监听器org.springframework.web.context.ContextLoaderListener,实现了SpringMVC容器的加载Bean对象创建DispatchServlet初始化等。

33.什么是拦截器?

依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架; 在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用; 缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理;

由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。

34.过滤器和拦截器的区别?

拦截器过滤器
基于Java反射机制基于函数回调
不依赖Servlet容器依赖Servlet容器
只能对action起作用几乎对所有请求起作用
可以访问action上下文,值栈里的对象可以访问action上下文,值栈里的对象
在Action生命周期中,拦截器可以多次被调用过滤器只能在容器初始化时被调用一次
拦截器不能修改request过滤器可以修改request
拦截器可以调用IOC容器中的各种依赖过滤器不能调用IOC容器中的各种依赖
拦截器可以详细到每个方法过滤器只能在请求的前后使用

过滤器主要是过滤出要的东西,如requeset中的信息;拦截器在做安全方面用的比较多,比如终止一些流程

35.Servlet与Filter的区别?

Filter是一种特别的Servlet,它们的作用是完全不一样的。 Servlet是用来处理请求的,而Filter是用来过滤检查请求的。

36.web.xml 的作用?

用于配置Web应用的相关信息 如:监听器(listener)、过滤器(filter)、 Servlet、相关参数、会话超时时间、安全验证方式、错误页面等。

37.filter的生命周期?

  • 启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;

  • 每一次请求时都只调用方法doFilter()进行处理;

  • 停止服务器时调用destroy()方法,销毁实例。

  • 需要实现javax.servlet包的Filter接口的三个方法init()doFilter()destroy()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿人啊兴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值