Java Web集合

目录

一、Java Web基础

基础概念

web开发:

  • web,网页的意思
  • 静态web
    1. HTML,CSS
    2. 提供给所有人看的数据(不会变化)
  • 动态web(JavaWeb)
    1. 提供给所有人的数据会因人而异,数据会不同(时间,用户…)
    2. 技术栈:PHP,ASP,Servlet/JSP

Web应用程序

可以提供浏览器访问的程序

  1. 比如:a.html 文件可以被外界访问,对外界提供服务
  2. 利用URL用户可以去访问一个页面或资源一定在某台计算机上
  3. 统一的Web资源会被放在同一文件夹下(Web应用程序—>Tomcat(服务器))
  4. Web应用程序编写完后,需要一个服务器来统一管理来实现提供给外界访问

Web应用程序组成部分:

  • HTML,CSS,JS
  • JSP,Servlet,ASP,PHP
  • Java程序
  • Jar包
  • 配置文件(Properties)
静态Web

静态Web页面的缺点:

  1. Web页面无法动态更新,所有用户看到的都是一个页面
    1. 伪动态(JS,VBScript)
    2. 它无法与数据库交互
动态Web

可以实现Web页面展示效果因人而异

可以与数据库交互(JDBC),数据持久化

动态Web页面的缺点:

  1. 加入服务器的动态web资源出现错误,需要重新编写后台程序(停机维护)
Web服务器

服务器是一种被动的操作,用来处理用户一些请求和给用户一些响应信息

IIS:微软的

Tomacat:

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。Tomcat最新版本为10.0.23

ky下载Tomcat,解压后用bin中startup.sh 启动,开启后可以打开网址https://localhost:8080

可以配置启动的端口号

  • tomcat的默认端口号:8080
  • MySQL:3306
  • http:80
  • https:443
 <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

高难度面试题:

谈谈网站是如何进行访问的?

  1. 输入一个域名,回车

  2. 检查本机的C:\WINDOWS\System32\drivers\etc\hosts配置文件下有没有这个域名映射

    • 有:直接返回对应的IP地址,有我们需要的web程序则可以直接访问

      	127.0.0.1       localhost
      
    • 没有:去DNS服务器上去找

发布一个Web网站
  • 将自己写的网站放到服务器中指定的web应用的文件夹(webapps)下,就可以访问了

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zu2NrqVE-1671708205271)(C:\Users\海潇\Desktop\屏幕截图 2022-10-22 202355.png)]

可以复制一个ROOT文件(删去可以删掉的),开启服务器后可以打开网址https://localhost:8080/MyWeb/

网站应有的结构:

--webapps : Tomcat服务器的web目录
    -ROOT
    -MyWeb : 网站的目录名
        - WEB-INF
        	-classes : java程序
            -lib : web应用所依赖的jar包
            -web.xml : 网站配置文件
        - index.html 默认首页
        - static
                -css
                	-style.css
                -js
                -img
                ....
Http协议

什么是Http

Http是一个简单的请求–响应协议(超文本传输协议),它通常运行在TCP之上

  • 80端口
  • Https:443端口(”s“是指安全的意思)

我在Microsoft Edge浏览器上面抓包不是很懂,不能抓到具体有用的数据,所有我看了其他大佬的博客,链接放在这:HTTP协议超级详解 - 爱文飞翔 - 博客园 (cnblogs.com)

请求行
  • 请求行中请求方式:GET
  • 请求方式:get,post,head,delete,put…
    • get:请求能够携带的参数较少,大小有限,会在浏览器的URL地址栏显示数据内容,不安全,但高效
    • post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效
消息头

Accept:告诉浏览器,它所支持的数据类型

Accept-Encoding:支持那种编码格式

Accept-Language:它的语言环境

Cache-Control:缓存控制

Connection:告诉浏览器,请求完成时断开还是保持连接

响应状态码

200:请求响应成功

3xx:请求重定向

  • 重定向:重新到我给你的新位置去

404:找不到资源

5xx:服务器代码错误 500 502(网关错误)

二、Maven项目

Maven的意义

能够自动帮助导入和配置jar包,就是个导jar包的管理工具

Maven的核心思想:约定大于配置

修改镜像(了解)
  • 镜像:mirrors
    • 加速国内反应速度

在D:\apache-maven-3.8.6\conf\settings.xml 下修改,以下就是这样

阿里云镜像

<mirror> 
    <id>alimaven</id> 
    <name>aliyun maven</name> 
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url> 
    <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf> 
  </mirror> 
本地仓库

建立一个本地仓库,自己创建一个文件夹

<localRepository>D:\apache-maven-3.8.6\maven-repo</localRepository>
eclipse配置maven本地仓库:

eclipse配置Maven本地仓库_罗汉爷的博客-CSDN博客

将tomcat加入到eclipse(高版本需要操作步骤1【添加包】):
  1. 增加server选项:eclipse中没有server选项的解决办法(详细)_果冻奶酪的博客-CSDN博客_eclipse下面没有server
  2. 将romcat加入:超详细Eclipse配置Tomcat配置教程_极小白的博客-CSDN博客_eclipse配置tomcat
Maven项目配置(重点)

