JavaWeb实验课---3 Jsp基础

3 jsp技术

  1. jsp的基本语法、jsp动作元素的使用
  2. jsp指令和隐式对象的使用
  3. jsp的运行原理

前言

编写Servlet响应遇到的问题:
我们需要通过拼接字符串的方式把html写入Servlet响应中。

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");//一段文本,html响应,字符编码utf-8

        String name = req.getParameter("name");
        PrintWriter writer = resp.getWriter();
        writer.println("<!DOCTYPE html>");
        writer.println("<html>");
        writer.println("<head>");
        writer.println("<meta charset=\"utf-8\">");
        writer.println("<title>Servlet + html + </title>");
        writer.println("</head>");
        writer.println("<body>");
        writer.println("<h2>你好" + name + "</h2>");
        writer.println("</body>");
        writer.println("</html>");
    }

实验结果:

  1. 运行上文代码,即在Java中插入html代码。(此时name为空L)
    在这里插入图片描述
    URL配置后,得到了name
    在这里插入图片描述

知识点:什么是 JSP?

概念:

  • jsp全名是Java Server Pages,它是建立在Servlet规范之上的动态网页开发技术。
  • JSP文件中,HTML代码Java代码共同存在。
  • 其中,HTML代码用来实现网页中的静态内容的显示,Java代码用来实现网页中动态内容的显示。

JSP的特征:

  • 跨平台:当从一个平台移植到另一个平台时,JSPJavaBean的代码并不需要重新编译,这是因为Java的字节码是与平台无关的。
  • 业务代码相分离:在使用JSP技术开发Web应用时,可以将界面的开发与应用程序的开发分离。
  • 预编译:预编译就是用户第一次通过浏览器访问JSP页面时,服务器将对JSP页面代码进行编译,并且仅执行一次编译。编译好的代码将被保存,在用户下一次访问时,会直接执行编译好的代码。
  • 组件重用:JSP中可以使用JavaBean编写业务组件,也就是使用JavaBean类封装业务处理代码或者作为一个数据存储模型。

JSP的运行原理:

当一次访问jsp页面时,客户端(即浏览器)会向一个JSP容器(tomcat等)发出请求,servlet容器先要把jsp页面转化为servlet代码(.java),再编译成.class文件再进行调用。当再次访问jsp页面时,会跳过翻译和编译的过程,直接调用,
在这里插入图片描述

3.1 创建jsp-对比jsp与生成的Servlet

步骤:

  1. 编写第一个JSP,在其中插入Java代码
  2. 查看jsp编译的java文件与class文件:
    • 在控制台找到jsp编译的文件的位置:
      在这里插入图片描述
    • 在这个work/Catalina/localhost/jap_war_exploded/org/apache/jsp目录下,就可以找到hello_jsp.classhello_jsp.java
      在这里插入图片描述
  3. 打开hello_jsp.java,对比jsp与生成的Servlet

代码:

hello.js代码:在其中插入了Java代码

<%@ page contentType="text/html;charset=UTF-8"
    pageEncoding="utf-8" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<%-- <%= >表示要输出表达式的值%> --%>
    <h2>你好 <%= request.getParameter("name")%></h2>
</body>
</html>

实验结果:

  1. jsp中插入了Java代码:
    刚开始未在url中配置name
    在这里插入图片描述
    配置后
    在这里插入图片描述
  2. 打开hello_jsp.java,对比jsp与生成的Servlet
    在这里插入图片描述

知识点:JSP 脚本元素、JSP 注释

JSP 脚本元素

  • JSP脚本元素是指嵌套在<%%>之中的一条或多条Java程序代码。
    通过JSP脚本元素可以将Java代码嵌入HTML页面中,所有可执行的Java代码,都可以通过JSP脚本来执行。
  • 脚本元素的三种类型
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

JSP注释

语法格式:<%-- 注释信息 --%>
注意:Tomcat在将JSP页面转换成Servlet的Java程序时会丢弃JSP注释,不会将注释信息发送到客户端。

JSP注释只存在于JSP页面中,转化成java文件就消失了,但是html注释在浏览器中还是可以看到的

3.2 使用jsp的脚本元素并对比Java文件

目标:

