JSP感觉实际开发用处不是很大,这里不再记录
监听器个人觉得由前端来做更合适并且更方便一些,所以也不再记录
这里使用Intelligent Idea开发,Tomcat和Maven的安装配置不再赘述
所以Tomcat和Maven的知识点还需要自己去了解一下
什么是Servelet
Servelet是动态开发Web的一门技术
就是给你配置好了一堆交互操作的接口,然后你自己去实现一下。
(如果不想手动实现,就直接一手继承内置实现就来了)
如何使用Servelet
1.首先编写一个类,实现Servelet接口
2.然后把开发好的java类部署到Web服务器
这其中,实现了Servelet接口的java程序就叫做Servelet
正式开始使用Servelet
1.先建立一个Maven项目(除了自定义名称之外只管点击下一步就行,这里叫做ServeletLearner)然后删除其中的src目录,这样就得到了Maven的主工程
2.建立父子模块
如果不知道该导入什么依赖,可以去这里Maven依赖查询
官网的关系对应图如下
IDEA中如果配置了较新版本的Maven那么只需要如下代码即可
(Tomcat10.x及以上版本需要注意,依赖名称已经发生了变化,据说是因为oracle把tomcat捐给了apache?)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>ServeletLearnerartifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>jakarta.servlet.jspgroupId>
<artifactId>jakarta.servlet.jsp-apiartifactId>
<version>3.0.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>jakarta.servletgroupId>
<artifactId>jakarta.servlet-apiartifactId>
<version>5.0.0version>
<scope>providedscope>
dependency>
dependencies>
project>
这样就配置好了一个父级Module
然后新建一个模块,勾选图示选项
然后下一步,就出现了这个界面
可以看到有了父级这个选项
这样操作就得到了一个子模块,
之后的操作只需要在子模块上进行,而不用改动父模块
3.开始编写Servelet程序
先建立一个普通类,然后要知道Servelet有一个默认的实现类HttpServelet(其实还有一个Generic,HttpServelet就是继承的这个),可以直接用
这里是重写一下方法
由于版本太高,所以导入的包是jakarta
(低版本是javax,反正就这两个,一个不行就换另一个)
package com.serio.servelet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServelet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
//上面这个是默认的
//接下来我们重写
System.out.println("芜湖,起飞2333");
PrintWriter writer = resp.getWriter();//响应流
writer.print("HelloServelet");
}
}
4.编写Servelet的映射
为什么要写映射:因为写的是java程序,但是要用浏览器访问,而浏览器是链接web服务器,所以我们要在web服务中注册我们写的servelet并且给他一个可以访问的路径。
<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-name>HelloServeletservlet-name>
<servlet-class>com.serio.servelet.HelloServeletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>HelloServeletservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
web-app>
这里就是访问到/hello这一级的时候发生以下操作:
如果访问/hello的方式又恰巧是我们重写的doGet的话,那么这里就会触发doGet
(这个其实有点像Vue的生命周期钩子)
5.配置Tomcat
这个大家会的都会,就照着图片顺序点一下
手动在后面加一个/hello,这样是get请求
就会出现以下情况
servelet就是这样,简直不要太舒服
6优先级问题
制定了固有的映射路径的优先级最高,其次才是固有路径
比如重新写404页面
然后写上以下代码
package com.example.ServeletRelearner;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;
import java.io.*;
//import jakarta.
public class ErrorServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.print("你的页面404了诶
");
}
}
<servlet>
<servlet-name>errorservlet-name>
<servlet-class>com.example.ServeletRelearner.ErrorServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>errorservlet-name>
<url-pattern>/404url-pattern>
servlet-mapping>
样式方面呢就先不要在意那么多,能访问就算成功
这里可能会出现路径冲突时的优先级的问题,这里的优先级类似于前端的CSS选择器的优先级,不再赘述。
至于Tomcat可能存在的乱码问题
只需要找到Tomcat 的 conf文件夹下的logging.properties文件,修改其中第五十一行的值为GBK,重启Tomcat即可解决
就是Servelet的上下文
是web容器在启动的时候,会为每一个web程序创建一个对应的ServeletContext对象,这个对象代表了当前的web应用.
首先来拿到一个ServeletContext
首先要导包,idea应该会提醒你这么做
import jakarta.servlet.ServletContext;
ServletContext context = this.getServletContext();
能用它实现
共享数据
即在这个Servelet中保存的数据可以在另一个servelet中使用
在HelloServlet中设置一个键值对属性
context.setAttribute("someAttr",2333);
然后再ErrorServlet中可以拿到
ServletContext context2 = this.getServletContext();
Integer s = (Integer)context2.getAttribute("someAttr");
System.out.println("这是拿到的属性" + s);
返回的其实是一个对象,但是这里由于我们知道是字符串,所以直接强转了
这里是我疏忽了,直接访问了/404,但是设置属性是在访问/hello的时候触发的,所以我这样操作就导致了还没设置就试图获取,就只能拿到null
接下来先访问/hello再访问/404试试看
其他形式
在web.xml里面配置一下初始化信息
<context-param>
<param-name>someParamparam-name>
<param-value>"这是一个param"param-value>
context-param>
然后再到servlet里面操作:
String s = context.getInitParameter("someParam");
System.out.println(s);
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表该请求的HttpServletRequest对象,和一个代表响应的HttpServletResponse对象
我们如果要获取客户端请求过来的参数,就使用HttpServletRequest
我们如果要获取客户端响应的信息,那么使用HttpServletResponse
**
来试试利用这个下载一个文件看看
直接新建一个FileServlet
(这里我才发现之前一直打的Servelet是错误的…)
相关操作的意义我都写到注释里面了
package com.example.ServeletRelearner;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取要下载的文件的路径
String realPath = "E:\\COMPILE\\JAVA\\ServeletRelearner\\src\\main\\resources\\img.png";
System.out.println("下载文件的路径为:" + realPath);
//2.下载文件的名字 这里用了一个极为巧妙的方式来获取到末尾的img.png
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
System.out.println("文件名字是:" + fileName);
//3.设置想办法能让浏览器支持(Content-Disposition)下载
resp.setHeader("Content-Disposition","attachment;filename=" + fileName);
//4.获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
//5.创建缓冲区(buffer
int len = 0;
byte[] buffer = new byte[1024];
//6.获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
//7.将FileOutputStream流写入到缓冲区(buffer
while(in.read(buffer)>0){
out.write(buffer,0,len);
}
in.close();
out.close();
//8.使用OutputStream将缓冲区的数据输出到客户端
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
配置一下Servlet
<servlet>
<servlet-name>filedownservlet-name>
<servlet-class>com.example.ServeletRelearner.FileServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>filedownservlet-name>
<url-pattern>/downurl-pattern>
servlet-mapping>
从结果上看是下载了一个文件(虽然打不开,可能是请求头设置的问题吧),那么其他类似的操作就可以依葫芦画瓢
突然觉得js是个什么缝合怪…这不是和canvas几乎一样吗…
package com.example.ServeletRelearner;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//浏览器刷新(3s
// resp.setHeader("refresh","3");
//在内存中创建一张图片(看不懂,不过先这么写吧,前两个参数是宽高,第三个猜测是颜色模式之类的应该可以不管
BufferedImage image = new BufferedImage(80,30,BufferedImage.TYPE_INT_RGB);
//掏出画笔
Graphics2D pen = (Graphics2D) image.getGraphics();
//先选取颜色
pen.setColor(Color.gray);
//画一个方块 参数:x y 宽 高
pen.fillRect(0,0,80,30);
//换颜色开始写字
pen.setColor(Color.black);
//设置字体
pen.setFont(new Font(null, Font.BOLD,20));
//开始画,参数分别是 内容 x y
pen.drawString(randomNum(),0,30);
//告诉浏览器用图片形式打开
resp.setContentType("image/jpeg");
//缓存设置:不缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
boolean write = ImageIO.write(image,"jpeg",resp.getOutputStream());
System.out.println(23333);
}
private String randomNum(){
Random random = new Random();
String num = random.nextInt(99999) + "";
StringBuffer s = new StringBuffer();
// 强行填成五位数
for(int i = 0;i < 5 - num.length();i ++){
s.append("" + random.nextInt(9));
}
num = s.toString() + num;
return num;
}
}
<servlet>
<servlet-name>imageservlet-name>
<servlet-class>com.example.ServeletRelearner.ImageServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>imageservlet-name>
<url-pattern>/imageurl-pattern>
servlet-mapping>
但是这个还是没有前端写一个方便…所以个人倾向于用前端的技术来写
(图片来自网络)
重定向与转发之区别:
重定向-----这个别找我,你去找xxx(url会变化)
转发--------我去帮你找xxx(url不会变化)
package com.example.ServeletRelearner;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("image");
}
}
<servlet>
<servlet-name>redirectservlet-name>
<servlet-class>com.example.ServeletRelearner.RedirectServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>redirectservlet-name>
<url-pattern>/redirecturl-pattern>
servlet-mapping>
然后我们去访问/redirect,它就会自动跳转到/image
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息都会被封装到HttpServletRequest中,这样一来我们就方便获取到所有的信息了
比如说
这里运用req.getParameter()方法
这个方法的参数是想要获取的参数的名称
package com.example.ServeletRelearner;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Request extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("成功访问");
resp.sendRedirect("success.jsp");
}
}
然后同样的是需要配置servlet
<servlet>
<servlet-name>requestservlet-name>
<servlet-class>com.example.ServeletRelearner.Requestservlet-class>
servlet>
<servlet-mapping>
<servlet-name>requestservlet-name>
<url-pattern>/loginurl-pattern>
servlet-mapping>
解下来我们准备两个JSP页面
JSP就是HTML中可以植入JAVA
据大佬说JSP原理其实是JAVA的resp.getWriter().print();一行一行打印HTML
这是第一个JSP页面
表单中的pageContext.request.contextPath可以理解为当前项目的路径
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
DOCTYPE html>
<html>
<head>
<title>JSP - Hello Worldtitle>
head>
<body>
<h1><%= "Hello World!" %>h1>
<%-- <a href="hello-servlet">Hello Servleta>--%>
<form action="${pageContext.request.contextPath}/login" method>
<div class="login">
<form action="" method="GET">
<h5>用户名h5>
<input type="text" name="username"><br>
<h5>密码h5>
<input type="text" name="password"><br>
<input type="submit" value="登陆">
form>
div>
body>
html>
这是第二个
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆后的页面title>
head>
<body>
<h1>成功h1>
body>
html>
原理是我们再第一个JSP页面访问/login,这样一来就触发了重写后的doGet方法中的重定向,从而跳转到新的页面
其实还有req.getParameterValues方法获取多组数据(比如checkbox多选中的选项),接收用数组来做就行了
用户打开一个浏览器,点了很多超链接,访问了多个web资源——这个过程,可以被称之为会话
**有状态会话:
**服务端能够证明某个客户端访问过的方式
一种是让客户端带上一个标记,也就是cookie
另一种是服务端上登记,也就是session
Cookie是客户端技术(响应,请求)
Session是服务器技术,保存用户信息
这里我们使用后端添加cookie,前端读取cookie
我们在原来的request中添加一个cookie
package com.example.ServeletRelearner;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class Request extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("成功访问");
// System.out.println(req.getParameter("remember"));
if(req.getParameter("remember").equals("on")){
System.out.println("成功进入");
//实例化一个cookie对象,设置生命周期为24小时,添加cookie
Cookie cookie = new Cookie("username",username);
cookie.setMaxAge(24 * 60 * 60);
resp.addCookie(cookie);
cookie = new Cookie("password",password);
cookie.setMaxAge(24 * 60 * 60);
resp.addCookie(cookie);
}
System.out.println("用户名: " + username);
System.out.println("密码: " + password);
resp.sendRedirect("success.jsp");
}
}
如果无误,那么在第一次登陆之后就能在图示位置找到这样的信息
然后使用前端访问cookie并将其中的值赋给input的value属性
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%--<%--%>
<%--String username = "";--%>
<%--String password = "";--%>
<%--%>--%>
DOCTYPE html>
<html>
<head>
<title>JSP - Hello Worldtitle>
<style>
.loginForm{
display: inline-block;
width: 300px;
height: 400px;
}
.loginForm>form{
display: inline-block;
width: 100%;
height: 100%;
text-align: center;
border: 1px solid black;
border-radius: 20px;
background-color: bisque;
}
style>
head>
<body>
<h1><%= "Hello World!" %>h1>
<%-- <a href="hello-servlet">Hello Servleta>--%>
<div class="loginForm" >
<form action="${pageContext.request.contextPath}/login" method="get">
<h5>登录h5>
<hr>
<h5>用户名h5>
<input type="text" name="username" value=""><br>
<h5>密码h5>
<input type="text" name="password" value=""><br>
<input type="radio" name="remember" id="remember" checked="checked">
<label for="remember">记住我label><br>
<input type="submit" value="登陆">
form>
div>
body>
<script>
function getCookie(name){
let cookies = [] = document.cookie.split(";");
for(let i = 0; i < cookies.length; i ++){
let crumb = cookies[i].split("=");
//血压上升的bug,莫名其妙的两个字符串首尾有多余的空格,
//这里用trim方法去除首尾空格
if(name.trim() == crumb[0].trim()){
return crumb[1];
}
}
return null;
}
//如果cookie不为空,那么就塞到input的value属性里面
if(getCookie("username") != null) {
document.getElementsByName("username")[0].setAttribute("value", getCookie("username"));
// console.log("这是用户名:" + document.getElementsByName("username")[0].getAttribute("username"));
}
if(getCookie("password") != null){
document.getElementsByName("password")[0].setAttribute("value",getCookie("password"));
// console.log("这是用户名:" + document.getElementsByName("password")[0].getAttribute("password"));
}
script>
html>
这里遇到了一个蜜汁bug,就是比较两个字符串的时候,二者首尾都有空格(数目还不等),搞得if里面的表达式一直是false,我这里就纳闷了一下午…整的我血压上升…不过加上了trim方法去除首尾空格就好了
总之这样一来就设置了一个有效时间为一天的“记住我”登录界面
另外,如果要删除某个cookie的话,那么就选中它然后把生命周期设置为0就好了
服务器给每一个用户(浏览器创建一个session对象)
一个session对象会独占一个浏览器,只要先浏览器还没有关闭,这个session就还存在
先了解一下Seesion的工作原理:
1.客户端把用户名密码等信息发送到服务器
2.服务器向客户端响应一个加密过的Cookie,这个cookie包含了一个唯一的session id,并且服务器记录这个session id
3.客户端拿到这个cookie后,下一次访问便会自动发送cookie,其中的session id随之提交
粗略地理解就是,session是一种加密的cookie
这里为了方便,我就在原来哪个index.jsp里面加上了这段代码
<div>
<form action="${pageContext.request.contextPath}/login" method="post">
<h5>用post方式向后端发送一个msgh5>
<input type="text" name="msg" value="">
<input type="submit" value="提交">
form>
div>
然后在原来哪个Request里面加上这个
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = req.getParameter("msg");
//解决中文乱码
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//获取session,如果不存在那么久创建一个
HttpSession session = req.getSession();
//将数据存到session中
session.setAttribute("msg",msg);
//获取session id
String sessionId = session.getId();
//判断session是不是新建的
if(session.isNew()){
System.out.println("创建了一个session,它的id是:" + sessionId);
System.out.println("它的内容是:" + session.getAttribute("msg"));
}else{
System.out.println("这是之前存在的session,它的id是:" + sessionId);
System.out.println("这是之前存在的session,它的内容是:" + session.getAttribute("msg"));
}
记得配置servlet
<servlet>
<servlet-name>AJAXservlet-name>
<servlet-class>com.example.ServeletRelearner.ajaxServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>AJAXservlet-name>
<url-pattern>/AJAXurl-pattern>
servlet-mapping>
然后再去index.jsp里面添加一段js代码:
function ajax(){
console.log("开始请求")
let httpRequest = new XMLHttpRequest();
if (!httpRequest) {
alert("创建请求失败");
}
httpRequest.open("GET", "http://localhost:8080/AJAX");
httpRequest.send();
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
// let data = JSON.parse(httpRequest.responseText);
let data = httpRequest.responseText;
// let jsonData = JSON.parse(data);
let jsonData = eval( "(" + data + ")" );
document.getElementsByName("msg")[0].value = jsonData.msg;
}
else {
console.error('请求失败');
}
}
}
}
ajax();
页面一加载就开始请求
我们输入一点内容,然后进行以下步骤:
提交——页面发生跳转——返回上一个页面——刷新页面进行重新请求
这样存储在服务端的session就会被请求下来
后端我们也可以看见
当一个Java类满足以下几个标准的时候,它就叫JavaBean:
1.public 修饰的类 ,有public修饰的无参构造
2.所有属性(如果有) 都是private,并提供set和get方法 (如果boolean 则get 可以替换成is)
javaBean也可以叫做pojo或者entity
主要用于存储数据库的数据或者封装各种数据操作
我们目前使用的servlet就是一种比较简陋的controller
作用如下:
1.接收用户请求
2.控制请求转发
也就是前端的代码,作用如下:
1.展示
2.发起请求
内部还有很多层,比如
业务逻辑(Service)层,数据持久(Dao)层等等
作用如下:
1.处理业务逻辑
2.数据库交互
另外,一个大佬还给我介绍了三层架构,好像和上面提到的不太一样,不过这里还是记录一下吧
UI界面层:dao
BLL业务逻辑层:service
DAL数据访问层:servlet
三层架构 和 MVC的区别图解:
(以下图片来自网络)
(以下图片来自大佬博客)
我们把MVC和三层架构完全拆解后得到:
View(UI),BIZ(BLL),DAO(DAL),Entity(Model),Controller
在MVC中:
BIZ(BLL) + DAO(DAL) + Model(Entity) = M层
View(UI) = V层
Controller = C层
在三层架构中:
只有UI DAO BLL三层
有些请求是无效的或者恶意的,所以我们需要有过滤器去处理一下
步骤:
一.导包
这个不在话下,有maven在很轻松就能解决
二.编写过滤器
重写三个方法:初始化、过滤时、销毁
这里我们暂时不用注解
然后我们得到开始配置filter,就类似于之前配置的servlet,依旧是在web.xml里面配置的
<filter>
<filter-name>LoginFilterfilter-name>
<filter-class>com.example.ServeletRelearner.LoginFilterfilter-class>
filter>
<filter-mapping>
<filter-name>LoginFilterfilter-name>
<url-pattern>/loginurl-pattern>
filter-mapping>
过滤器里面有三个方法,都很语义化,类似于生命周期函数,总之我们先写点东西试试
package com.example.ServeletRelearner;
import jakarta.servlet.*;
import java.io.IOException;
import java.sql.Time;
public class LoginFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("Filter创建完毕!!!");
}
public void destroy() {
System.out.println("Filter销毁完毕");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("开始执行...");
chain.doFilter(request, response);
System.out.println("执行完毕...");
}
}
打开tomcat,发现,服务器连接后filter就构建完毕了
当我们点击登录的时候,fiter优先执行
并且我们发现,filter过滤结束后不会自动销毁(是在服务器关闭的时候自动销毁的)
过滤器的作用便是将信息拦截下来然后进行过滤
并且我们可以设置多个过滤器,他们以类似链表的形式存在,通过chain.doFilter(request, response);进行迭代,不断执行下一个过滤器直到没有更多过滤器
个人觉得这个前端做的话比较合适,所以这个暂时就不学了
首先准备三个html文件(或者jsp),分别是登录、成功、失败页面
成功失败就随便写点
登录页面代码如下:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>logintitle>
head>
<body>
<form action="login" method="get">
用户名
<input type="text" name="username">
密码
<input type="text" name="password">
<input type="submit">
form>
body>
html>
然后是后端的三层架构
这里的LoginFilter不用管(本来想写个过滤器,结果不知道该过滤什么,就没用了…)
UI界面层
这里连接的数据库时jdbc_learner,直接复制代码的话记得先根据个人情况修改内容
package com.example.dao;
import java.sql.*;
public class UserDao {
public boolean login(String username, String password){
//判断是否能成功登录的标志
boolean flag = false;
PreparedStatement statement = null;
Connection connection = null;
ResultSet resultSet = null;
try {
//加载驱动,其实现在大部分版本可以省略这一部分
//mysql8以下为 com.mysql.jdbc.Driver
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//?后面那个是为了支持中文和安全连接,要背下来
//这里的jdbc_learner是数据库名字,根据个人情况修改
String url = "jdbc:mysql://localhost:3306/jdbc_learner?useSSL=false&serverTimezone=UTC";
//实例化一个数据库对象
connection = DriverManager.getConnection(url, "root", "root");
String sql = "SELECT username FROM `user` where `password` = ? and `username` = ?";
statement = connection.prepareStatement(sql);
statement.setString(1,password);
statement.setString(2,username);
resultSet = statement.executeQuery();//执行结果的集合
//如果查询到匹配的内容,那么就flag = true,代表可以成功登录
if(resultSet.next()){
System.out.println(resultSet.getObject("username"));
flag = true;
}
}catch(SQLException e){
System.out.println(e);
}finally {
//释放连接
try {
resultSet.close();
statement.close();
connection.close();
}catch(SQLException e){
System.out.println(e);
}
}
return flag;
}
}
BLL业务逻辑层
就是调用UI层的login方法,这样加一层是为了方便管理(项目太小体现不出优势)
package com.example.service;
import com.example.dao.UserDao;
public class UserService {
UserDao userDao = new UserDao();
public boolean login(String username, String password){
return userDao.login(username,password);
}
}
DAL数据访问层
package com.example.servlet;
import com.example.dao.UserDao;
import com.example.service.UserService;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
UserService userService = new UserService();
if(userService.login(username,password)){
//添加名字cookie
Cookie nameCookie = new Cookie("username",username);
nameCookie.setMaxAge(3 * 24 * 24 * 60);
response.addCookie(nameCookie);
//添加密码cookie
Cookie pswdCookie = new Cookie("password",password);
pswdCookie.setMaxAge(3 * 24 * 24 * 60);
response.addCookie(pswdCookie);
response.sendRedirect("success.html");
}else{
response.sendRedirect("fail.html");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
最后记得到web.xml里面配置一下(会注解就当我没说)
<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-name>loginservlet-name>
<servlet-class>com.example.servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>loginservlet-name>
<url-pattern>/loginurl-pattern>
servlet-mapping>
web-app>
当我们输入一个数据库中存在的数据时:
自然是成功,并且添加了cookie
那写一个数据里面没有的
也相应的失败了,并且没有添加cookie
学完以上内容,后端框架前的基础内容(不包括反射代理线程等)也大致了解了
后面我还会继续更新学习笔记
不过下次应该是有关前端或者是计网的内容了