单击maven文件选中properties配置Java Build Path 和Project Facets
注意:

  1. 一定要jdk的版本在两个配置地方一致
  2. Dynamic Web Module版本高的话一定要使用jdk1.8以上
  3. 记得在Project Facets和自己的tomcat连接上
    在这里插入图片描述
    在这里插入图片描述
创建maven父子工程(了解)
maven环境优化(了解)

现在的eclipse创建出来的web.xml不需要改动,servlet映射等都会自动生成,以下是老版本可能需要的web.xml文件的优化

三、Servlet文件

Servlet简介

Servlet就是sun公司开发动态web的一门技术
开发Servlet程序两个步骤:

  1. 编写一个类
  2. 把开发好的Java类部署到web服务器中
HelloServlet的创建
1.创建servlet文件

在src/main/Java目录下创建servlet文件,命名为HelloServlet并继承HttpServlet(建议使用jakarta.servlet.http.HttpServlet,现在版本高了就搞出了Jakarta)
在这里插入图片描述

以下导入的是javax(图找不到了)

package servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("holleservlet");
		
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doPost(req, resp);
	}

}
2.编写servlet映射(eclipse下不用写,会自动生成)

在web.xml下编写

<!--注册servlet -->
<servlet>
        <servlet-name>Hello</servlet-name>
        <servlet-class>servlet.HelloServlet</servlet-class>
      </servlet>
<!--servlet的请求路径 -->
      <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <!--url名字 -->
        <url-pattern>/hello</url-pattern>
      </servlet-mapping>
3.添加tomcat服务器(之前就要配置好,在servers下引入你想加载的maven文件就行了)

在这里插入图片描述

4.测试
servlet生命周期

实例化----->初始化------->服务------->销毁

servlet特点
  • servlet是单例多线程
  • 一个servlet实例只会执行一次无参构造器与init()方法,并在第一次访问时进行
  • 用户没提交一次对当前servlet的请求,就会执行一次service()方法
  • 只会执行一次destroy()方法,在服务器停止时执行
  • 默认情况下,servlet在web容器启动时不会被实例化的
关于mapping问题
  1. 一个servlet可以对应一个映射路径

  2. 一个servlet可以对应多个映射路径

    <servlet-mapping>
        <servlet-name>Helloservlet</servlet-name>
        <url-pattern>/hello2</url-pattern>
      </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Helloservlet</servlet-name>
        <url-pattern>/hello3</url-pattern>
      </servlet-mapping>
    
  3. 一个servlet可以对应通用映射路径

    <servlet-mapping>
        <servlet-name>Helloservlet</servlet-name>
        <url-pattern>/hello/*</url-pattern>
      </servlet-mapping>
    
  4. 默认请求路径

    <servlet-mapping>
        <servlet-name>Helloservlet</servlet-name>
        <url-pattern>/*</url-pattern>
      </servlet-mapping>
    
  5. 自定义后缀实现请求

    <servlet-mapping>
        <servlet-name>Helloservlet</servlet-name>
        <url-pattern>*.do</url-pattern>
      </servlet-mapping>
    //*前面什么都不加,可以在浏览器上输入如何前缀
    
Servlet Context

web容器在启动的时候,它会为每个web程序都创建一个对应的servletcontext对象

servletcontext作用:共享数据,我在一个servlet保存的数据,可以在另一个servlet中拿到

  • 先创建一个放置数据的类
package com.hai;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Servlet implementation class HelloServlet
 */
public class HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//System.out.println("heelo");
		//response.getWriter().append("Served at:heelo ").append(request.getContextPath());
		ServletContext s = this.getServletContext();
		String username = "hai";
		s.setAttribute("username", username); 
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

  • 再创一个servlet类
package com.hai;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Servlet implementation class NewServlet
 */
public class NewServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NewServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		ServletContext s = this.getServletContext();
		String username = (String) s.getAttribute("username");
		
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");;
		response.getWriter().print("名字:"+username);	
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}
  • 测试结果

    • 先打开NewServlet类,则
      在这里插入图片描述

    • 先打开HelloServlet类,后打开NewServlet类,则
      在这里插入图片描述

Servlet Context的应用
  • 获取初始化参数
<!-- 配置一些web应用初始化参数 -->
<context-param>
  	<param-name>url</param-name>
  	<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
  </context-param>
 <servlet>
    <description></description>
    <display-name>ServletDome</display-name>
    <servlet-name>ServletDome</servlet-name>
    <servlet-class>com.hai.ServletDome</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletDome</servlet-name>
    <url-pattern>/jp</url-pattern>
  </servlet-mapping>
  <servlet>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext s = this.getServletContext();
		String url = s.getInitParameter("url");
		 response.getWriter().print(url);
	}
  • 请求转发
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext s = this.getServletContext();
		RequestDispatcher requestDispatcher = s.getRequestDispatcher("/jp"); //转发的请求路径
		 requestDispatcher.forward(request, response); //调用forward方法实现请求
	}
  • 读取资源文件
Properties文件
  1. 在src/main/java目录下新建Properties

  2. 在src/main/resource目录下新建Properties

    发现:都被打包在class下生成,统称为class path

    思路:都需要一个流(Stream类)