三种脚本元素类型 + 两种注释,找到它们在Java文件中的位置

步骤:

  1. 编写代码
  2. 打开网页http://localhost:8080/jsp_war_exploded/test01.jsp,查看其中的内容
  3. 打开jsp生成的对应的.java文件,对比它们在Java中的位置

代码:

JSP声明语句<%! %>,代码段<% %>,JSP表达式:<%= %>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>jsp test01</h1>
<%! int a = 2
        ,
        b = 3; %>
<h1>test02</h1>
<%!
    void showAb() {
        System.out.println("a + b = " + (a + b));
    }
%>
<h1>test03</h1>
<%
    System.out.println("a * b = " + (a * b));
    showAb();
%>
<h1>test04</h1>
<%= a * b %>
</body>
</html>

实验结果:

<%! %>这个标签所定义的内容,并没有出现在Service方法中,而是定义成了这个类的成员变量/成员方法
在这里插入图片描述
<% %>出现在Service方法中,外面没有包裹out.wirte()
<%= %>出现在Service方法中,其内容作为一个表达式包裹在out.print()里面输出
在这里插入图片描述
<%-- this is .....--%>jsp注释只存在于jsp页面中,转换成Java文件就消失了
<!-- this is .....-->转换成Java文件,html的注释是在Service方法中的,是可以看到的的。在浏览器端也是可以看到的。
在这里插入图片描述

知识点:JSP 指令

  • 为了设置JSP页面中的一些信息,可以使用page、include和taglib指令,每种指令都定义了各自的属性。

page 指令

  • page指令用于对页面的某些特性进行描述。例如,页面的编码方式、JSP页面采用的语言等。
  • 语法为:<%@ page 属性名="属性值"%>
  • page指令提供了一系列与JSP页面相关的属性
language		JSP文件采用的语言,默认为Java
import			导包
contentType		根据属性判断文档类型,返回值为文档类型
pageEnCoding	指定页面编码格式
session			JSP内是否内置Session对象,返回值为true/false
isErrorPage		该页面是否为错误处理页面,返回值true/false
errorPage		指定一个错误页面

include 指令

  • include指令只有一个file属性,该属性用来指定插入到JSP页面目标位置的文件资源。(即先把另一个文件包含进来,再翻译成Java文件)
  • include指令 使用注意的问题:
    • 被引入的文件必须遵循JSP语法,其中的内容可以包含静态HTMLJSP脚本元素和JSP指令等普通JSP页面所具有的一切内容。
    • 除了指令元素之外,被引入的文件中的内容会插入进当前JSP文件,然后转换成Servlet源文件(.java),插入位置与include指令在当前JSP页面中的位置保持一致。
  • file属性:
    • 如果以/开头,表示相对于当前Web应用程序的根目录
    • 否则,表示相对于当前文件。需要注意的是,这里的file属性指定的相对路径是相对于文件(file),而不是相对于页面(page)
  • 语法为:<%@ include file="relativeURL"%>

3.3 JSP指令

page指令

步骤:

  1. 修改jsp文件模版
    win系统就点file---->setting点击进入
    在这里插入图片描述
    在这里插入图片描述
  2. 创建jsp文件info1.jsp,编写代码,查看运行情况
  3. 创建err1.jsp专门作为错误的展示页面,让info1.jsp与错误页面err1.jsp关联,即在info1的中加一句errorPage="err1.jsp",访问http://localhost:8080/jsp_war_exploded/ex01/info1.jsp,即可查看错误页面

代码:

info1.jsp

  1. page指令 导包:import=""
  2. 可以设置session,读取session,因为pagesession属性默认为true
  3. int x = 1/0会报错:HTTP状态500 - 内部服务器错误
  4. page中指定,当发生错误时,由哪个页面来展示错误信息。errorPage=""
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" errorPage="err1.jsp" %>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<h1> info1.jsp</h1>
<%= new Date()%>
</br>
<% session.setAttribute("user", "zhang3");%>
<%= session.getAttribute("user")%>
</br>
<% int x = 1 / 0; %>
</body>
</html>

err1.jsp

  1. page中配置isErrorPage,这个页面专门做为错误的展示页面
  2. 通过exception对象拿到错误信息
