Java学习笔记_从零到Web全栈:Web后端基础篇

前言

JSP感觉实际开发用处不是很大,这里不再记录
监听器个人觉得由前端来做更合适并且更方便一些,所以也不再记录

前置准备

这里使用Intelligent Idea开发,Tomcat和Maven的安装配置不再赘述
所以Tomcat和Maven的知识点还需要自己去了解一下

Servelet

基本使用

什么是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?)

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>ServeletLearner</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--jsp的依赖-->
        <dependency>
            <groupId>jakarta.servlet.jsp</groupId>
            <artifactId>jakarta.servlet.jsp-api</artifactId>
            <version>3.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!--jar包的依赖-->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
            <scope>provided</scope>
        </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并且给他一个可以访问的路径。

<?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">
         
    <!-- 注册servelet-->
    <servlet>
        <servlet-name>HelloServelet</servlet-name>
        <servlet-class>com.serio.servelet.HelloServelet</servlet-class>
    </servlet>
    
    <!-- servelet的请求路径  -->
    <servlet-mapping>
        <servlet-name>HelloServelet</servlet-name>
        <url-pattern>/hello</url-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("<h1>你的页面404了诶</h1>");
    }
}

接下来回到web.xml文件里面进行配置
在这里插入图片描述
添加如下代码

    <!--  注册404页面  -->
    <servlet>
        <servlet-name>error</servlet-name>
        <servlet-class>com.example.ServeletRelearner.ErrorServlet</servlet-class>
    </servlet>
    <!--  servelet的请求路径  -->
    <servlet-mapping>
        <servlet-name>error</servlet-name>
        <url-pattern>/404</url-pattern>
    </servlet-mapping>

样式方面呢就先不要在意那么多,能访问就算成功
在这里插入图片描述
这里可能会出现路径冲突时的优先级的问题,这里的优先级类似于前端的CSS选择器的优先级,不再赘述。

至于Tomcat可能存在的乱码问题
只需要找到Tomcat 的 conf文件夹下的logging.properties文件,修改其中第五十一行的值为GBK,重启Tomcat即可解决
在这里插入图片描述

ServeletContext

就是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里面配置一下初始化信息

 <!--  配置servlet的初始化信息  -->
    <context-param>
        <param-name>someParam</param-name>
        <param-value>"这是一个param"</param-value>
    </context-param>

然后再到servlet里面操作:

   String s = context.getInitParameter("someParam");
   System.out.println(s);

在这里插入图片描述
当然context还有很多用法这里就不再赘述

HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表该请求的HttpServletRequest对象,和一个代表响应的HttpServletResponse对象

我们如果要获取客户端请求过来的参数,就使用HttpServletRequest
我们如果要获取客户端响应的信息,那么使用HttpServletResponse


**

response下载文件

来试试利用这个下载一个文件看看
直接新建一个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

<!--注册FileServlet-->
    <servlet>
        <servlet-name>filedown</servlet-name>
        <servlet-class>com.example.ServeletRelearner.FileServlet</servlet-class>
    </servlet>
    <!--  servelet的请求路径  -->
    <servlet-mapping>
        <servlet-name>filedown</servlet-name>
        <url-pattern>/down</url-pattern>
    </servlet-mapping>

从结果上看是下载了一个文件(虽然打不开,可能是请求头设置的问题吧),那么其他类似的操作就可以依葫芦画瓢
在这里插入图片描述


response生成验证码

突然觉得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;
    }
}
  <!--注册Image-->
    <servlet>
        <servlet-name>image</servlet-name>
        <servlet-class>com.example.ServeletRelearner.ImageServlet</servlet-class>
    </servlet>
    <!--  servelet的请求路径  -->
    <servlet-mapping>
        <servlet-name>image</servlet-name>
        <url-pattern>/image</url-pattern>
    </servlet-mapping>

在这里插入图片描述

但是这个还是没有前端写一个方便…所以个人倾向于用前端的技术来写

response重定向

(图片来自网络)
在这里插入图片描述
重定向与转发之区别:
重定向-----这个别找我,你去找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");
    }
}

    <!--注册redirect-->
    <servlet>
        <servlet-name>redirect</servlet-name>
        <servlet-class>com.example.ServeletRelearner.RedirectServlet</servlet-class>
    </servlet>
    <!--  servlet的请求路径  -->
    <servlet-mapping>
        <servlet-name>redirect</servlet-name>
        <url-pattern>/redirect</url-pattern>
    </servlet-mapping>