Properties文件下写的内容:

username = root
password = 123456

servlet文件下写的内容:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/class/db.properties");
	Properties properties = new Properties();
	properties.load(is);
	String user = properties.getProperty("username");
	String pwd = properties.getProperty("password");
	response.getWriter().print(user+":"+pwd);
	}
HttpServletResponse

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

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:找HttpServletResponse
简单分类

负责向浏览器发送数据的方法

 public ServletOutputStream getOutputStream() throws IOException;
 public PrintWriter getWriter() throws IOException;

负责向浏览器发送响应头的方法

 public void setCharacterEncoding(String charset);
 public void setContentLength(int len);
 public void setContentLengthLong(long len);
 public void setContentType(String type);
 public void setBufferSize(int size);

响应状态码(也是servlet会向浏览器发送头的方法)

default public Supplier<Map<String, String>> getTrailerFields() {
        return null;
    }

    /*
     * Server status codes; see RFC 2068.
     */

    /**
     * Status code (100) indicating the client can continue.
     */
    public static final int SC_CONTINUE = 100;

    /**
     * Status code (101) indicating the server is switching protocols according to Upgrade header.
     */
    public static final int SC_SWITCHING_PROTOCOLS = 101;

    /**
     * Status code (200) indicating the request succeeded normally.
     */
    public static final int SC_OK = 200;

    /**
     * Status code (201) indicating the request succeeded and created a new resource on the server.
     */
    public static final int SC_CREATED = 201;

    /**
     * Status code (202) indicating that a request was accepted for processing, but was not completed.
     */
    public static final int SC_ACCEPTED = 202;

    /**
     * Status code (203) indicating that the meta information presented by the client did not originate from the server.
     */
    public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;

    /**
     * Status code (204) indicating that the request succeeded but that there was no new information to return.
     */
    public static final int SC_NO_CONTENT = 204;

    /**
     * Status code (205) indicating that the agent <em>SHOULD</em> reset the document view which caused the request to be
     * sent.
     */
    public static final int SC_RESET_CONTENT = 205;

    /**
     * Status code (206) indicating that the server has fulfilled the partial GET request for the resource.
     */
    public static final int SC_PARTIAL_CONTENT = 206;

    /**
     * Status code (300) indicating that the requested resource corresponds to any one of a set of representations, each
     * with its own specific location.
     */
    public static final int SC_MULTIPLE_CHOICES = 300;

    /**
     * Status code (301) indicating that the resource has permanently moved to a new location, and that future references
     * should use a new URI with their requests.
     */
    public static final int SC_MOVED_PERMANENTLY = 301;

    /**
     * Status code (302) indicating that the resource has temporarily moved to another location, but that future references
     * should still use the original URI to access the resource.
     *
     * This definition is being retained for backwards compatibility. SC_FOUND is now the preferred definition.
     */
    public static final int SC_MOVED_TEMPORARILY = 302;

    /**
     * Status code (302) indicating that the resource reside temporarily under a different URI. Since the redirection might
     * be altered on occasion, the client should continue to use the Request-URI for future requests.(HTTP/1.1) To represent
     * the status code (302), it is recommended to use this variable.
     */
    public static final int SC_FOUND = 302;

    /**
     * Status code (303) indicating that the response to the request can be found under a different URI.
     */
    public static final int SC_SEE_OTHER = 303;

    /**
     * Status code (304) indicating that a conditional GET operation found that the resource was available and not modified.
     */
    public static final int SC_NOT_MODIFIED = 304;

    /**
     * Status code (305) indicating that the requested resource <em>MUST</em> be accessed through the proxy given by the
     * <code><em>Location</em></code> field.
     */
    public static final int SC_USE_PROXY = 305;

    /**
     * Status code (307) indicating that the requested resource resides temporarily under a different URI. The temporary URI
     * <em>SHOULD</em> be given by the <code><em>Location</em></code> field in the response.
     */
    public static final int SC_TEMPORARY_REDIRECT = 307;

    /**
     * Status code (400) indicating the request sent by the client was syntactically incorrect.
     */
    public static final int SC_BAD_REQUEST = 400;

    /**
     * Status code (401) indicating that the request requires HTTP authentication.
     */
    public static final int SC_UNAUTHORIZED = 401;

    /**
     * Status code (402) reserved for future use.
     */
    public static final int SC_PAYMENT_REQUIRED = 402;

    /**
     * Status code (403) indicating the server understood the request but refused to fulfill it.
     */
    public static final int SC_FORBIDDEN = 403;

    /**
     * Status code (404) indicating that the requested resource is not available.
     */
    public static final int SC_NOT_FOUND = 404;

    /**
     * Status code (405) indicating that the method specified in the <code><em>Request-Line</em></code> is not allowed for
     * the resource identified by the <code><em>Request-URI</em></code>.
     */
    public static final int SC_METHOD_NOT_ALLOWED = 405;

    /**
     * Status code (406) indicating that the resource identified by the request is only capable of generating response
     * entities which have content characteristics not acceptable according to the accept headers sent in the request.
     */
    public static final int SC_NOT_ACCEPTABLE = 406;

    /**
     * Status code (407) indicating that the client <em>MUST</em> first authenticate itself with the proxy.
     */
    public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;

    /**
     * Status code (408) indicating that the client did not produce a request within the time that the server was prepared
     * to wait.
     */
    public static final int SC_REQUEST_TIMEOUT = 408;

    /**
     * Status code (409) indicating that the request could not be completed due to a conflict with the current state of the
     * resource.
     */
    public static final int SC_CONFLICT = 409;

    /**
     * Status code (410) indicating that the resource is no longer available at the server and no forwarding address is
     * known. This condition <em>SHOULD</em> be considered permanent.
     */
    public static final int SC_GONE = 410;

    /**
     * Status code (411) indicating that the request cannot be handled without a defined
     * <code><em>Content-Length</em></code>.
     */
    public static final int SC_LENGTH_REQUIRED = 411;

    /**
     * Status code (412) indicating that the precondition given in one or more of the request-header fields evaluated to
     * false when it was tested on the server.
     */
    public static final int SC_PRECONDITION_FAILED = 412;

    /**
     * Status code (413) indicating that the server is refusing to process the request because the request entity is larger
     * than the server is willing or able to process.
     */
    public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;

    /**
     * Status code (414) indicating that the server is refusing to service the request because the
     * <code><em>Request-URI</em></code> is longer than the server is willing to interpret.
     */
    public static final int SC_REQUEST_URI_TOO_LONG = 414;

    /**
     * Status code (415) indicating that the server is refusing to service the request because the entity of the request is
     * in a format not supported by the requested resource for the requested method.
     */
    public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;

    /**
     * Status code (416) indicating that the server cannot serve the requested byte range.
     */
    public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;

    /**
     * Status code (417) indicating that the server could not meet the expectation given in the Expect request header.
     */
    public static final int SC_EXPECTATION_FAILED = 417;

    /**
     * Status code (500) indicating an error inside the HTTP server which prevented it from fulfilling the request.
     */
    public static final int SC_INTERNAL_SERVER_ERROR = 500;

    /**
     * Status code (501) indicating the HTTP server does not support the functionality needed to fulfill the request.
     */
    public static final int SC_NOT_IMPLEMENTED = 501;

    /**
     * Status code (502) indicating that the HTTP server received an invalid response from a server it consulted when acting
     * as a proxy or gateway.
     */
    public static final int SC_BAD_GATEWAY = 502;

    /**
     * Status code (503) indicating that the HTTP server is temporarily overloaded, and unable to handle the request.
     */
    public static final int SC_SERVICE_UNAVAILABLE = 503;

    /**
     * Status code (504) indicating that the server did not receive a timely response from the upstream server while acting
     * as a gateway or proxy.
     */
    public static final int SC_GATEWAY_TIMEOUT = 504;

    /**
     * Status code (505) indicating that the server does not support or refuses to support the HTTP protocol version that
     * was used in the request message.
     */
    public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
}
常见应用
  1. 向浏览器输出信息
  2. 下载文件
  3. 验证码功能
  4. 实现重定向