<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" isErrorPage="true" %>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<h2>出错啦.....</h2>
<h3><%=exception.getMessage()%>></h3>
</body>
</html>

实验结果:

info1.jsp实验结果
在这里插入图片描述
err1.jsp实验结果:
在这里插入图片描述

include指令

步骤:

  1. 创建home1.jsphome2.jspheader.html
  2. home1.jsphome2.jsp中通过include指令,引入HTML文件header.html
  3. 打开对应网页查看实验结果

代码:

home1.jsp
两行分别是:学生信息管理界面,添加
include指令把header.html指令包含进来

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<%@ include file="header.html"%>
<h2>学生信息管理界面.....</h2>
<h3>添加....</h3>
</body>
</html>

home2.jsp
两行分别是:教师信息管理界面,添加

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
  <meta charset="UTF-8"></meta>
  <title>Title</title>
</head>
<body>
<%@ include file="header.html"%>
<h2>教师信息管理界面.....</h2>
<h3>添加....</h3>
</body>
</html>

header.html
一行内容:学校信息管理系统
style中给它加上样式
page中设置pageEncoding,防止中文乱码

<%@ page pageEncoding="UTF-8" %>
<style type="text/css">
  .header{
    height: 200px;
    background: orange;
    color: white;
  }
</style>
<div>
  <h1> 学校信息管理系统</h1>
</div>

实验结果:

在这里插入图片描述
在这里插入图片描述

知识点:JSP 隐式对象

为了简化Web应用程序的开发,可使用隐式(内置)对象,它们是JSP默认创建的,可以直接在JSP页面中使用。

1. 隐式对象的名称、类型和描述信息

request、response、out代表输入输出
request请求输入,response响应,out也是用于页面输出
在这里插入图片描述

  • 这些隐式对象实际上就是在_jspService()方法中的,两个形参和方法里定义的局部变量
    在这里插入图片描述
    作用范围
    (这四个对象都可以用setAttribute、getAttribute来共享数据)
pageContext	当前请求
request		当前页面有效
application	整个应用有效
session	当前会话有效

2. out对象

out对象是java.servlet.jsp.JspWriter类的实例对象,一种带缓存功能的Writer,其作用是用来向客户端发送文本形式的实体内容。

Servlet时,通过response.getWriter()方法返回PrintWriter对象的方法写入数据,写到Response的缓冲区,刷新的时候,就把数据交给了Servlet引擎,让它响应给浏览器。
调用out隐式对象的方法写入数据,写到JspWriter对象的缓冲区,如果没刷新就会一直往下写,刷新/写满时,再把数据写入Response的缓冲区中,最后再把这些交给Servlet引擎
在这里插入图片描述

3. pageContext 对象

提供了用于获取其他隐式对象的方法,都是get....()
(只要拿到了pageContext 对象,其他隐式对象我们都能拿到)
在这里插入图片描述
pageContext 对象还提供了存储数据的功能
pageContext对象存储数据是通过操作属性来实现的,其操作属性的一系列方法如下。
在这里插入图片描述
其中,参数name用于指定属性的名称,参数scope指定的是属性的作用范围,
在这里插入图片描述
findAttribute()方法可以在那4个域中依次查找数据,查找顺序为:pageContext--->request请求域--->session--->application

4. exception对象

在这里插入图片描述
在实验3.3 JSP 指令的include指令实验中,在错误信息展示页面err1.jsp中,只要指定了isErrorPage="true",那么这个JSP页面就可以使用exception对象

3.4 JSP隐式对象

1. out对象

步骤:

  1. 创建jsp文件,编写代码
  2. 分别使用out对象和getWrite()调用的println方法,打印数据
  3. 观察out的内容和getWrite()的内容出现的顺序
  4. 在page指令buffer设置为0kb之后,在观察两个内容出现的顺序

代码:

testOut.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" buffer="0kb" %>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<%
    out.println("write by out <br>");
    //  out.flush();//先把它刷到Response缓存区中
    response.getWriter().println("second line <br>");
%>
</body>
</html>

实验结果:

当内容为时

<%
    out.println("write by out <br>");
    response.getWriter().println("second line <br>");
