Servlet
项目结构
CS 结构
Client Server 客户端服务,要在客户端进行安装后才可以正常使用的软件,例如:QQ、微信、钉钉 等
BS 结构
Browser Server 浏览器服务,通过浏览器直接访问的软件项目,例如:通义千问、文心一言、讯飞等
服务器
服务器分为:硬件服务器和软件服务器。
硬件服务器:IBM、HP、HUAWEI。
软件服务器:Tomcat(Apache)、Weblogic(Oracle)、Websphere(IBM)等
下载配置 Tomcat
IDEA 配置 Tomcat
Servlet
1.1、简介
Servlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。 它担当客户请求与服务器响应的中间层 ,是单进程多线程程序。它担任着客户端与服务器的中间组件,执行的流程是客户端发送请求至服务器端服务器将请求信息发送至Servlet;Servlet根据业务逻辑生成响应内容 服务器将响应返回给客户端。
1.2、IDEA 创建 Servlet 工程
见 Maven 笔记,此处省略
1.3、发布 web 工程
名称起好以后,点击 Apply—>OK,推荐重启 Tomcat 服务器,即可完成 web 工程发布。
1.4、使用 Servlet 完成登录注册
见课堂代码,此处省略
1.5、Ajax
1.5.1、 概念
AJAX(Asynchronous JavaScript And XML)是一种在 Web 应用中通过异步发送 HTTP 请求向服务器获取内容,并使用这些新内容更新页面中相关的部分,而无需重新加载整个页面的 Web 开发技术。这可以让网页更具有响应性,因为只请求了需要更新的部分。
1.5.2、原生 Ajax 实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>注册界面</title>
<link href="./bootstrap-5.3.3-dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="./bootstrap-5.3.3-dist/modals.css" rel="stylesheet"/>
<style>
#modalSignin
{
height: 740px;
}
</style>
</head>
<body>
<div class="modal modal-sheet position-static d-block bg-body-secondary p-4 py-md-5" tabindex="-1" role="dialog" id="modalSignin">
<div class="modal-dialog" role="document">
<div class="modal-content rounded-4 shadow">
<div class="modal-header p-5 pb-4 border-bottom-0">
<h1 class="fw-bold mb-0 fs-2">注册界面</h1>
</div>
<div class="modal-body p-5 pt-0">
<form action="/javawebdemo/register" method="post">
<div class="form-floating mb-3">
<input type="text" class="form-control rounded-3" value="" name="username" id="floatingInput" placeholder="Username">
<label for="floatingInput">请输入用户名</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control rounded-3" value="" name="userpwd" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">请输入密码</label>
</div>
<div class="form-floating mb-3">
<input type="number" class="form-control rounded-3" value="" name="userage" id="Userage" placeholder="Userage">
<label for="Userage">请输入年龄</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="usersex" value="男" id="flexRadioDefault1">
<label class="form-check-label" for="flexRadioDefault1">
男
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="usersex" value="女" id="flexRadioDefault2">
<label class="form-check-label" for="flexRadioDefault2">
女
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="usersex" value="保密" id="flexRadioDefault3" checked>
<label class="form-check-label" for="flexRadioDefault3">
保密
</label>
</div>
<button class="w-100 mb-2 btn btn-lg rounded-3 btn-primary" type="submit">注册</button>
<hr class="my-4">
<span id="msg"></span>
</form>
</div>
</div>
</div>
</div>
</body>
<script>
//创建XMLHttpRequest对象
var XMLHttpRequest = new XMLHttpRequest();
document.getElementById("floatingInput").onblur = function ()
{
console.log(this.value);
let uname = this.value;
//true表示异步请求
//XMLHttpRequest.open("GET","http://localhost:8080/javawebdemo/queryUsername?username="+uname,true);
XMLHttpRequest.open("POST","http://localhost:8080/javawebdemo/queryUsername",true);
//POST请求时,必须要设置请求头
XMLHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
XMLHttpRequest.onreadystatechange = function () {
console.log(XMLHttpRequest.readyState)
console.log("status --- ",XMLHttpRequest.status)
//当请求响应完成以后,判断请求是否成功,4表示请求响应完成
if(XMLHttpRequest.readyState == 4)
{
//判断请求成功
if(XMLHttpRequest.status == 200)
{
//当前请求成功以后,获取服务器响应的数据
let respText = XMLHttpRequest.responseText;
console.log(respText);
if(respText == "OK")
{
alert(uname+"可以使用!");
}
else
{
alert(uname+"已存在,请换一个用户名");
}
}
}
};
XMLHttpRequest.send("username="+uname);
}
</script>
</html>
1.5.3、JQueryAjax
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>注册界面</title>
<link href="./bootstrap-5.3.3-dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="./bootstrap-5.3.3-dist/modals.css" rel="stylesheet"/>
<script src="js/jquery-3.7.1.min.js"></script>
<style>
#modalSignin
{
height: 740px;
}
</style>
</head>
<body>
<div class="modal modal-sheet position-static d-block bg-body-secondary p-4 py-md-5" tabindex="-1" role="dialog" id="modalSignin">
<div class="modal-dialog" role="document">
<div class="modal-content rounded-4 shadow">
<div class="modal-header p-5 pb-4 border-bottom-0">
<h1 class="fw-bold mb-0 fs-2">JQuery注册界面</h1>
</div>
<div class="modal-body p-5 pt-0">
<form action="/javawebdemo/userservlet" method="post">
<input type="text" value="register" name="method" hidden/>
<div class="form-floating mb-3">
<input type="text" class="form-control rounded-3" value="" name="username" id="floatingInput" placeholder="Username">
<label for="floatingInput">请输入用户名</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control rounded-3" value="" name="userpwd" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">请输入密码</label>
</div>
<div class="form-floating mb-3">
<input type="number" class="form-control rounded-3" value="" name="userage" id="Userage" placeholder="Userage">
<label for="Userage">请输入年龄</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="usersex" value="男" id="flexRadioDefault1">
<label class="form-check-label" for="flexRadioDefault1">
男
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="usersex" value="女" id="flexRadioDefault2">
<label class="form-check-label" for="flexRadioDefault2">
女
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="usersex" value="保密" id="flexRadioDefault3" checked>
<label class="form-check-label" for="flexRadioDefault3">
保密
</label>
</div>
<button class="w-100 mb-2 btn btn-lg rounded-3 btn-primary" type="submit">注册</button>
<hr class="my-4">
<span id="msg"></span>
</form>
</div>
</div>
</div>
</div>
</body>
<script>
$(function () {
$("#floatingInput").blur(function ()
{
let uname = $(this).val();
console.log(`uname = ${uname}`);
$.ajax({
/*type: "GET",
url: "http://localhost:8080/javawebdemo/queryUsername?username="+uname,*/
type: "POST",
url: "http://localhost:8080/javawebdemo/userservlet",
data: "method=queryUserName&username="+uname,
success: function (data)
{
if(data == "OK")
{
alert(uname+"可以使用!");
}
else if(data == "NO")
{
alert(uname+"已存在,请换一个用户名");
}
else
{
alert("用户名不能为空")
}
}
});
});
});
</script>
</html>
1.6、Servlet 生命周期
1.7、MVC
MVC (Model View Controller)是一个设计模式 ,把视图、控制、模型各自分开,处理各自的事情,以达到软件开发最优化。
M 用户名和密码验证过程
V 用户表单输入界面和显示用户登录信息界面
C 用servlet请求转发控制
1.8、过滤器
1.8.1、 什么是 Servlet 过滤器
过滤器是一个程序,它先于与之相关的其他程序运行在服务器上。过滤器可附加到一个或多个其他的程序上,并且可以检查进入这些资源的请求信息。而Servlet 过滤器就是在执行运行某个具体的Servlet 之前要执行的一段程序。与之相关的还有一个叫过滤器链,就是把多个过滤器组合在一起形成了一个链,比如对用户登录的过滤和编码的过滤就组成了一个过滤器链
1.8.2、 登录过滤器实现
package com.wlx.day02;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebFilter("/*")
public class MyFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter----------");
}
/**
* 过滤业务处理方法
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//获取Session对象
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
System.out.println("***************"+req.getRequestURI());
String uri = req.getRequestURI();
if(uri.endsWith("main.html"))
{
Object userinfo = session.getAttribute("userinfo");
//如果userinfo不等于null,则放行,通过过滤器,允许继续访问
if(userinfo != null)
{
chain.doFilter(request,response);
}
else
{
//如果userinfo等于null,则重定向到login页面
HttpServletResponse resp = (HttpServletResponse) response;
resp.sendRedirect("login2.html");
}
}
else
{
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
System.out.println("Filter---destroy------");
}
}
1.9、监听器
1.9.1、什么是监听器
Servlet的作用除了页面控制跳转、功能过滤,还有监听器,监听器就是事件触发器,类似于JS中的事件Servlet监听的对象主要分为 ServletContext、ServletRequest、HttpSession它用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理,作用在于:监听三个域对象的创建和销毁的事件监听域对象中属性的增加和删除的事件监听绑定到 HttpSession 域中的某个对象的状态的事件监听器.
1.9.2、实现监听器
package com.wlx.day02;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyListener implements ServletRequestAttributeListener
{
/**
* 当向request作用域中添加属性时,触发该方法
*/
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
System.out.println("Add-----"+srae.getName()+"---"+srae.getValue());
}
/*
当从request作用域中删除属性时,触发该方法
*/
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
System.out.println("Removed-----"+srae.getName()+"---"+srae.getValue());
}
/*
当对request作用域中的属性进行修改时,除非该方法
*/
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
System.out.println("Replaced-----"+srae.getName()+"---"+srae.getValue());
}
}
1.10、跳转和重定向
重定向
(1)、重定向是客户端行为。(浏览器重新请求)
(2)、重定向是浏览器做了至少两次的访问请求的(当然也可以重定向多次)。
(3)、定向浏览器地址改变。
(4)、重定向两次跳转之间传输的信息会丢失(request范围)。
(5)、重定向可以指向任何的资源,包括当前应用程序中的其他资源,同一个站点上的其他应用程序
中的资源,其他站点的资源。
跳转
1,跳转是服务器行为(这是不经过浏览器的)
2,跳转是浏览器只做了一次访问请求
3,跳转浏览器地址不变
4,跳转之间传输的信息不会丢失,所以可以通过request进行数据的传递
5,跳转只能将请求转发给同一个WEB应用中的组件
注意:如果创建RequestDispatcher 对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
Log4j
1.1、什么是 Log4j
Log 是日志,是记录程序的走向,有助于分析程序的信息,而log4j则是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件等;我们也可以控制每一条日志的输出格式,通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码 。
Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。
1.2、Log4j 配置文件
log4j.rootLogger=DEBUG, stdout, logfile,sql
#控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
#文件日志
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=d:/logfile.txt
log4j.appender.logfile.MaxFileSize=1024KB
log4j.appender.logfile.MaxBackupIndex=5
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
1.3、实现日志
package com.wlx.day02;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class Log4jDemo
{
public static void main(String[] args) {
//创建日志对象
Logger rootlogger = Logger.getLogger(Log4jDemo.class);
//加载日志配置文件
PropertyConfigurator.configure("/log4j.properties");
//指定输出的日志信息
rootlogger.debug("log4jdebug------");
rootlogger.info("log4jInfo------");
rootlogger.warn("log4jWarn-------");
}
}