1.下载文件
  • 要获取下载文件的路径
  • 下载的文件名
  • 设置想办法让浏览器能够支持下载我们需要的东西
  • 获取下载文件的输入流
  • 创建缓冲区
  • 获取OutputStream对象
  • 将FileOutputStream流写入到buffer缓冲区
  • 使用OutputStream将缓冲区中的数据输出到客户端
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//		 要获取下载文件的路径
//  String rp = this.getServletContext().getRealPath("/15196900621605176.jpg");
    String rp = "C:\\Users\\hai\\Desktop/15196900621605176.jpg";
//		 下载的文件名
		String fileName = rp.substring(rp.lastIndexOf("\\")+1);
//		 设置想办法让浏览器能够支持下载我们需要的东西,中文文件用URLEncoder.encode(fileName,"UTF-8")编码,否则可能会乱码
		response.setHeader("Content-disposition","attachment;filename="+fileName);
//		 获取下载文件的输入流
		FileInputStream in = new FileInputStream(rp);
//		 创建缓冲区
		int len = 0;
		byte[] buffer = new byte[1024];
//		 获取OutputStream对象
		ServletOutputStream outputStream = response.getOutputStream();
//		 将FileOutputStream流写入到buffer缓冲区
		while((len=in.read(buffer))>0) {
			outputStream.write(buffer, 0, len);
		}
		in.close();
		outputStream.close();
//		 使用OutputStream将缓冲区中的数据输出到客户端
		
		
	}

测试结果:

2. 验证码功能

验证怎么来的?

  1. 前端实现
  2. 后端实现,需要用到Java的图片类,生成一个图片
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//如何让浏览器3秒自动刷新一次
		response.setHeader("refresh","5");
		//在内存中创建一个图片
		BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
		//得到图片
		Graphics2D g = (Graphics2D) image.getGraphics();
		
		//设置图片的背景颜色
		g.setColor(Color.white);
		g.fillRect(0, 0, 80, 20);
		//给图片写数据
		g.setColor(Color.blue);
		g.setFont(new Font(null,Font.BOLD,20));
		g.drawString(makeNum(),0,20);
		//告诉浏览器这个请求用图片的方式打开
		response.setContentType("image/jpeg");
		//网站存在缓存,不让它缓存
		response.setContentType("expires");
		response.setHeader("Cache-Control","no-cache");
		response.setHeader("Pragma","no-cache");
		//把图片给浏览器
		ImageIO.write(image, "jpg",response.getOutputStream());
	}

	
	private String makeNum() {   //生成随机数
		Random random = new Random();
		String num = random.nextInt(9999999)+ "";
		StringBuffer sb = new StringBuffer();
		//保证7位数随机数
		for (int i=0;i<7-num.length();i++) {
			sb.append("0");
		}
		num = sb.toString()+ num;
		return num;
	}