%>
  1. 此时,second line写到了write by out前面了
    在这里插入图片描述
  2. 因为out的内容先写在JspWrite缓冲区,第二行代码的getWrite()写在了Response缓冲区,当刷新时,out就会出现在getWriter后面
    在这里插入图片描述
  3. 当内容为
<%
    out.println("write by out <br>");
    out.flush();//先把它刷到Response缓存区中
    response.getWriter().println("second line <br>");
%>

page中加入buffer="0kb"
会先把out内容刷到缓存区中,显示顺序就正常了
在这里插入图片描述

2. pageContext对象

pageContext作为域对象共享数据

步骤:

  1. 创建data_set.jsp文件,给四个域设置数据
  2. 创建data_get.jsp文件,获取四个作用域中的数据
  3. 分析四个作用域的作用范围

代码:

data_set.jsp
给四个域application、session、request、pageContext设置数据

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<% application.setAttribute("user1", "user-app-zhang3");%>
application.setAttribute("user1","user-app-zhang3");<br>

<% session.setAttribute("user2", "user-session-zhang3");%>
session.setAttribute("user2", "user-session-zhang3");<br>

<% request.setAttribute("user3", "user-request4-zhang3");%>
request.setAttribute("user3","user-request-zhang3");<br>

<% pageContext.setAttribute("user4", "user-page4-zhang3");%>
pageContext.setAttribute("user4","user-page-zhang3");<br>
</body>
</html>

data_get.jsp,获取四个作用域中的数据

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<%= request.getParameter("active")%>

<%--四个作用域,作用的范围不同,在自己的范围内可以进行数据共享,
pageContext当前页面, request当前请求, session同一个会话的多次请求, application整个应用--%>
application: user1= <%= application.getAttribute("user1")%> <br>
session: user2= <%= session.getAttribute("user2")%> <br>
request: user3= <%= request.getAttribute("user3")%> <br>
pageContext: user4= <%= pageContext.getAttribute("user4")%> <br>
</body>
</html>

实验结果:

先访问data_get:发现没有数据,因为还没有写数据
在这里插入图片描述
访问data_set,写数据:
在这里插入图片描述
访问data_get,读数据:
在这里插入图片描述
application读到了,因为它们是同一个应用
session读到了,因为它们在cookie里面有相同的JSESSION ID
requestpageContext没读到,因为不是同一次请求

知识点:<jsp:include> 动作元素

  • JSP页面中,为了把其他资源的输出内容插入到当前JSP页面的输出内容中,JSP技术提供了<jsp:include>动作元素。
  • 其语法格式为:
    在这里插入图片描述
  • <jsp:include>工作原理:
    <jsp:include>包含的原理是将被包含的页面编译处理后的结果包含在页面中。当浏览器第一次请求一个使用<jsp:include>包含其他页面的页面时,Web容器首先会编译被包含的页面,然后将编译处理后的返回结果包含在页面中,之后编译包含页面,最后将两个页面组合的结果回应给浏览器。
  • <jsp:forward>动作元素将当前请求转发到其他Web资源(HTML页面、JSP页面和Servlet等)。在执行请求转发之后,当前页面不再执行,而是执行该元素指定的目标页面。
  • 语法格式:<jsp:forwar page="relativeURL" />

3.5 <jsp:include>动作元素

步骤:

  1. data_set.jsp中,加入分割线<hr>,通过<jsp:include>data_get.jsp包含在页面中。

代码:

data_set.jsp:请求包含<jsp:include>的使用
<jsp:include> </jsp:include>这里面可以给它指定参数
data_get.jsp中调用getParameter()方法来获得参数

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<% application.setAttribute("user1", "user-app-zhang3");%>
application.setAttribute("user1","user-app-zhang3");<br>

<% session.setAttribute("user2", "user-session-zhang3");%>
session.setAttribute("user2", "user-session-zhang3");<br>

<% request.setAttribute("user3", "user-request4-zhang3");%>
request.setAttribute("user3","user-request-zhang3");<br>

<% pageContext.setAttribute("user4", "user-page4-zhang3");%>
pageContext.setAttribute("user4","user-page-zhang3");<br>

<hr>
<jsp:include page="data_get.jsp">
    <jsp:param name="active" value="edit"/>
</jsp:include>
</body>
</html>

