JavaWeb面试题
1-10
1.说一说Servlet的生命周期?
Servlet的生命周期包括以下几个阶段:
初始化阶段(Initialization):在容器启动时,Servlet容器会调用Servlet的init()方法来进行初始化操作。在这个阶段,可以进行一些必要的设置和资源加载,例如数据库连接的建立。
请求处理阶段(Request Handling):一旦Servlet初始化完成后,它就可以接受客户端的请求,并根据请求的类型执行相应的操作。每个请求都会由Servlet容器创建一个新的线程来处理,并调用Servlet的service()方法来处理请求。
服务阶段(Service):在服务阶段,Servlet容器会根据请求的类型,调用合适的doGet()、doPost()、doPut()等方法来处理请求并生成响应。开发者需要根据具体的需求,在这些方法中编写相应的业务逻辑代码。
销毁阶段(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()的区别?
从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.所以redirect等于客户端向服务器端发出两次request,同时也接受两次response。
从数据共享来说 forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据.
redirect不仅可以重定向到当前应用程序的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源. forward方法只能在同一个Web应用程序内的资源之间转发请求.forward 是服务器内部的一种操作.
redirect 是服务器通知客户端,让客户端重新发起请求. 所以,你可以说 redirect 是一种间接的请求, 但是你不能说”一个请求是属于forward还是redirect “
从运用地方来说 forward:一般用于用户登陆的时候,根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.
从效率来说 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()有何区别?
request.getParameter()取得是通过容器的实现来取得通过类似post,get等方式传入的数据。request.setAttribute()和getAttribute()只是在web容器内部流转,仅仅是请求处理阶段。
getAttribute是返回对象,getParameter返回字符串
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 有什么区别?
jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
jsp更擅长表现于页面显示,servlet更擅长于逻辑控制。
Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到。
Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。
9.tomcat容器是如何创建servlet类实例?用到了什么原理?
当容器启动时,会读取在webapps目录下所有的web应用中的web.xml文件,然后对xml文件进行解析,并读取servlet注册信息。然后,将每个应用中注册的servlet类都进行加载,并通过反射的方式实例化。(有时候也是在第一次请求时实例化) 在servlet注册时加上1如果为正数,则在一开始就实例化,如果不写或为负数,则第一次请求实例化。
10.如何避免 sql 注入?
预编译PreparedStatement(简单又有效的方法)
使用正则表达式过滤传入的参数
字符串过滤
JSP中调用该函数检查是否包函非法字符
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();
一个事务中的多个DML操作需要基于同一个数据库连接;
创建连接之后,设置事务手动提交(关闭自动提交);
connection.setAutoCommit(false);
当当前事务中的所有DML操作完成之后手动提交;
connection.commit();
当事务中的任何一个步骤出现异常,在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的区别是什么?
Statement的execute(String query)方法用来执行任意的SQL查询,如果查询的结果是一个ResultSet,这个方法就返回true。
如果结果不是ResultSet,比如insert或者update查询,它就会返回false。我们可以通过它的getResultSet方法来获取ResultSet,或者通过getUpdateCount()方法来获取更新的记录条数。
Statement的executeQuery(String query)接口用来执行select查询,并且返回ResultSet。即使查询不到记录返回的ResultSet也不会为null。
我们通常使用executeQuery来执行查询语句,这样的话如果传进来的是insert或者update语句的话,它会抛出错误信息为 “executeQuery method can not be used for update”的java.util.SQLException。 ,
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的好处如下:
连接池管理:DataSource可以通过连接池管理数据库连接,连接池维护了一定数量的数据库连接,可以重复使用已经创建的连接,避免了频繁地创建和关闭数据库连接的开销,提高了性能。
连接资源控制:DataSource可以对数据库连接进行资源控制,例如最大连接数、最小连接数、连接超时等配置,防止因为连接过多而导致数据库负荷过大或资源耗尽的情况。
连接的可靠性:DataSource可以自动检测连接的可用性,在连接异常或失效时自动重新连接或从连接池中移除不可用的连接,提高了数据库连接的可靠性。
事务管理:DataSource可以与事务管理器(例如Java中的JTA)配合使用,提供了对分布式事务的支持,确保数据库操作的一致性和完整性。
配置的灵活性:DataSource通常提供了丰富的配置选项,可以根据应用程序的需求进行灵活的配置,例如连接超时时间、连接池大小、连接验证等,使得应用程序可以根据实际情况进行优化和配置调整。
使用DataSource需要以下步骤:
配置DataSource:根据具体的DataSource实现类提供的方式,配置数据库连接的相关参数,例如数据库URL、用户名、密码、连接池大小等。
获取Connection对象:通过调用DataSource的getConnection方法获取一个数据库连接,该方法会从连接池中获取可用的连接或创建一个新的连接。
执行SQL操作:使用获取到的Connection对象执行数据库的相关操作,例如执行查询、更新等操作。
关闭连接:在使用完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()