测试结果:

在这里插入图片描述

3.实现重定向

一个web资源收到客户端请求后会告诉客户端去访问另一个web资源,通过另一个资源访问

response.sendRedirect("/jjj/yanzheng");
//结果会跳转到yanzheng这个界面
//原理:
//response.setHeader("Location", "/jjj/yanzheng");
//response.setStatus(302);
面试题:请你聊聊重定向和转发的区别?
  • 相同点:

    页面都会实现跳转

  • 不同点:

    1. 请求转发的时候 URL不会发生变化
    2. 重定向时,URL地址栏会发生变化
HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过HTTP协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过HttpServletRequest方法来获得客户端的信息

  • 获取前端的信息,转发
<!DOCTYPE HTML><html lang="en"><head>
<meta charset="UTF-8">
<title>Apache Tomcat Examples</title>
</head>
<body>

<form action="http://localhost:8080/jjj/dl" method="post">
<p>
	用户名:<input type="text" name="username">
	密码: <input type="password" name="password">
	</p>
	<input type="submit">
</form>


</body>
</html>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //解决浏览器中文乱码问题
		response.setCharacterEncoding("utf-8");
		request.setCharacterEncoding("utf-8");
    	response.setContentType("text/html;charset=utf-8");
    //获取前端的信息
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String[] hoobys = request.getParameterValues("hoobys");
    //重定向
//		response.sendRedirect("/jjj/new.jsp");
    //转发
		request.getRequestDispatcher("/new.jsp").forward(request, response);
	}

四、Cookie\Session

会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,然后关闭浏览器,这个过程叫做会话

有状态会话:客户端来过,下次再来的时候,浏览器知道来过

一个网站怎么证明你来过?

客户端-------------->服务端

  1. 服务端给客户端一个信件,客户端下次访问时带上信件就可以了:Cookie
  2. 服务端登记你来过了,下次来的时候就会匹配你:Session

保存会话的两种技术

Cookie

  • 客户端技术(响应,请求)

Session

  • 服务器技术,可以把信息和数据放在Session中
常见问题:网站登录后,下次就不用再登陆了,第二次直接访问就行了
Cookie[] cookies = request.getCookies(); //获得Cookie
cookie.getName() //获得cookie中的key
cookie.getValue()//获得cookie中的value
Cookie time = new Cookie("time",System.currentTimeMillis()+""); //新建一个cookie
time.setMaxAge(24*60*60); //设置cookie有效期
response.addCookie(time); //响应一个cookie给客户端

cookie:一般会保存在本地的用户目录下appdata

一个网站cookie是否有上限?

  1. 一个cookie只能保存一个信息
  2. 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
  3. cookie大小有限制4kb
  4. 300个cookie浏览器上限

cookie删除

  1. 不设置有效期,关闭浏览器,自动失效
  2. 设置有效期为0
//再创建一个cookie,名字要和要删除的cookie名一致
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Cookie cookie = new Cookie("time",System.currentTimeMillis()+"");
		cookie.setMaxAge(0);
		response.addCookie(cookie);
	}

Session(重点)

什么是Session:

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
  • 用户登录之后,整个网站它都可以访问------>保存用户信息,保存购物车信息

Cookie\Session的区别:

  • Cookie是把用户的数据写给用户浏览器,浏览器保存
  • Session把用户的数据写到用户独占Session中,服务器端保存

使用场景:

  • 保存登录用户信息
  • 购物车信息
  • 再整个网站中经常使用的数据会放在Session
		response.setCharacterEncoding("utf-8");
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//得到session
		HttpSession session = request.getSession();
		//给session中存东西
		session.setAttribute("name", "hai");
		
		//获得session的id
		String id = session.getId();
		
		//判断session是不是新创建
		if(session.isNew()) {
			response.getWriter().write("创建成功,id="+id);
			
		}else {
			response.getWriter().write("创建已经存在了,id="+id);
		}
//注销后会立马生成一个新的
HttpSession session = request.getSession();
		session.removeAttribute("name");
		//手动注销session
		session.invalidate();
//获得session中数据
HttpSession session = request.getSession();
		Object attribute = session.getAttribute("name");
		response.getWriter().write(attribute.toString());

Session失效时间,在web.xml文件中配置

<!-- session默认失效时间 -->
  <session-config>
   <!-- session默认失效时间为1分钟 -->
  	<session-timeout>1</session-timeout>
  </session-config>

五、JSP文件

JSP和HTML的区别
  • jsp页面中可以嵌入Java代码,为用户提供动态数据
  • html页面只会给用户提供静态的数据
本质:

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet,jsp最终也会被转换为一个Java类,它也是个servlet