data_get.jsp:
通过调用getParameter()方法来获得在data_set.jsp<jsp:include> </jsp:include>中设置的参数

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<%= request.getParameter("active")%>

<%--四个作用域,作用的范围不同,在自己的范围内可以进行数据共享,
pageContext当前页面, request当前请求, session同一个会话的多次请求, application整个应用--%>
application: user1= <%= application.getAttribute("user1")%> <br>
session: user2= <%= session.getAttribute("user2")%> <br>
request: user3= <%= request.getAttribute("user3")%> <br>
pageContext: user4= <%= pageContext.getAttribute("user4")%> <br>
</body>
</html>

实验结果:

使用include时,访问页面http://localhost:8080/jsp_war_exploded/ex04/data_set.jsp,当前页面data_set的内容有,目标页面data_get的内容也有
在这里插入图片描述
data_set.jsp中把include改为forward,访问页面http://localhost:8080/jsp_war_exploded/ex04/data_set.jsp,就只有目标页面data_get的内容
在这里插入图片描述

3.6 实现注册页面

步骤:

任务目标:使用jsp改写html;实现修改登录页面,错误时显示用户名;引用公共页面
实现步骤:

  1. 修改login.jsp(需要修改LoginServlet.java和login.jsp中的内容)
  2. 创建home.jsp(需要修改HomeServlet.java和home.jsp中的内容)
  3. 运行项目,查看结果
  4. 引用header.jsp

代码:

LoginServlet.java

当登录成功时,重定向到home.jsp

当登录失败时,请求转发到login.jsp,且要把用户名数据传过去,
这里我们没有把数据放在session里面,而是单独发过去,表示在本次请求里有效。
login.jsp中通过request.getAttribute("user")把转发过来的user填进value里

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String pwd = req.getParameter("pwd");

        String checkcode = req.getParameter("checkcode");
        System.out.println("LoginServlet用户输入的验证码:" + checkcode);
//        String s = CheckCodeServlet.instance.s;
//        System.out.println("LoginServlet随机生成的验证码: " + s);

        HttpSession session = req.getSession();