然后我们去访问/redirect,它就会自动跳转到/image
在这里插入图片描述

HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息都会被封装到HttpServletRequest中,这样一来我们就方便获取到所有的信息了
比如说
在这里插入图片描述

request获取参数

这里运用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

    <!--注册request-->
    <servlet>
        <servlet-name>request</servlet-name>
        <servlet-class>com.example.ServeletRelearner.Request</servlet-class>
    </servlet>
    <!--  servlet的请求路径  -->
    <servlet-mapping>
        <servlet-name>request</servlet-name>
        <url-pattern>/login</url-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 World</title>
</head>
<body>
    <h1><%= "Hello World!" %></h1>
<%--    <a href="hello-servlet">Hello Servlet</a>--%>
    <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多选中的选项),接收用数组来做就行了

Cookie和Session

会话

用户打开一个浏览器,点了很多超链接,访问了多个web资源——这个过程,可以被称之为会话
**有状态会话:
**服务端能够证明某个客户端访问过的方式
一种是让客户端带上一个标记,也就是cookie
另一种是服务端上登记,也就是session

Cookie是客户端技术(响应,请求)
Session是服务器技术,保存用户信息

Cookie实现登录“记住我”

这里我们使用后端添加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 World</title>
    <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 Servlet</a>--%>
    <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结合AJAX

服务器给每一个用户(浏览器创建一个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方式向后端发送一个msg</h5>
            <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>AJAX</servlet-name>
        <servlet-class>com.example.ServeletRelearner.ajaxServlet</servlet-class>
    </servlet>
    <!--  servlet的请求路径  -->
    <servlet-mapping>
        <servlet-name>AJAX</servlet-name>
        <url-pattern>/AJAX</url-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就会被请求下来
在这里插入图片描述
后端我们也可以看见
在这里插入图片描述

MVC 与 三层架构

JavaBean

当一个Java类满足以下几个标准的时候,它就叫JavaBean:
1.public 修饰的类 ,有public修饰的无参构造
2.所有属性(如果有) 都是private,并提供set和get方法 (如果boolean 则get 可以替换成is)

javaBean也可以叫做pojo或者entity
主要用于存储数据库的数据或者封装各种数据操作

MVC

C:controller层

我们目前使用的servlet就是一种比较简陋的controller

作用如下:
1.接收用户请求
2.控制请求转发

V:view层

也就是前端的代码,作用如下:
1.展示
2.发起请求

M:model层

内部还有很多层,比如
业务逻辑(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三层

filter过滤器

有些请求是无效的或者恶意的,所以我们需要有过滤器去处理一下
步骤:
一.导包
这个不在话下,有maven在很轻松就能解决
二.编写过滤器
重写三个方法:初始化、过滤时、销毁
在这里插入图片描述
在这里插入图片描述
这里我们暂时不用注解
然后我们得到开始配置filter,就类似于之前配置的servlet,依旧是在web.xml里面配置的

    <!--  注册filter  -->
    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.example.ServeletRelearner.LoginFilter</filter-class>
    </filter>
    <!--  filter的请求路径  -->
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/login</url-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);进行迭代,不断执行下一个过滤器直到没有更多过滤器

监听器

个人觉得这个前端做的话比较合适,所以这个暂时就不学了

结合JDBC制作登录系统

首先准备三个html文件(或者jsp),分别是登录、成功、失败页面
成功失败就随便写点
在这里插入图片描述
登录页面代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</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里面配置一下(会注解就当我没说)

<?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">

    <!--注册login-->
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.example.servlet.LoginServlet</servlet-class>
    </servlet>
    <!--  servlet的请求路径  -->
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

当我们输入一个数据库中存在的数据时:
在这里插入图片描述
自然是成功,并且添加了cookie
在这里插入图片描述
那写一个数据里面没有的
在这里插入图片描述
也相应的失败了,并且没有添加cookie
在这里插入图片描述

后记

学完以上内容,后端框架前的基础内容(不包括反射代理线程等)也大致了解了
后面我还会继续更新学习笔记
不过下次应该是有关前端或者是计网的内容了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

碳苯

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

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

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

打赏作者

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

抵扣说明:

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

余额充值