在jsp页面中:只要是Java代码就会原封不动的输出;如果是HTML代码则会被转换为:

out.write("<html>\r\n"); //以这样的格式输出到前端

JSP基本使用:JSP的基本使用总结_Nice2cu_Code的博客-CSDN博客_jsp的使用场景

JSP基础语法
四个依赖:
<dependencies>
    <!-- Servlet 依赖 -->
    <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>5.0.0</version>
    <scope>provided</scope>
</dependency>
<!-- JSP 依赖 -->
<!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp/jakarta.servlet.jsp-api -->
<dependency>
    <groupId>jakarta.servlet.jsp</groupId>
    <artifactId>jakarta.servlet.jsp-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<!-- JSTL 表达式的依赖 -->
<!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl -->
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>jakarta.servlet.jsp.jstl</artifactId>
    <version>2.0.0</version>
</dependency>
<!-- standard标签库 -->
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>
  </dependencies>
JSP常用<>
  1. <% %>叫做脚本片段,在jsp页面可以有多个脚本片段,但是多
    个脚本片段之间要保证结构完整。
  2. <%! %>称作声明,其中写的内容将来会直接翻译在Servlet类中,因为我们可以在类中定义方法和属性以及全局变量,所以我们可以在<%! %>中声明方法、属性、全局变量。
  3. <%= %>称作jsp表达式,用于将已经声明的变量或者表达式输出到网页上面。
  4. 直接写在jsp页面中的代码称作模板元素,将来会Servlet的Service方法中的out.write(“___”)中,作为输出内容。

JSP中的<>应用:JSP页面中<%!%>与<%%>与<%=%>

<% %>
<%= %>
<%! %>
<%-- 注释 --%>
<%-- jsp的注释不会出现在web页面上,HTML的注释会 --%>
JSP表达式
<%--jsp表达式
作用:用来将程序的输出到客户端
<%= 变量或者表达式%>
 --%>
<%= new java.util.Date()%>
JSP脚本片段
<%-- jsp脚本片段 --%>
<%
	int sum=0;
	for(int i=0;i<=10;i++){
		sum+=i;
	} %>
	out.print(sum);

脚本混实现
<%-- 脚本在实现 --%>
<%
for(int i=0;i<5;i++){
%>
<h3>hello <%=i%></h3>
<%
}
%>
JSP声明(实现全局变量)

上面的代码都是写在方法下的,jsp也支持写在全局下

<%!
 public static void hai(){
	 System.out.print("你猜猜我是谁?");
 }
 %>
JSP声明:

会被编译到jsp生成的Java类中,其他的会被生成到_jspService方法中

在jsp中嵌入Java代码即可

自定义一个错误页面

web.xml下的配置:

<error-page>
  	<error-code>404</error-code>
  	<location>/Error/404.jsp</location>
  </error-page>
  <error-page>
  	<error-code>500</error-code>
  	<location>/Error/500.jsp</location>
  </error-page>

创建一个jsp文件:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<title>500</title>
</head>
<body>
<img alt="500" src="../image/500.png">
</body>
</html>
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<title>404</title>
</head>
<body>
<img alt="" src="../image/404.png">
</body>
</html>

测试结果:

在这里插入图片描述

JSP指令

JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。
推荐菜鸟:JSP 指令

<%-- 显示声明这是一个错误页面 --%>
<%@ page isErrorPage="true" %> 
<%@ page ... %> 
<%-- 把文件包含进去 --%>
<%@ include file="" %>
...
九大内置对象
  • Page Context (存东西)
  • Request (存东西)
  • Response
  • Session (存东西,例如:购物车)
  • Application [Servlet Context] (存东西,例如:聊天框)
  • config [Servlet Config]
  • out
  • page
  • exception
<%-- 内置对象 --%>
<%
request.setAttribute("name0", "hai0");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name1", "hai1");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name2", "hai2");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
pageContext.setAttribute("name3", "hai3");//保存的数据只在一个页面中存在
%>

<%--脚本片段中的代码,会被原封不动的生成到。JSP.java --%>
<%
//从pageContext取出,通过寻找的方式来
//从底层到高层(作用域):page-->request-->session--application

String name3=(String)pageContext.findAttribute("name3");
String name2=(String)pageContext.findAttribute("name2");
String name1=(String)pageContext.findAttribute("name1");
String name0=(String)pageContext.findAttribute("name0");
%>

<h1>显示:</h1>
<hr>
<p>${name3}<br>
   ${name2}<br>
   ${name1}<br>
   ${name0}<br>
   ${name4}<br>  <%--不存在--%>
</p>
JSP标签、JSTL标签、EL表达式(重点)
EL表达式:${}
  • 获取数据
  • 执行运算
  • 获取web开发的常用对象
JSP标签
<%--http://localhost:8080/rr/New2.jsp?name=hai&age=20 --%>
<jsp:forward page="/New2.jsp">
	<jsp:param value="name" name="hai"/>
	<jsp:param value="age" name="20"/>
</jsp:forward>
===============================================
<jsp:include page="/New2.jsp"></jsp:include>
<h1>hello</h1>
<jsp:include page="/New2.jsp"></jsp:include>