/**
 * 前三个条件,保证可以从session中拿到验证码信息,分别是保证session不为空;
 * session里有存验证码信息的键值对,name为code;
 * 用户输入的验证码checkcode不为空,空不能使用equals语句
 * 最后一个条件是,检验密码、验证码是否正确;
 */
        if (session != null && session.getAttribute("code") != null && checkcode != null &&
                "123".equals(pwd) && checkcode.equals(req.getSession().getAttribute("code"))) {

            req.getSession().setAttribute("user", username);
            //如果登录成功,重定向跳转到home页面
            req.getRequestDispatcher("home.jsp").forward(req, resp);
        } else {
            //如果验证失败,请求转发到login.jsp,且要把用户名数据传过去
            //数据不放在session里面,单独发过去,表示在本次请求里有效
            req.setAttribute("user", username);
            req.getRequestDispatcher("login.jsp").forward(req, resp);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

login.jsp

login.html改为login.jsp
login.jsp中通过request.getAttribute("user")把从LoginServlet.java转发过来的user填进value

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<form action="login" method="post">
    <input type="text" name="username" placeholder="账号" value="<%=request.getAttribute("user") %>"/><br/><br/>
    <input type="text" name="pwd" placeholder="密码"/><br/><br/>

    <%--  功能:点击验证码图片,刷新验证码--%>
    <%--  当点击这张图片时,就会执行下面的script代码--%>
    img: <img id="code" alt="" src="check" onclick="freash()">
    <script>
        function freash() {
            let check = document.getElementById("code");
            check.src = "check?" + new Date().getTime();
            console.log("freash2....")//控制台上输出freash....
        }
    </script>
    <br/>

    <%--  输出框、登录按钮--%>
    <p>请输入验证码:</p>
    <input type="text" name="checkcode" placeholder="验证码"/><br/><br>
    <input type="submit" value="登录">
</form>
</body>
</html>

HomeServlet.java

如果session中有用户信息,即有用户登录,就通过req.getRequestDispatcher,请求转发到home.jsp。
再在home.jsp中把数据取出来

@WebServlet("/home")
public class HomeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码方式
        resp.setContentType("text/html;charset=utf-8");

        //判断用户是否在登录状态,如果不在登录状态,要重定向到login.html
        HttpSession session = req.getSession();
        //如果有session对象,并且session对象当中已经保存了user
        if (session != null && session.getAttribute("user") != null) {
            //展示信息
            req.getRequestDispatcher("home.jsp").forward(req,resp);
        } else {
            //重定向
            req.getRequestDispatcher("login.jsp").forward(req,resp);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

home.jsp

  • 如何拿到用户名?
    通过homeServlet把数据传过来,传到jsp里面,让jsp去展示。

  • jsp负责展示信息,servlet负责取得数据

  • home.jsp中把数据取出来
    session中的数据:通过session.getAttribute("user")取出

<%@ page contentType="text/html;charset=UTF-8" language="java"
         pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>管理首页</h1>
<h4>登录用户:<%=session.getAttribute("user")%>
</h4>
<a href='logout'>退出登录</a><br/>
添加成绩<br/>
修改成绩<br/>
....<br/>
</body>
</html>

LogoutServlet.java

重定向到login.jsp

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //删除session中的数据
        if (req.getSession() != null) {
            req.getSession().removeAttribute("user");
        }
        //重定向到login.html
        resp.sendRedirect("login.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

CheckCodeServlet.java

@WebServlet("/check")
public class CheckCodeServlet extends HttpServlet {
    //刚开始想的是通过一个字符串s获得4个随机生成的字母,再传给LoginServlet进行验证
    //即用login里打注释的那两行代码接收字符串s
    //    public String s = "";
//    public static CheckCodeServlet instance;
//
//    @Override
//    public void init() throws ServletException {
//        super.init();
//        instance = this;
//    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1. content-type 返回图片类型
        String mimeType = getServletContext().getMimeType(".jpg");
        System.out.println("mimetype" + mimeType);
        resp.setContentType(mimeType);

        //2. 画图大小
        int w = 100;
        int h = 50;

        //3. 生成BufferedImage对象
        BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = bufferedImage.getGraphics();

        //4. 填充矩形
        graphics.setColor(Color.LIGHT_GRAY);//颜色
        graphics.fillRect(0, 0, w, h);//矩形从左上角(0,0)到(x,y)

        //5. 画外框
        graphics.setColor(new Color(34, 34, 250));//先设置一个颜色
        graphics.drawRect(0, 0, w - 1, h - 1);//画一个矩形框

        //6. 在这张图片上写4个字母
        String s = new String();
        graphics.setFont(new Font("", Font.BOLD, 20));
        Random random = new Random();
        for (int i = 0; i < 4; i++) {    //随机生成4个字符,画在图片里
            char x = (char) ('A' + random.nextInt(25));
            s = s + x;
            graphics.drawString("" + x, 5 + i * 20, 30);
        }
        System.out.println("验证码Servlet随机生成的验证码为:" + s);
        //将字符串s保存在session中
        HttpSession session = req.getSession();
        session.setAttribute("code", s);

        //7. 画随机线条
        for (int i = 0; i < 10; i++) {
            int x1 = random.nextInt(100);
            int x2 = random.nextInt(100);
            int y1 = random.nextInt(50);
            int y2 = random.nextInt(50);
            graphics.drawLine(x1, y1, x2, y2);
        }

        //8. 把图片写出到输出流
        ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

实验结果:

  1. 还没有登录时,访问home页面,自动跳转到login.jsp
    在这里插入图片描述
  2. 验证失败,自动跳转到login.jsp,且用户名被保存
    在这里插入图片描述
  3. 验证码和密码输入正确,自动跳转到home.jsp
    用户名被保存在session中,home.jsp拿到session中的用户名并输出。
    在这里插入图片描述
  4. 此时已经登录成功了,且没有退出登录,即session中数据未被删除
    访问home页面,自动跳转到home.jsp
    在这里插入图片描述
  5. 点击退出登录,会删除session中的数据,并重定向到login.jsp
    在这里插入图片描述


小技巧:当jsp页面修改了,不需要重启tomcat,只要点击一下部署按钮即可

例子:
这是一个修改后的页面
在这里插入图片描述
点击部署按钮
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值