上述代码会在浏览器上从上到下显示:

New.jsp的内容
hello
New.jsp的内容

JSTL标签

JSTL标签库的使用就是为了弥补HTML标签的不足,它自定义许多标签,可以供我们使用,标签的功能和Java代码一样

JSTL标签库:JSP 标准标签库(JSTL) | 菜鸟教程 (runoob.com)

  • 核心标签(掌握部分即可)
 <%--引入JSTL核心标签库 --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
if测试:
<hr>
<form action="" mathod="get">
	<input type="text" name="username" value="${param.username}">
	<input type="submit">

</form>
<c:if test="${param.username=='hai'}" var="ture">
	<c:out value="hai欢迎您!"></c:out>

</c:if>
	<c:out value="${ture}"></c:out>

测试结果:

在这里插入图片描述

set/chhose测试:
<%--set 定义一个变量 choose相当于switch --%>
 <c:set var="s" value="85"></c:set>
 <c:choose>
 	<c:when test="${s>=90}">
 	优秀
 	</c:when>
 	<c:when test="${s>=80}">
 	一般优秀
 	</c:when>
 	<c:when test="${s>=70}">
 	优良
 	</c:when>
 	<c:when test="${s>=60}">
 	及格
 	</c:when>
 </c:choose>
c:forEach测试:
<%--c:forEach 遍历 --%>
	<%
	ArrayList<Object> p = new ArrayList<>();
	p.add(0, "hai0");
	p.add(1, "hai1");
	p.add(2, "hai2");
	p.add(3, "hai3");
	p.add(4, "hai4");
	request.setAttribute("list",p);

	%>
<%-- 
items 要遍历的对象
var 每次遍历的变量
begin 从哪开始
end  到那结束
step  步长
--%>	
	<c:forEach var="p" items="${list}">
		<c:out value="${p}"></c:out>
	</c:forEach>
	
<hr>
	<c:forEach var="p" items="${list}" begin="1" end="3" step="2">
		<c:out value="${p}"></c:out>
	</c:forEach>	
	

测试结果:

在这里插入图片描述

  • 格式化标签
  • SQL 标签
  • XML 标签
  • JSTL 函数

六、MVC三层架构

什么是MVC: Model View Controller 模型、视图、控制器

  • 早些年:用户直接访问控制层,控制层就可以直接操作数据库;
servlet ----> CRUD ----> 数据库

servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

程序员调用 <------JDBC<-------MySQL Oracle SQLserver …

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

Model(模型)
  • 业务处理:业务逻辑(Service)

  • 数据持久层

View(视图)
  • 展示数据
  • 提供链接发起servlet请求(a,from,img…)
Controller(控制器)
  • 接收用户请求:(req:请求数据、Session信息)
  • 交给业务层处理对应的代码
  • 控制视图的跳转

七、Filter(过滤器)

Filter(过滤器):用来过滤网站的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sNkzLRVe-1671708205280)(D:\image\v2-r.png)]

Filter作用:

  1. 解决文件乱码问题
  2. 登陆验证

创建Filter步骤:

  1. 在pom.xml下连接到数据库
<!-- 连接mysql数据库 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
  1. 编写Filter(解决文件乱码问题)

在这里插入图片描述

public class NewFilter extends HttpFilter implements Filter {
           
    public NewFilter() {
        super();
        // TODO Auto-generated constructor stub
    }

	//初始化:web服务器启动它就初始化了
	public void destroy() {
		
	}

	//Chain:链
	/*
	 1.过滤中的所有代码,在过滤特定请求的时候都会执行
	 2.必须要让过滤器继续执行
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		
		System.out.println("doFilter执行:");
		chain.doFilter(request, response); //放行doFilter,让我们的请求继续走,如果不写就停下了
		
	}

	//销毁
	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("销毁NewFilter");
	}
}
  1. 在web.xml中配置Filter
<filter>
    <display-name>NewFilter</display-name>
    <filter-name>NewFilter</filter-name>
    <filter-class>com.hai.NewFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>NewFilter</filter-name>
    <url-pattern>/NewFilter</url-pattern> <!-- /*可以指代文件下所有页面 -->
  </filter-mapping>

八、Listener(监听器)

实现一个监听器的接口:(有n种)

//统计网站在线人数  :   统计session
public class NewListener extends HttpServlet implements HttpSessionListener {
       
    public NewListener() {
        super();
        // TODO Auto-generated constructor stub
    }

	//创建session监听 : 看你的一举一动
    //一旦创建一个session就会触发一次这个监听
    public void sessionCreated(HttpSessionEvent se)  { 
         ServletContext servletContext = se.getSession().getServletContext();
         Integer attribute = (Integer)servletContext.getAttribute("OnlineCount");
         
         if(attribute==null) {
        	 attribute = new Integer(1);
         }else {
        	 int intValue = attribute.intValue();
        	 attribute = new Integer(1+intValue);
         }
         
         servletContext.setAttribute("OnlineCount", attribute);
         
         
    }

	//销毁session监听
    //一旦销毁一个session就会触发一次这个监听
    public void sessionDestroyed(HttpSessionEvent se)  { 
    	 ServletContext servletContext = se.getSession().getServletContext();
         Integer attribute = (Integer)servletContext.getAttribute("OnlineCount");
         
         if(attribute==null) {
        	 attribute = new Integer(0);
         }else {
        	 int intValue = attribute.intValue();
        	 attribute = new Integer(intValue-1);
         }
         
         servletContext.setAttribute("OnlineCount", attribute);
         
    }	
}
/*
session销毁
1. 手动销毁  se.getSession().invalidate();
2. 自动销毁  在web.xml中配置,如下:

补充:Integer类 :Integer详解_白啊白啊的博客-CSDN博客_integer运算

在web.xml配置

<listener>
    <listener-class>com.hai.NewListener</listener-class>
  </listener>
  <session-config>
  	<session-timeout>1</session-timeout>
  </session-config>

测试

<div>
<h3>当前有</h3>
<span style="color:red"><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>
<h3>个人在线</h3>
</div>

测试结果:

在这里插入图片描述

九、JDBC回顾

什么是JDBC:等价于中间商,将application和数据库连接起来

连接MySQL (简单的实现JDBC)

// TODO Auto-generated method stub
		 String url = "jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
		 String user = "root";
		 String password = "123456";
		//加载驱动
		 Class.forName("com.mysql.cj.jdbc.Driver");
		 //连接数据库
		 Connection connection = DriverManager.getConnection(url,user,password);
		 //向数据库发送SQL的对象statement
		 Statement statement = connection.createStatement();
		 
		 //编写SQL
		String sql = "select * from users;";
		ResultSet resultSet = statement.executeQuery(sql);
		 
		while(resultSet.next()) {
			System.out.print("id="+resultSet.getObject("id")+"\t");
			System.out.print("name="+resultSet.getObject("name")+"\t");
			System.out.print("password="+resultSet.getObject("password")+"\t");
			System.out.print("email="+resultSet.getObject("email")+"\t");
			System.out.print("birthday="+resultSet.getObject("birthday")+"\t");
			System.out.println();
		}
		 //关闭,先开后关
		resultSet.close();
		statement.close();
		connection.close();
	}
用预编译(PreparedStatement)编写
public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		 String url = "jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
		 String user = "root";
		 String password = "123456";
		//加载驱动
		 Class.forName("com.mysql.cj.jdbc.Driver");
		 //连接数据库
		 Connection connection = DriverManager.getConnection(url,user,password);
		 //向数据库发送SQL的对象statement
		 //编写SQL
		 String sql = "insert into users(id,name,password,email,birthday)value(?,?,?,?,?);";
		 //预编译
		 PreparedStatement statement = connection.prepareStatement(sql);
		 
		 statement.setInt(1, 4);
		 statement.setString(2, "五六七");
		 statement.setString(3, "123456");
		 statement.setString(4, "null");
		 statement.setDate(5,new Date(new java.util.Date().getDate()));
		 
		 
		 int update = statement.executeUpdate();
		 if(update>0) {
			 System.out.println("成功注册");
		 }
		 //关闭,先开后关
		
		statement.close();
		connection.close();
	}

}
用Servlet编写JDBC
  1. Maven文件驱动MySQL需要的包
<!-- 连接mysql数据库 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<!-- 以及java.sql包和jakarta.sql包 -->
  1. 编写一个servlet文件
public void init() {
		 String url = "jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
		 String user = "root";
		 String password = "123456";
		//加载驱动
		 try {
			Class.forName("com.mysql.cj.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 //连接数据库
		 try {
			connection = DriverManager.getConnection(url,user,password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String id = request.getParameter("id");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String email = request.getParameter("email");
		String birthday = request.getParameter("birthday");
		 String sql = "insert into users(id,name,password,email,birthday)value(?,?,?,?,?);";
		 //预编译
		 PreparedStatement statement;
		try {
			statement = connection.prepareStatement(sql);
			 statement.setString(1, id);
			 statement.setString(2, username);
			 statement.setString(3, password);
			 statement.setString(4, email);
			 statement.setString(5,birthday);
			int update = statement.executeUpdate();
			 if(update>0) {
				 System.out.println("成功注册");
			 }
			//关闭,先开后关
				statement.close();
				connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		response.sendRedirect("/bbb/login.jsp");	
	}
  1. 编写一个jsp文件(实现在浏览器上看见)
<form action="http://localhost:8080/bbb/Longin" mathod="post">
<h3>注册:</h3>
<p>
ID:<input type="number" name="id">
名字:<input type="text" name="username"><br>
密码:<input type="password" name="password">
Email:<input type="text" name="email"><br>
生日:<input type="date" name="date"><br>
<input type="submit">
  1. 编辑web.xml
  <servlet>
    <description></description>
    <display-name>LonginServlet</display-name>
    <servlet-name>LonginServlet</servlet-name>
    <servlet-class>com.hai.LonginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LonginServlet</servlet-name>
    <url-pattern>/Longin</url-pattern>
  </servlet-mapping>

测试:
在这里插入图片描述
“提交”后跳转到的新页面【response.sendRedirect(“/bbb/login.jsp”); 】:
在这里插入图片描述
后台显示的内容:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

海量的海

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

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

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

打赏作者

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

抵扣说明:

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

余额充值