[Crazy God Talks Java] Detailed Notes from JavaWeb Introduction to Practical Combat (Complete)

@[toc]7

1. Basic concepts

1.1. Preface

web development:

  • web, meaning web page, www.baidu.com·
  • static web
    • html,css
    • The data available for everyone to see never changes!
  • dynamic web
    • Taobao, almost all websites;
    • The data provided to everyone will always change, and everyone sees different information at different times and in different places!
    • Technology stack: Servlet/JSP, ASP, PHP

1.2. Web application web application:

Programs that provide browser access;

  • a.html, b.html... multiple web resources. These web resources can be accessed by the outside world and provide services to the outside world;
  • Any page or resource you can access exists on a computer somewhere in the world.
  • URL
  • This unified web resource will be placed in the same folder, web application > Tomcat: server
  • A web application consists of multiple parts (static web, dynamic web)
    • html,css,js
    • jsp,servlet
    • Java program
    • jar package
    • Configuration file (Properties)

After the Web application program is written, if you want to provide it for external access, you need to use a service to manage it uniformly.

1.3. Static web

  • *.htm, *.html are the background of network users. If these things always exist on the server, we can read them directly and require network;
  • image.png
  • Disadvantages of static web
    • Web pages cannot be updated dynamically, and all users see the same page.
      • Carousel image, click special effects: pseudo-dynamic
      • JavaScript [In actual development, it is used the most]
      • VBScript
    • It cannot interact with the database (data cannot be persisted and users cannot interact)

1.4. Dynamic web

The page will be displayed dynamically, and "the display effect of the web page varies from person to person"
image.png
Disadvantages:

  • There is an error in adding dynamic web resources to the server. We need to rewrite our background program and re-publish it;
    • Advantages of downtime maintenance:
  • Web pages can be updated dynamically, and all users will not see the same page.
  • It can interact with the database (data persistence: registration, product information, user information...)
    image.png

2. web server

2.1. Technical explanation

ASP:

  • Microsoft: The earliest popular one in China is ASP;
  • ·Embedded VB script, ASP+COM in HTML;
  • ·In ASP development, basically every page has several lines of business code, and the page is extremely confusing.
  • ·High maintenance costs!
  • C#
  • IIS

php:

  • PHP development speed is very fast, its functions are very powerful, cross-platform, and the code is very simple (70%, WP)
  • Unable to carry large amounts of traffic (limitations)

jSP/Servlet:
B/S; browsing and server C/S: client and server

  • The B/S architecture mainly promoted by Sun Company
  • Based on Java language (all large companies, or some open source components, are written in Java)
  • Can bear the impact of the three high issues;
  • The syntax is like ASP, ASP->JSP, strengthening market strength;

2.2. web server

The server is a passive operation, used to process some of the user's requests and give the user some response information;
IS Microsoft; ASP., the Tomcat
that comes with Windows is oriented to Baidu programming: Tomcat is the Apache Software Foundation (Apache Software Foundation) A core project in the jakarta project, the latest Servlet and JSP specifications can always be reflected in Tomcat. Because Tomcat has advanced technology, stable performance, and is free, it is deeply loved by lava enthusiasts and has been favored by some software developers. recognized and become a popular web application server. Tomcat server is a free open source web application server. It is a lightweight application server. It is commonly used in small and medium-sized systems and situations where there are not many concurrent access users. It is the first choice for developing and debugging JSP programs. For a Java web beginner, it is the best choice Tomcat actually runs JSP pages and Serlets. After the latest version of Tornct 9.0 has been working for 3-5 years, you can try to write a Tomcat server by hand; download tomcat:

image.png





  1. Install or unzip
  2. Understand configuration files and directory structure
  3. What this thing does

3、Tomcat

3.1 Install tomcat tomcat

Official website: http://tomcat.apache.org/
image.png
image.png

3.2. Tomcat startup and configuration

Folder function:
image.png
image.png
Access test: http://localhost:8080/
Possible problems:

  1. Java environment variables are not configured
  2. Crash issue: compatibility needs to be configured
  3. Garbled code problem: Settings in the configuration file

You can modify java.util.logging.ConsoleHandler.encoding = GBK in conf/logging.properties to solve the garbled problem (not recommended)

3.3. Configuration

image.png
Configurable startup port number

  • The default port number of tomcat is: 8080
  • mysql:3306
  • http:80
  • https:443
<Connector port="8081" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />

Configurable host name

  • The default host name is: localhost->127.0.0.1
  • The default website application storage location is: webapps
<Host name="www.qinjiang.com"  appBase="webapps"
    unpackWARs="true" autoDeploy="true">
// name 默认是loaclhost, 改了之后,需要去host里面改DNS映射关系

Difficult interview question:
Please tell me how to access the website!

  1. Enter a domain name; press Enter
  2. Check whether there is this domain name mapping in the C:\Windows\System32\drivers\etc\hosts configuration file of this machine;
    1. Yes: directly return the corresponding IP address. In this address, there is the web program we need to access, which can be accessed directly.
    2. No: Go to the DNS server to search, and if it is found, it will return. If it cannot be found, it will return if it cannot be found;
      image.png

4. You can configure environment variables (optional)

3.4. Publish a web website

If you don’t know it, imitate it first

  • Put the website you wrote in the specified web application folder (webapps) in the server (Tomcat) and you can access it.

The structure a website should have

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

HTTP Protocol: Interview
with Maven: Build Tool

  • Maven installation package

Getting started with Servlets

  • HelloWorld!
  • Servlet configuration·principle

4、Http

4.1. What is HTTPHTTP

(Hypertext Transfer Protocol) is a simple request-response protocol that usually runs on top of TCP.

  • Text: html, string,…
  • Hypertext: pictures, music, videos, positioning, maps...
  • Port:80

HTTPS: secure

4.2. Two eras

  • http1.0
    • HTTP/1.0: After the client can connect to the web server, it can only obtain one web resource and disconnect
  • http2.0
    • HTTP/1.1: After the client can connect to the web server, it can obtain multiple web resources.

4.3. HTTP request

  • Client – ​​Request – Server

Baidu:

Request URL:https://www.baidu.com/   请求地址
Request Method:GET    get方法/post方法
Status Code:200 OK    状态码:200
Remote(远程) Address:14.215.177.39:443

Accept:text/html  
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9    语言
Cache-Control:max-age=0
Connection:keep-alive
1. Request line
  • Request method in request line: GET
  • Request method: Get, Post, HEAD, DELETE, PUT, TRACT.…
    • get: The request can carry relatively few parameters, the size is limited, and the data content will be displayed in the URL address bar of the browser. It is unsafe, but efficient.
    • Post: There is no limit on the parameters that the request can carry, and there is no limit on the size. The data content will not be displayed in the browser's URL address bar. It is safe, but not efficient.
2. Message header
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.

4.4. HTTP response

  • Server – Response….Client

Baidu:

Cache-Control:private    缓存控制
Connection:Keep-Alive    连接
Content-Encoding:gzip    编码
Content-Type:text/html   类型  
1. Response body
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;
2. Response status code

200: Request response successful 200
3xx: Request redirection·Redirection: You go to the new location I gave you;
4xx: Resource not found 404·The resource does not exist;
5xx: Server code error 500 502: Gateway error
Common interview questions :
What did you experience when you entered the address in the address bar of your browser and pressed Enter when the page was displayed?

5、Maven

Why should I learn this technology?

  1. In Java web development, a large number of jar packages need to be used, and we import them manually;
  2. How can I have something automatically import and configure this jar package for me?

From this, Maven was born!

5.1 Maven project architecture management tool

We are currently using it to facilitate the import of jar packages!
The core idea of ​​Maven: Agreement is greater than configuration

  • There are restrictions, don't violate them.

Maven will stipulate how you should write our Java code, and you must follow this specification;

5.2 Download and install Maven

Official website:
image.png
After downloading, unzip it;

5.3 Configure environment variables

Configure the following configuration in our system environment variables:

  • The bin directory under the M2_HOME maven directory
  • MAVEN_HOME maven directory
  • Configure %MAVEN_HOME%\bin in the system path

image.png
image.png
Test whether Maven is installed successfully and ensure that it must be configured!

5.4 Alibaba Cloud Image

  • Mirrors: mirrors
  • Function: Speed ​​up our downloads
  • In China, it is recommended to use Alibaba Cloud’s image
<mirror>
  <id>nexus-aliyun</id>  
  <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>  
  <name>Nexus aliyun</name>  
  <url>http://maven.aliyun.com/nexus/content/groups/public</url> 
</mirror>

5.5 Local warehouse

Local warehouse, remote warehouse; create a local warehouse: localRepository

在D:\java\Maven\apache-maven-3.8.7\ 新建一个空目录,maven-repo

<localRepository>D:\java\Maven\apache-maven-3.8.7\maven-repo</localRepository>

5.6 IDEA Deployment Maven

image.png
Note that you need to set it up twice. The setting location is as shown in the picture above!
image.png
When creating a project for the first time, use a generator. When
image.png
image.png
creating a project for the second time, use a generator.
image.png
As shown below, main-java places the java source code, resources places the configuration file, and test-java tests (the convention is greater than the configuration!)
image.png
and re-constructs it using the constructor. In a maven project, the following webapp package will appear.
image.png
Right-click to mark it as the source code directory, or you can set-project structure-module settings.

5.7 Configure Tomcat in IDEA

Current file in the upper right corner, pull down to select the configuration file, + a Tomcan local server.
image.png
Try not to set the path setting below to /Otherwise, the original ROOT directory in Tomcat will be deleted.
image.png
Then start it, and you can access helloworld.
image.png

5.8 pom file

pom.xml is the core configuration file of maven

<!--Maven版本和头文件-->
<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <!--这里是刚才配置的GAV-->
  <groupId>org.example</groupId>
  <artifactId>test2</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!--Packaging 项目的打包方式
  jar: java 应用
  war: JavaWeb 应用
  -->
  <packaging>war</packaging>

  <name>test2 Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  <!--项目依赖-->
  <dependencies>
    <!--具体依赖的jar包-->
		<!--高级之处在于自动下载对应的jar包-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
			<!--作用域 -->
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <!--配置-->
  <properties>
    <!--编码版本 -->
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <!--项目的默认编码-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <build>
    <finalName>test2</finalName>
  </build>
</project>

Since Maven has more conventions than configuration, we may encounter the problem that the configuration file we wrote cannot be exported or take effect. Solution: IDEA operation: The directory tree in the upper right corner
image.png
can display the dependent directory structure.Crtl+Alt+Shift+U

IDEA uses the Maven constructor. The default version of the generated web.xml is 2.3, which should be consistent with Tomcat, so you need to copy the web.xml content from the ROOT directory in Tomcat. It is currently 5.0.

<?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"
  metadata-complete="true">

</web-app>

6、Servlet

6.1. Introduction to Servlet

  • Servlet is a technology used by Sun to develop dynamic web
  • Sun provides an interface in these APIs called: Servlet. If you want to develop a Servlet program, you only need to complete two small steps:
    • Write a class to implement the Serlet interface
    • Deploy the developed java classes to the web server.

The Java program that implements the Servlet interface is called Servlet

6.2、HelloServlet

Serlvet interface Sun has two default implementation classes: HttpServlet, GenericServled

  1. Build an ordinary Maven project and delete the src directory inside. In the future, we will build Moudel in this project; this empty project is the main Maven project;
  2. Understanding of Maven parent and child projects;
    there will be in the parent project
<modules>
  <module>servlet-01</module>
</modules>

There will be sub-projects

<parent>
  <artifactId>javaweb-02-servlet</artifactId>
  <groupId>com.kuang</groupId>
  <version>1.0-SNAPSHOT</version>
</parent>

Java in the parent project can be used directly by sub-projects

son extends father
  1. Maven environment optimization
    1. Modify web.xml to be the latest
    2. Complete the maven structure
<?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"
  metadata-complete="true">

</web-app>
  1. Write a Servlet program
    1. Write a normal class
    2. Implement the Servlet interface, here we directly inherit HttpServlet
<?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>javaweb-02-servlet</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>servlet-01</module>
        <module>servlet-02</module>
    </modules>
    
    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        
         <!--这个是Tomcat10用的-->
         <!--https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
        <!--<dependency>-->
        <!--    <groupId>jakarta.servlet</groupId>-->
        <!--    <artifactId>jakarta.servlet-api</artifactId>-->
        <!--    <version>6.0.0</version>-->
        <!--</dependency>-->


    </dependencies>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>
package org.Martin.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    
    

    //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter(); //响应流
        writer.print("Hello,Serlvet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        doGet(req, resp);
    }
}
  1. Writing Servlet mapping
    Why mapping is needed: We write a JAVA program, but it needs to be accessed through a browser, and the browser needs to connect to the web server, so we
    need to Servlet we wrote in the web service and give it a browse The path that the server can access;
<!--注册Servlet-->
<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. Note when configuring Tomcat
    : Just configure the (project) path for project release; if there is no content in the deployment, refresh Maven on the right
  2. Start the test, OK!
    image.png

6.3. Servlet principle

Servlet is called by the web server. After receiving the browser request, the web server will:
image.png

6.4. Mapping problem

  1. A Servlet can specify a mapping path
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. A Servlet can specify multiple mapping paths
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello4</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello5</url-pattern>
</servlet-mapping>
  1. A servlet can specify a universal mapping path
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  1. Default request path
<!--默认请求路径,直接顶替了Index它成为了首页-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>
  1. Specify some suffixes or prefixes, etc...
<!--可以自定义后缀实现请求映射
注意点,*前面不能加项目映射的路径
例如不能这样: /*.txt /hello/*.txt
-->
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>*.qinjiang</url-pattern>
</servlet-mapping>
  1. Priority issue:
    The inherent mapping path is specified to have the highest priority. If it cannot be found, the default processing request will be used;
<!-- 访问/hello优先级高,不会进入error界面 -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>myError</servlet-name>
    <servlet-class>org.Martin.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>myError</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

6.5、ServletContext

When the web container starts, it will create a corresponding ServletContext object for each web program, which represents the current web application;

1. Share data

The data I save in this servlet can be obtained in another servlet;

public class HelloServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        //this.getInitParameter()   初始化参数
        //this.getServletConfig()   Servlet配置
        //this.getServletContext()  Servlet上下文
        ServletContext context = this.getServletContext();

        String username = "秦疆"; //数据
        context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username

    }

}
public class GetServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        ServletContext servletContext = this.getServletContext();

        // 获取HelloServlet保存的
        String username = (String) servletContext.getAttribute("username");

        resp.getWriter().print(username);
    }
}

<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>com.Martin.servlet.HelloServlet</servlet-class>
</servlet>    
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
  <servlet-name>gets</servlet-name>
  <servlet-class>com.Martin.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>gets</servlet-name>
  <url-pattern>/gets</url-pattern>
</servlet-mapping>

Test the access results; access hello first, and then access gets to take effect. Otherwise, hello did not submit data and gets cannot be accessed.

2. Get initialization parameters
<!--配置一些web应用初始化参数-->
<context-param>
  <param-name>url</param-name>
  <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>

<servlet>
    <servlet-name>gp</servlet-name>
    <servlet-class>com.Martin.servlet.GetParaServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>gp</servlet-name>
    <url-pattern>/gp</url-pattern>
</servlet-mapping>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    ServletContext context = this.getServletContext();
    String url = context.getInitParameter("url");
    resp.getWriter().print(url);
}
3. Request forwarding

Forwarded GP resources to my own page

	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        ServletContext context = this.getServletContext();
        System.out.println("进入了ServletDemo04");
        //RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
        //requestDispatcher.forward(req,resp); //调用forward实现请求转发;
        context.getRequestDispatcher("/gp").forward(req,resp);
    }

image.png
4. Read resource files
Properties

  • Create new properties in the java directory (this requires configuration)
  • Create new properties in the resources directory

Found: They are all packaged under the same path: target-classes, we commonly call this path classpath:
image.pngimage.png
Idea: A file stream is needed

username=admin	
password=root
public class GetPropertiesServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 在打包之后的target下的项目路径
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");

        Properties prop = new Properties();
        prop.load(is);
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");

        resp.getWriter().print(username+password);
    }
}

Access to test is ok;

6.6、HttpServletResponse

The web server receives the client's http request. For this request, it creates an HttpServletRequest
object representing the request and an HttpServletResponse representing the response;

  • If you want to get the parameters requested by the client: find HttpServletRequest
  • If you want to respond to the client with some information: Find HttpServletResponse
1. Simple classification

Method responsible for sending data to the browser

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

Method responsible for sending response headers to the browser

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String varl,long var2);
void addDateHeader(String var1,long var2);
void setHeader(String var1,String var2);
void addHeader(String var1,String var2);
void setIntHeader(String var1,int var2);
void addIntHeader(String varl,int var2);

response status code
image.png
image.png

2. Common applications
  1. Output a message to the browser (I’ve been talking about it forever, so I won’t talk about it anymore)
  2. download file
    1. To get the path to the downloaded file
    2. What is the name of the downloaded file?
    3. Setting up ways to enable the browser to support downloading what we need
    4. Get the input stream of the downloaded file
    5. Create buffer
    6. Get OutputStream object
    7. Write the FileOutputStream stream to the bufer buffer
    8. Use OutputStream to output the data in the buffer to the client!
package org.Martin.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 1. 要获取下载文件的路径
        String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/ctfshow.png");
        // String realPath = "E:\\Martin_Code\\java\\javaweb\\javaweb-02-servlet\\Response-01\\target\\Response-01\\WEB-INF\\classes\\ctfshow.png";
        System.out.println("文件路径:"+realPath);
        // 2. 下载的文件名是啥?
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        // 3. 设置想办法让浏览器能够支持下载我们需要的东西
        // "Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"))
        resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
        // 4. 获取下载文件的输入流
        FileInputStream fis = new FileInputStream(realPath);
        // 5. 创建缓冲区
        int len=0;
        byte[] buffer = new byte[1024];
        // 6. 获取OutputStream对象
        ServletOutputStream outputStream = resp.getOutputStream();
        // 7. 将FileOutputStream流写入到bufer缓冲区
        while ((len=fis.read(buffer))!=-1){
    
    
            // 8. 使用OutputStream将缓冲区中的数据输出到客户端!
            outputStream.write(buffer,0,len);
        }
        outputStream.close();
        fis.close();
    }
}

3. Verification code function

How did the verification come about?

  • Front-end implementation
  • Back-end implementation requires the use of Java's picture class to produce a picture
package org.Martin.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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 {
    
    

        // 如何让浏览器每5秒刷新一次
        resp.setHeader("refresh","3");

        // 在内存中创建一个图片
        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);

        // 告诉浏览器这个请求用图片的方式打开
        resp.setContentType("image/png");
        // 网站存在缓冲,不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        // 把图片写给浏览器
        ImageIO.write(image,"jpg",resp.getOutputStream());


    }

    // 生成随机数
    private String makeNum(){
    
    
        Random random = new Random();
        // 最大值,4位数
        String num = random.nextInt(9999) + "";
        StringBuffer sb = new StringBuffer();
        // 不足四位数,补充0
        for (int i = 0; i < 4-num.length(); i++) {
    
    
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }
}

<servlet>
  <servlet-name>ImageServlet</servlet-name>
  <servlet-class>com.kuang.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Imageservlet</servlet-name>
  <url-pattern>/img</url-pattern>
</servlet-mapping>
4. Implement redirection

image.png
Common scenarios:

  • User login
void sendRedirect(String var1) throws IOException;

test:

public class RedirectServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 跳转到哪里
        /*
        resp.setHeader("Location","./image");
        resp.setStatus(302);
         */
        // resp.sendRedirect(req.getContextPath()+"/image");
        resp.sendRedirect("./image");

    }
}

image.png
image.png
index.jsp

<html>
  <body>
    <h2>Hel1o World!</h2>

    <%--这里超交的路径,需要寻找到项目的路径--%>
      <%--${pageContext. request, contextPath}代表当前的项目--%>
        <form action="${pageContext. request.contextPath}/login" method="get">
          用户名: <input type="text" name="username"> <br>
          密码: <input type="password" name="password"> <br>
          <input type="submit">
        </form>
      </body>
      </html>

RequestTest.java

public class RequestTest extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        System.out.println("进入请求");
        // 处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username+password);

        // 重定向到成功,注意路径
        resp.sendRedirect(req.getContextPath()+"/success.jsp");
        // resp.sendRedirect("./success.jsp");
    }
}

Redirect page success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>success</h1>
</body>
</html>

web.xml configuration

<servlet>
  <servlet-name>requset</servlet-name>
  <servlet-class>com. kuang. servlet. RequestTest</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>requset</servlet-name>
  <url-pattern>/login</url-pattern>
</servlet-mapping>

Import dependent jar packages

<dependencies>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
</dependencies>

6.7、HttpServletRequest

HttpServletRequest represents the client's request. The user accesses the server through the Http protocol. All information in the HTTP request will be encapsulated into HttpServletRequest. Through this HttpServletRequest method, all the client's information is obtained;
image.png
image.png

1. Obtain parameters and request forwarding

image.png
Create your own class and need to inherit the HttpServlet class

public class LoginServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req. setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
        for (String hobby : req.getParameterValues("hobby")) {
    
    
            System.out.println(hobby);
        }

        // 请求转发 会保留项目地址  所以不用加这个 req.getContextPath()
        req.getRequestDispatcher("/success.jsp").forward(req,resp);

        System.out.println(req.getPathInfo()); // null
        System.out.println(req.getContextPath()); // /Request_01_war 项目的根路径
        System.out.println(req.getServletPath()); // /login 自己这个类的路径

    }
}

6.8. The difference between redirection and request forwarding!

image.png

// 重定向,需要根目录的地址
response.sendRedirect(req.getContextPath()+"/success.jsp");


// 请求转发, 会保留项目的根目录地址,不用加requset.getContextPath()来获取根目录地址
requset.getRequestDispatcher("/success.jsp").forward(req,resp);

// 前端获取项目的根地址
${
    
    pageContext.request.contextPath}

7、Cookie、Session

7.1. Conversation

Session : The user opens a browser, clicks on many hyperlinks, accesses multiple web resources, and closes the browser. This process can be called a session; stateful session:
a classmate has been to the classroom and we will know when he comes to the classroom next time. This classmate, who has been here before, calls it a stateful conversation;
how can you prove that you are a student from Xikai?
You drive west

  1. Invoice Xikai will give you the invoice
  2. School registration Xikai marks that you have been here

How can a website prove that you have been there?
client server

  1. The server sends a letter to the client, and the client can bring the letter with it the next time it visits the server; cookie
  2. The server registers that you have come, and I will match you next time you come; seesion

7.2. Two techniques for saving sessions

cookie

  • Client technology (response, request)

session

  • Server technology, using this technology, can the user's session information be saved? We can put information or data in Session!

Common common: After logging in to the website, you don’t need to log in again next time. You will be logged in directly the second time you visit!

7.3、Cookie

image.png

  1. Get cookie information from request
  2. The server responds to the client cookie
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie

代码:
public class CookieDemo01  extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 解决中文乱码,解决不了!!
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        // 写数据
        PrintWriter writer = resp.getWriter();

        // Cookie从服务器获取
        Cookie[] cookies = req.getCookies(); // 可能存在多个,是一个数组

        // 判断是否是第一次登录
        boolean flag = false;
        for (Cookie cookie : cookies) {
    
    
            if (cookie.getName().equals("lastTime")){
    
    
                flag=true;
                // cookie.getValue();是一个字符串
                // 字符串变整数时间戳
                long lastTime = Long.parseLong(cookie.getValue());
                Date date = new Date(lastTime);
                writer.write("Not first: ");
                writer.write(date.toLocaleString());
            }
        }
        if (!flag){
    
    
            writer.write("The First");
        }

        // 服务器更新Cookie  name value
        // System.currentTimeMillis()一个时间戳
        Cookie cookie = new Cookie("lastTime",String.valueOf(System.currentTimeMillis()));
        cookie.setMaxAge(24*60*60); //有效期
        resp.addCookie(cookie);
    }
}

Cookies: Generally stored in the local user directory AppData;
is there an upper limit for cookies on a website? Let’s talk about details

  • A cookie can only save one piece of information;
  • A web site can send multiple cookies to the browser, storing up to 20 cookies;
  • Cookie size is limited to 4kb;
  • 300 cookie browser limit

Delete cookies;

  • If you do not set a validity period, close the browser and it will automatically expire;
  • Set the validity period to 0;

encode decode:

URLEncoder.encode("秦疆","utf-8");
URLDecoder.decode(cookie.getValue(),"UTF-8");

7.4. Session (Key Points)

image.png
What is Session:

  • The server will create a Seesion object for each user (browser);
  • A Seesion occupies a browser. As long as the browser is not closed, this Session exists;
  • After the user logs in, the entire website can be accessed! –> Save user information; save shopping cart information…

scenes to be used:

  • Save the information of a logged in user;
  • Shopping cart information;
  • We save data that is frequently used throughout the website in Session;

Use Session:

public class SessionDemo01 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        //解决乱码
        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        // 得到Session
        HttpSession session = req.getSession();

        // session.removeAttribute("name"); 删除session中的name
        // session.invalidate(); 清除session,当浏览器再次访问,会生成新的session,应用于用户手动注销
        
        // 给Session 存信息 可以存一个对象
        session.setAttribute("name","Martin");
        session.setAttribute("Person",new Person("person.name",3));

        // 得到Session 的信息
        System.out.println(session.getAttribute("name"));
        System.out.println(session.getAttribute("Person"));

        // 获取Session ID
        String sessionId = session.getId();

        // 判断是不是新的
        if (session.isNew()){
    
    
            resp.getWriter().write("new: "+sessionId);
        }else {
    
    
            resp.getWriter().write("old: "+sessionId);
        }

        //Session创建的时候做了什么?
        //传递了一个Cookie, name="JSESSIONID" value=session.getId()
    }
}

Automatic session expiration: web.xml configuration

<!--设置Session默认的失效时间-->
<session-config>
  <!--15分钟后Session自动失效,以分钟为单位-->
  <session-timeout>15</session-timeout>
</session-config>

7.5. Comparison between Cookie and Session

  • Cookie
    • Get Cookiereq.getCookies()
    • Add a cookie array of key-value pairs:resp.addCookies(cookie)
    • Get the contents of the cookie:cookie.getName();cookie.getValue();
  • Session
    • GetSessionreq.getSession()
    • Add the key-value pair of the Session objectsession.setAttribute(name,value)
    • Get the contents of Session: session.getAttribute(name)
      | Cookie | Session | Token |
      | — | — | — |
      | When the user logs in for the first time:
  1. Client sends request
  2. The server sets the cookie and sends it to the client
  3. The client accepts the cookie, saves it locally, and brings the cookie with it the next time it visits.
  4. The server accepts the cookie and puts back the corresponding user's data (Cookie limitations: it can only be saved with key-value pairs, which is inefficient and introduces Session)
    | Every time the user logs in:
  5. Client sends request
  6. The server sets a unique SessionID and returns it to the client (using cookies)
  7. The client carries the SessionID every time it visits (brought in the form of a cookie)
  8. Because the server saves the SessionID of all users, the way to distinguish each user is to compare. The server saves too much data, and Token | appears
    when the user logs in:
  9. Client sends request
  10. The server generates a Token and returns it to the user. This Token stores the encrypted UserID and is used to distinguish users.
  11. The client carries the Token every time it accesses
  12. The server accepts the Token, decrypts it, and then gets the UserID to distinguish users; it does not use Session to save a large amount of SessionID data, saving space
    |

Cookie: can only save key-value pairs, low efficiency. Session is introduced. Session
: SessionID is the hash value of a string of key-value pairs, which is highly efficient (the server uses SessionIDs to match each other to verify and distinguish users), but they are all stored in the server. The server It's very uncomfortable, so Token Token is introduced
: save the encrypted UserID to the client, and the server decrypts it to get the UserID, which is very easy for the server.

8、JSP

8.1. What is JSP

Java Server Pages: Java server-side pages, also like Servlets, are used in dynamic web technologies!
The greatest feature:

  • Writing JSP is like writing HTML
  • the difference:
    • HTML only provides static data to users
    • JAVA code can be embedded in JSP pages to provide users with dynamic data;

8.2. JSP principles

Idea: How is JSP executed?

  • There are no problems at the code level
  • The internal working of the server is that there is a work directory in tomcat; if you use Tomcat in IDEA, a work directory will be produced in tomcat in IDEA.

C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat
The address of my computer: C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat\16a6cd02-6b09-4de3-a7fa-601b94a708b7\work\Catalina\localhost\Request_01_war\org\apache\jspThe discovery page was converted into a Java program!
image.png
The browser sends a request to the server. No matter what resource is accessed, it is actually accessing the Servlet!
The JSP will eventually be converted into a Java class!

JSP is essentially an encapsulated Servlet

//初始化
public void _jspInit() {
    
    

}
//销毁
public void _jspDestroy() {
    
    
}
//JSPService
public void _jspService(.HttpServletRequest request,HttpServletResponse response){
    
    
}

  1. Judgment request
  2. built-in objects
  3. Code added before outputting the page
  4. We can use the above objects directly in JSP pages!
final javax.servlet.jsp.PageContext pageContext;  //页面上下文
javax.servlet.http.HttpSession session = null;    //session
final javax.servlet.ServletContext application;   //applicationContext
final javax.servlet.ServletConfig config;         //config
javax.servlet.jsp.JspWriter out = null;           //out
final java.lang.Object page = this;               //page:当前
HttpServletRequest request;                       //请求
HttpServletResponse response;                     //响应
response.setContentType("text/html");       //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
                                          null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;

image.png
In the JSP page;
as long as it is JAVA code, it will be output intact;
if it is HTML code, it will be converted into: out.write("<html>\r\n");such a format and output to the front end!

8.3. JSP basic syntax

Any language has its own grammar, and JAVA has it. As an application of Java technology, JSP has some of its own expanded syntax (just know it, just know it!), and all Java syntaxes are supported!

JSP expression
<%-- 注释 --%> 
<%= 变量或者表达式%>  //作用:用来将程序的输出,输出到客户端
<%= new java.util.Date()%>
jsp script fragment
<%--jsp脚本片段--%>

<%
 int sum = 0;
 for (int i = 1; i <=100 ; i++) {
   sum+=i;
 }
 out.println("<h1>Sum="+sum+"</h1>");
%>

Reimplementation of script fragments

<%
 int x = 10;
 out.println(x);
%>
<p>这是一个JSP文档</p>
<%
 int y = 2;
 out.println(y);
%>

<hr>
 
 
<%--在代码嵌入HTML元素--%>
<%
 for (int i = 0; i < 5; i++) {
%>
 <h1>Hello,World  <%=i%> </h1>
<%
 }
%>
JSP declaration
<%!
 static {
   System.out.println("Loading Servlet!");
 }

 private int globalVar = 0;

 public void kuang(){
   System.out.println("进入了方法Kuang!");
 }
%>

JSP declaration: will be compiled into the JSP-generated Java class! Others will be generated into the _jspService method!
image.png
In JSP, just embed Java code!

<%%>  java代码片段
<%= %> 表达式的值
<%! %> jsp声明
 
<%--注释--%>

JSP comments will not be displayed on the client, HTML will!

8.4. JSP instructions

<%@page args.... %>
<%@include file=""%>

<%--@include会将两个页面合二为一,参数不能冲突--%>

<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>

<hr>


<%--jSP标签
   jsp:include:拼接页面,本质还是三个,参数互不影响
   --%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>

8.5, 9 built-in objects

  • PageContext stores things
  • Request to save something
  • Response
  • Session saves things
  • Application [ServletContext] save things
  • config 【ServletConfig】
  • out
  • page , no need to understand
  • exception
pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","秦疆4号");  //保存的数据只在服务器中有效,从打开服务器到关闭服务器

image.png
request: The client sends a request to the server. The generated data is useless after the user has read it. For example: news is useless after the user has read it!
Session: The client sends a request to the server, and the generated data can be used by the user for a while, such as a shopping cart; application: The client
sends a request to the server, and the generated data is used by one user, but other users may still use it. For example: chat data;

8.6, JSP tags, JSTL tags, EL expressions

<!-- JSTL表达式的依赖 -->
<dependency>
  <groupId>javax.servlet.jsp.jstl</groupId>
  <artifactId>jstl-api</artifactId>
  <version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
  <groupId>taglibs</groupId>
  <artifactId>standard</artifactId>
  <version>1.1.2</version>
</dependency>

EL expression: ${ }

  • retrieve data
  • perform operations
  • Get common objects used in web development

JSP tags

<%--jsp:include--%>
 
<%--
http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
--%>

<jsp:forward page="/jsptag2.jsp">
   <jsp:param name="name" value="kuangshen"></jsp:param>
   <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

/jsptag2.jsp
<%=request.getParameter("name")%>

The use of JSTL expression
JSTL tag library is to make up for the shortcomings of HTML tags; it customizes many tags and can be used by us. The functions of tags are the same as Java code! , need to introduce tag library
formatting tag
SQL tag
XML tag
core tag (master part)
image.png
JSTL tag library usage steps

  • Introduce the corresponding taglib<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  • Use the method
  • Tomcat also needs to introduce the jstl package, otherwise an error will be reported: JSTL parsing error

c:if

<head>
  <title>Title</title>
</head>
<body>
<h4>if测试</h4>

<hr>

<form action="coreif.jsp" method="get">
  <%--
  EL表达式获取表单中的数据
  ${param.参数名}
  --%>
  <input type="text" name="username" value="${param.username}">
  <input type="submit" value="登录">
</form>

<%--判断如果提交的用户名是管理员,则登录成功--%>
<!--   test是接受的值,var返回的boolean,cout输出value的值 -->
<c:if test="${param.username=='admin'}" var="isAdmin">
  <c:out value="管理员欢迎您!"/>
</c:if>

<%--自闭合标签--%>
<c:out value="${isAdmin}"/>

</body>

c:choose c:when

<body>

<%--定义一个变量score,值为85--%>

<c:set var="score" value="55"/>

  <c:choose>
    <c:when test="${score>=90}">
      你的成绩为优秀
    </c:when>
    <c:when test="${score>=80}">
      你的成绩为一般
    </c:when>
    <c:when test="${score>=70}">
      你的成绩为良好
    </c:when>
    <c:when test="${score<=60}">
      你的成绩为不及格
    </c:when>
  </c:choose>

</body>

c:forEach

<%
    ArrayList<String> peoples = new ArrayList<>();
    peoples.add(0,"张三");
    peoples.add(1,"李四");
    peoples.add(2,"王五");
    peoples.add(3,"赵六");
    peoples.add(4,"田六");
    request.setAttribute("list",peoples);
%>


<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin,   哪里开始
end,     到哪里
step,   步长
--%>
    
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>

<hr>

<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="${people}"/> <br>
</c:forEach>

9、JavaBean

Entity class
JavaBean has a specific way of writing:

  • There must be a parameterless constructor
  • Properties must be private
  • There must be corresponding get/set methods;

Generally used to map ORM to database fields;
ORM: Object Relational Mapping

  • Table—>Class
  • Fields–>Properties
  • Row record---->Object

people table

id name age address
1 Qinjiang No. 1 3 Xi'an
2 Qinjiang No. 2 18 Xi'an
3 Qinjiang No. 3 100 Xi'an
class People{
    
    
    private int id;
    private String name;
    private int id;
    private String address;
}

class A{
    
    
    new People(1,"秦疆1号",3"西安");
    new People(2,"秦疆2号",3"西安");
    new People(3,"秦疆3号",3"西安");
}

image.png

10. MVC three-tier architecture

  • What is MVC: Model view Controller model, view, controller
    • Model: corresponding correspondence between database tables and classes
    • View: jsp page
    • Controller: Servlet

10.1. Previous architecture

image.png
Users directly access the control layer, and the control layer can directly operate the database;

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护  
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

架构:没有什么是加一层解决不了的!
程序猿调用
↑
JDBC (实现该接口)
↑
Mysql Oracle SqlServer ....(不同厂商)

10.2. MVC three-tier architecture

image.png
Model

  • Business processing: business logic (Service)
  • Data persistence layer: CRUD (Dao - data persistence object)

View

  • display data
  • Provide a link to initiate a Servlet request (a, form, img...)

Controller (Servlet)

  • Receive user's request: (req: request parameters, session information...)
  • Hand it over to the business layer to process the corresponding code
  • Control the jump of the view
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库

11. Filter (key point)

For example, Shiro security framework technology is implemented using
Filter: Filter, used to filter website data;

  • Handle Chinese garbled characters
  • Login authentication….

(For example, to filter out curse words on the Internet, I *** myself 0-0)
image.png
Filter development steps:

  1. Guide package
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
    </dependencies>
  1. Write a filter
    1. Don’t make the wrong guide package (note)

image.png
Implement the Filter interface and rewrite the corresponding method.

package org.example.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    
    

    //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        System.out.println("CharacterEncodingFilter初始化");
    }

    //Chain : 链
       /*
       1. 过滤中的所有代码,在过滤特定请求的时候都会执行
       2. 必须要让过滤器继续执行
           chain.doFilter(request,response);
        */
    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("CharacterEncodingFilter执行前....");
        chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
        System.out.println("CharacterEncodingFilter执行后....");
    }

    //销毁:web服务器关闭的时候,过滤器会销毁
    public void destroy() {
    
    
        System.out.println("CharacterEncodingFilter销毁");
    }
}

  1. Configure Filter in web.xml
<filter>
  <filter-name>CharacterEncodingFilter</filter-name>
  <filter-class>org.example.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <!--只要是下方的请求,就会经过过滤器-->
  <url-pattern>/servlet/*</url-pattern>
</filter-mapping>

12. Listener

Implement a listener interface; (there are n types of listeners)

  1. Write a listener to implement the listener's interface...the dependent jar packageimage.png
  2. Register listener in web.xml
  3. It depends on the situation whether to use it!
//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {
    
    

    //创建session监听: 看你的一举一动
    //一旦创建Session就会触发一次这个事件!
    public void sessionCreated(HttpSessionEvent se) {
    
    
        ServletContext ctx = se.getSession().getServletContext();

        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
    
    
            onlineCount = new Integer(1);
        }else {
    
    
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }

    //销毁session监听
    //一旦销毁Session就会触发一次这个事件!
    public void sessionDestroyed(HttpSessionEvent se) {
    
    
        ServletContext ctx = se.getSession().getServletContext();

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
    
    
            onlineCount = new Integer(0);
        }else {
    
    
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }


    /*
Session销毁:
1. 手动销毁  getSession().invalidate();
2. 自动销毁
*/
}
<!--注册监听器-->
<listener>
  <listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
当前在线人数:<%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>

13. Common applications of filters and listeners

Listener: often used in GUI programming;

public class TestPanel {
    
    
    public static void main(String[] args) {
    
    
        Frame frame = new Frame("中秋节快乐");  //新建一个窗体
        Panel panel = new Panel(null); //面板
        frame.setLayout(null); //设置窗体的布局

        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(0,0,255)); //设置背景颜色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,255,0)); //设置背景颜色

        frame.add(panel);

        frame.setVisible(true);

        //监听事件,监听关闭事件
        frame.addWindowListener(new WindowAdapter() {
    
    
            @Override
            public void windowClosing(WindowEvent e) {
    
    
                super.windowClosing(e);
            }
        });

    }
}

Only after the user logs in can they enter the home page! After the user logs out, he cannot enter the homepage!

  1. After the user logs in, put the user's data into Sesison.
  2. When entering the homepage, it is necessary to determine whether the user has logged in; requirement: implemented in the filter!

image.png

// error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>没有权限或者密码错误</h1>
<a href="./login.jsp"> 请登录</a>
</body>
</html>

// login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
${pageContext.request.contextPath}
<form action="${pageContext.request.contextPath}/login" method="get">
    请输入用户名:<input type="text" name="username">
    <input type="submit">
</form>
</body>
</html>

// success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
<a href="${pageContext.request.contextPath}/logout">注销</a>
</body>
</html>
public class LoginServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        System.out.println("进入LoginServlet->doGet");
        System.out.println(req.getContextPath());
        // 如果是管理员登录,跳转到成功页面
        if (req.getParameter("username").equals("admin")){
    
    
            // 设置Session
            req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
            // 重定向需要获得根目录
            resp.sendRedirect(req.getContextPath()+"/security/success.jsp");
        }else{
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }
}

public class LogoutServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        System.out.println("LogoutServlet->doGet");
        // 销毁Session 或者 移除其中一个属性(建议后者,开销小
        Object userSession = req.getSession().getAttribute("USER_SESSION");

        if (userSession!=null){
    
    
            req.getSession().removeAttribute("USER_SESSION");
            resp.sendRedirect(req.getContextPath()+"/login.jsp");
        }else {
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }
}

public class LogoutFilter implements Filter {
    
    
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        Object userSession = req.getSession().getAttribute("USER_SESSION");
        if (userSession==null){
    
    
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
        filterChain.doFilter(req,resp);
    }
    public void destroy() {
    
    
    }
}
<!--登录验证-->
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>org.example.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>logout</servlet-name>
    <servlet-class>org.example.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>logout</servlet-name>
    <url-pattern>/logout</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>LogoutFilter</filter-name>
    <filter-class>org.example.filter.LogoutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LogoutFilter</filter-name>
    <url-pattern>/security/*</url-pattern>
</filter-mapping>

14、JDBC

What is JDBC: Java connection to database!
image.png
Requires jar package support:

  • java.sql
  • javax.sql
  • mysql-connecter-java… connection driver (must be imported)

Experimental environment setup

CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
  id INT PRIMARY KEY,
  `name` VARCHAR(40),
  `password` VARCHAR(40),
  email VARCHAR(60),
  birthday DATE
);

INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','[email protected]','2000-01-01');


SELECT	* FROM users;

Import database dependencies

<!--mysql的驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

Connecting to the database in IDEA:
image.png
JDBC fixed steps:

  1. Load driver
  2. Connect to the database, represent the database
  3. Send SQL object Statement to the database: CRUD
  4. Write SQL (different SQL according to business)
  5. Execute SQL
  6. Close the connection (open first and then close)
package org.example;

import java.sql.*;

public class TestJdbc {
    
    
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
        Statement statement = connection.createStatement();

        //4.编写SQL
        String sql = "select * from users";

        //5.执行查询SQL,返回一个 ResultSet  : 结果集
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()){
    
    
            System.out.println("id="+rs.getObject("id"));
            System.out.println("name="+rs.getObject("name"));
            System.out.println("password="+rs.getObject("password"));
            System.out.println("email="+rs.getObject("email"));
            System.out.println("birthday="+rs.getObject("birthday"));
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        rs.close();
        statement.close();
        connection.close();
    }
}

Precompiled SQL

package org.example;
import java.sql.*;

public class TestJdbc2 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.编写SQL
        String sql = "insert into  users(id, name, password, email, birthday) values (?,?,?,?,?);";

        //4.预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        // 注意这里第一个是ID,有没有自增,或者用不用赋值
        preparedStatement.setInt(1,4);//给第一个占位符? 的值赋值为1;
        preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;
        preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;
        preparedStatement.setString(4,"[email protected]");//给第四个占位符? 的值赋值为1;
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());

        //5.执行SQL
        int i = preparedStatement.executeUpdate();

        if (i>0){
    
    
            System.out.println("插入成功@");
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        preparedStatement.close();
        connection.close();
    }
}

Either everything
succeeds or everything fails!
ACID principle: ensure data security.

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务

转账:
A:1000
B:1000

A(900)   --100-->   B(1100) 

Junit unit testing
dependencies

<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
</dependency>

Simply using
the @Test annotation is only effective on methods. As long as the method with this annotation is added, it can be run directly!
Using annotations for reflection?

import org.junit.Test;

@Test
public void test(){
    
    
    System.out.println("Hello");
}

image.png
It is red when it fails:
image.png
build an environment

CREATE TABLE account(
    id INT PRIMARY KEY AUTO_INCREMENT,
    `name` VARCHAR(40),
    money FLOAT
    );

INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
package org.example;


import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestJdbc3 {
    
    

    @Test
    public void test() {
    
    
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "root";

        Connection connection = null;

        //1.加载驱动
        try {
    
    
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.连接数据库,代表数据库
            connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务,false 开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造错误
            //int i = 1/0;

            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();

            connection.commit();//以上两条SQL都执行成功了,就提交事务!
            System.out.println("success");
        } catch (Exception e) {
    
    
            try {
    
    
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
    
    
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                connection.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

15. SMBMS (supermarket management project)

SMBMS project experiment in episodes 30~37

Extended application

1. File upload

In Web applications, file upload and download functions are very common functions. Today we will implement the file upload and download functions in JavaWeb.

1. Preparation

For file upload, the browser submits the file to the server in the form of a stream during the upload process.
Generally, you choose to use the file upload component of apache's open source tool common-fileupload.
common-fileupload depends on the common-io package, so you also need to download this package.
Download the latest jar package
https://mvnrepository.com/artifact/commons-io/commons-io
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
image.png

2. Introduction to usage classes

[Notes on file upload]

  1. To ensure server security, uploaded files should be placed in a directory that cannot be directly accessed by the outside world, such as the WEB-INF directory.
  2. To prevent file overwriting, a unique file name must be generated for the uploaded file.
  3. To limit the maximum size of uploaded files.
  4. You can limit the type of uploaded files, and when receiving the uploaded file name, determine whether the suffix name is legal.

[Detailed explanation of classes to be used]
ServletFileUpload is responsible for processing uploaded file data and encapsulating each input item in the form into a FileItem object. The DiskFileItemFactory object is required when using the ServletFileUpload object to parse the request . Therefore, we need to construct the DiskFileItemFactory object before parsing, and set the fileItemFactory property of the ServletFileUpload object through the construction method of the ServletFileUpload object or the setFileItemFactory()== method .

FileItem class

There must be name <input type="file" name="filename">
a form in the HTML page input. If it contains a file upload input, the enctype attribute of this form must be set to multipart/form-data.
If the browser form type is multipart/form-data, if you want to obtain data on the server side, To pass the stream.


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <%--通过表单上传
      get:上传文件大小有限制
      post: 上传文件大小没有限制--%>
      <form action = "" method = "post" enctype="multipart/form-data">
        上传用户:<input type="text" name="username"><br/>
        <p><input type="file" name="file1"></p>
        <p><input type="file" name="file2"></p>
        <p><input type="submit"> |<input type="reset"></p>
      </form>
  </body>
</html>

[Introduction to common methods]

//isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormField();

//getFieldName方法用于返回表单标签name属性的值。
String getFieldName();

//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();

//getName方法用于获得文件上传字段中的文件名。
String getName();

//以流的形式返回上传文件的数据内容。
InputStream getInputStream();

//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
void delete();
ServletFileUpload 类

ServletFileUpload is responsible for processing uploaded file data and encapsulating each input item in the form into a FileItem object . Use its parseRequest(HttpServletRequest) method to encapsulate the data submitted through each HTML tag in the form into a FileItem object, and then use Returned in the form of List list. This method is simple and easy to use for uploading files.

3. Code writing

UploadServlet

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;

public class UploadServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        try {
    
    
            //判断上传的文件是普通的表单还是带文件的表单
            if (!ServletFileUpload.isMultipartContent(request)) {
    
    
                return;//如果是普通文件,我们可以直接返回
            } //如果通过了这个if,说明我们的表单是带文件上传的;

            //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件;
            String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()) {
    
    //如果目录不存在,创建这样一个目录;
                uploadFile.mkdir();
            }

            //临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
            String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
            File file = new File(tmpPath);
            if (!file.exists()) {
    
    //如果目录不存在,创建这样一个目录;
                file.mkdir();
            }

            //处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
            //但是我们都建议使用 Apache的文件上传组件来实现,common-fileupload,它需要依赖于 commons-io组件;

            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
            DiskFileItemFactory factory = getDiskFileItemFactory(file);
            //2.获取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);
            //3.处理上传的文件
            String msg = uploadParseRequest(upload, request, uploadPath);

            //servlet请求转发消息
            request.setAttribute("msg",msg);
            request.getRequestDispatcher("msg.jsp").forward(request,response);

        } catch (FileUploadException e) {
    
    
            e.printStackTrace();
        }

    }


    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
    
    
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
        factory.setSizeThreshold(1024 * 1024); //缓存区大小为1M
        factory.setRepository(file);//临时目录的保存目录,需要一个File
        return factory;
    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
    
    
        ServletFileUpload upload = new ServletFileUpload(factory);
        //监听文件上传进度;
        upload.setProgressListener(new ProgressListener() {
    
    
            @Override
            //pBytesRead:已经读取到的文件大小
            //pContentLength : 文件大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
    
    
                System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
            }
        });

        //处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //设置总共能够上传文件的大小
        //1024 = 1kb * 1024 = 1M * 10 = 10M
        upload.setSizeMax(1024 * 1024 * 10);

        return upload;
    }


    public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadPath)
    throws FileUploadException, IOException {
    
    

        String msg = "";

        //3.把前端请求解析,封装成一个FileItem对象
        List<FileItem> fileItems = upload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
    
    
            if (fileItem.isFormField()){
    
     //判断上传的文件是普通的表单还是带文件的表单
                //getFieldName指的是前端表单控件的name;
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8"); //处理乱码
                System.out.println(name+":"+value);
            }else {
    
     //判断它是上传的文件

                //=======================处理文件===============================//

                //拿到文件名字
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名:"+uploadFileName);

                if (uploadFileName.trim().equals("")||uploadFileName==null){
    
    
                    continue;
                }

                //获得上传的文件名  /images/girl/paojie.png
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
                //获得文件的后缀名
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                /*
如果文件后缀名 fileExtName 不是我们所需要的
就直接return,不处理,告诉用户文件类型不对。
*/

                System.out.println("文件信息 [件名:"+fileName+"---文件类型"+fileExtName+"]");

                //可以使用UUID(唯一识别的通用码),保证文件名唯一;
                //UUID.randomUUID(),随机生一个唯一识别的通用码;
                String uuidPath = UUID.randomUUID().toString();

                //=======================处理文件完毕===============================//

                //存到哪? uploadPath
                //文件真实存在的路径 realPath
                String realPath =   uploadPath+"\\"+uuidPath;
                //给每个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()){
    
    
                    realPathFile.mkdir();
                }

                //=======================存放地址完毕===============================//

                //获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();

                //创建一个文件输出流
                //realPath = 真实的文件夹;
                //差了一个文件; 加上输出文件的名字+"/"+uuidFileName
                FileOutputStream fos = new FileOutputStream(realPath+"\\"+fileName);

                //创建一个缓冲区
                byte[] buffer = new byte[1024*1024];

                //判断是否读取完毕
                int len = 0;
                //如果大于0说明还存在数据;
                while ((len=inputStream.read(buffer))>0){
    
    
                    fos.write(buffer,0,len);
                }

                //关闭流
                fos.close();
                inputStream.close();

                msg = "文件上传成功!";
                fileItem.delete(); //上传成功,清除临时文件
                //=======================文件传输完毕===============================//
            }
        }

        return msg;
    }
}

upload.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>文件上传</title>
    </head>
    <body>
      <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="username"><br/>
        上传文件1:<input type="file" name="file1"><br/>
        上传文件2:<input type="file" name="file2"><br/>
        <input type="submit" value="提交">
      </form>
    </body>
  </html>

msg.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>消息提示</title>
    </head>
    <body>
      ${msg}
    </body>
  </html>

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">    
  <servlet>         
    <servlet-name>upload</servlet-name>         
    <servlet-class>com.kuang.servlet.UploadFileServlet</servlet-class>     
  </servlet>     
  <servlet-mapping>         
    <servlet-name>upload</servlet-name>         
    <url-pattern>/upload.do</url-pattern>     
  </servlet-mapping> </web-app> 

Email sending and receiving

e-mail

To implement the mail function on the network, a dedicated mail server is necessary.
These mail servers are similar to post offices in real life. They are mainly responsible for receiving mails delivered by users and delivering the mails to the email recipients' email boxes.
SMTP server address: generally smtp.xxx.com , for example, the 163 mailbox is smtp.163.com , and the qq mailbox is smtp.qq.com .
To obtain an email address (E-Mail address), you need to apply on the mail server. For example, if we want to use QQ mailbox, we need to activate the mailbox function;
image.png

Transfer Protocol

SMTP protocol
for sending emails:
We usually call the server that handles user SMTP requests (email sending requests) as SMTP servers (email sending servers).
POP3 protocol
for receiving mail:
We usually call the server that handles user pop3 requests (mail receiving requests) a POP3 server (mail receiving server).
Principles of sending and receiving emails
image.png

  1. Da Kuangshen connects to the Smtp server through the SMTP protocol, and then sends an email to NetEase's mail server
  2. NetEase analysis found that it is necessary to go to QQ's mail server and forward the mail to QQ's Smtp server through the SMTP protocol.
  3. QQ stores received emails in the space of the email account [email protected]
  4. Xiaokuangshen connects to the Pop3 server through the Pop3 protocol to collect emails
  5. Retrieve emails from the space of the email account [email protected]
  6. The Pop3 server will send the retrieved email to the little mad god

[Note] It is possible that your recipient address, sender address and other information are correct, and the console prints the correct information, but you cannot receive the information in the inbox. This is because the inbox server may have rejected the email you sent (for example, it thinks your email is an advertisement). At this time, it may be found in the trash can, but may not be found. The solution is not to send duplicate email content multiple times, or try changing your inbox.

Send email using Java

Overview

We will use the code to complete the sending of the email. This is widely used in actual projects. For example, registration requires sending an email for account activation. Another example is the use of emails for task reminders in OA projects.
Sending E-mail using Java is very simple, but first you should prepare the JavaMail API and Java Activation Framework.
Get two jar packages:

  • mail.jar
  • activation.jar

JavaMail is a set of standard development packages provided by Sun Corporation (now acquired by Oracle) to facilitate Java developers to implement email sending and receiving functions in applications. It supports some commonly used email protocols, such as SMTP mentioned earlier. POP3, IMAP, and MIME, etc. When we use the JavaMail API to write emails, we do not need to consider the underlying implementation details of the email. We only need to call the corresponding API class in the JavaMail development kit.
We can try sending a simple email first to ensure that the computer can connect to the network.

  • Create a Session object that contains network connection information for the mail server.
  • Create a Message object that represents the content of the email
  • Create a Transport object, connect to the server, send a Message, and close the connection

There are mainly four core classes. When we write a program, if we remember these four core classes, it will be easy to write a Java mail processing program.
image.png

plain text email

First, import the jar package QQ mailbox into the project
image.png
to obtain the corresponding permissions.
QQ mailbox requires security verification, and we need to obtain its corresponding permissions;
QQ mailbox–>mailbox settings–>account
image.png
image.png
writing test code

import com.sun.mail.util.MailSSLSocketFactory;

import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

public class SendEmail {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
        prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码

        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);

        //使用JavaMail发送邮件的5个步骤
        //创建定义整个应用程序所需的环境信息的 Session 对象

        Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    
            public PasswordAuthentication getPasswordAuthentication() {
    
    

                //发件人邮件用户名、授权码
                return new PasswordAuthentication("[email protected]", "授权码");

            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com", "[email protected]", "授权码");
        //4、创建邮件
        //创建邮件对象
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("[email protected]"));
        //指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
        //邮件的标题
        message.setSubject("只包含文本的简单邮件");
        //邮件的文本内容
        message.setContent("你好啊!", "text/html;charset=UTF-8");
        //5、发送邮件
        ts.sendMessage(message, message.getAllRecipients());
        ts.close();
    }
}

Emails with pictures and attachments

First, let’s get to know two classes and one noun:
MIME (Multipurpose Internet Mail Extension Type)
MimeBodyPart class
javax.mail.internet.MimeBodyPart class represents a MIME message, which, like the MimeMessage class, is inherited from the Part interface.
The MimeMultipart class
javax.mail.internet.MimeMultipart is an implementation subclass of the abstract class Multipart, which is used to combine multiple MIME messages. A MimeMultipart object can contain multiple MimeBodyPart objects representing MIME messages.
image.png
Creating an email containing embedded images
In the previous example, HTML or plain text content was used alone, but sometimes we need to display some images inline in plain text, so we need to combine plain text and embedded images. Just store it separately in MimeBodyPart and then store it in a Mimemultipart object.

import com.sun.mail.util.MailSSLSocketFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;

public class SendImageEmail {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
        prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码

        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);

        //使用JavaMail发送邮件的5个步骤
        //1、创建定义整个应用程序所需的环境信息的 Session 对象
        Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    
            public PasswordAuthentication getPasswordAuthentication() {
    
    
                //发件人邮件用户名、授权码
                return new PasswordAuthentication("[email protected]", "授权码");
            }
        });

        //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
        session.setDebug(true);
        
        //2、通过session得到transport对象
        Transport ts = session.getTransport();
        //3、使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com", "[email protected]", "授权码");
        //4、创建邮件
        //创建邮件
        MimeMessage message = new MimeMessage(session);
        // 设置邮件的基本信息
        //发件人
        message.setFrom(new InternetAddress("[email protected]"));
        //收件人
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
    //邮件标题
    message.setSubject("带图片的邮件");
    // 准备邮件数据
    // 准备图片数据
    MimeBodyPart image = new MimeBodyPart();
    DataHandler dh = new DataHandler(new FileDataSource("src/resources/bz.jpg"));
    image.setDataHandler(dh);
    image.setContentID("bz.jpg");
    // 准备正文数据
    MimeBodyPart text = new MimeBodyPart();
    text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件", "text/html;charset=UTF-8");
    // 描述数据关系
    MimeMultipart mm = new MimeMultipart();
    mm.addBodyPart(text);
    mm.addBodyPart(image);
    mm.setSubType("related");
    //设置到消息中,保存修改
    message.setContent(mm);
    message.saveChanges();
    //5.发送邮件
    ts.sendMessage(message, message.getAllRecipients());
    ts.close();
    }
}

Send complex emails with pictures and attachments

import com.sun.mail.util.MailSSLSocketFactory;



 



import javax.activation.DataHandler;



import javax.activation.FileDataSource;



import javax.mail.*;



import javax.mail.internet.InternetAddress;



import javax.mail.internet.MimeBodyPart;



import javax.mail.internet.MimeMessage;



import javax.mail.internet.MimeMultipart;



import java.security.GeneralSecurityException;



import java.util.Properties;



 



public class SendFileMail {
    
    



    public static void main(String[] args) throws MessagingException, GeneralSecurityException {
    
    



 



        //创建一个配置文件保存并读取信息



        Properties properties = new Properties();



 



        //设置qq邮件服务器



        properties.setProperty("mail.host","smtp.qq.com");



        //设置发送的协议



        properties.setProperty("mail.transport.protocol","smtp");



        //设置用户是否需要验证



        properties.setProperty("mail.smtp.auth", "true");



 



 



        //=================================只有QQ存在的一个特性,需要建立一个安全的链接



        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可



        MailSSLSocketFactory sf = new MailSSLSocketFactory();



        sf.setTrustAllHosts(true);



        properties.put("mail.smtp.ssl.enable", "true");



        properties.put("mail.smtp.ssl.socketFactory", sf);



 



        //=================================准备工作完毕



 



        //1.创建一个session会话对象;



        Session session = Session.getDefaultInstance(properties, new Authenticator() {
    
    



            @Override



            protected PasswordAuthentication getPasswordAuthentication() {
    
    



                return new PasswordAuthentication("[email protected]", "授权码");



            }



        });



 



        //可以通过session开启Dubug模式,查看所有的过程



        session.setDebug(true);



 



 



        //2.获取连接对象,通过session对象获得Transport,需要捕获或者抛出异常;



        Transport tp = session.getTransport();



 



        //3.连接服务器,需要抛出异常;



        tp.connect("smtp.qq.com","[email protected]","授权码");



 



        //4.连接上之后我们需要发送邮件;



        MimeMessage mimeMessage = imageMail(session);



 



        //5.发送邮件



        tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());



 



        //6.关闭连接



        tp.close();



 



    }



 



 



    public static MimeMessage imageMail(Session session) throws MessagingException {
    
    



 



        //消息的固定信息



        MimeMessage mimeMessage = new MimeMessage(session);



 



        //邮件发送人



        mimeMessage.setFrom(new InternetAddress("[email protected]"));



        //邮件接收人,可以同时发送给很多人,我们这里只发给自己;



        mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));



        mimeMessage.setSubject("我也不知道是个什么东西就发给你了"); //邮件主题



 



 



        /*



        编写邮件内容



        1.图片



        2.附件



        3.文本



         */



 



        //图片



        MimeBodyPart body1 = new MimeBodyPart();



        body1.setDataHandler(new DataHandler(new FileDataSource("src/resources/yhbxb.png")));



        body1.setContentID("yhbxb.png"); //图片设置ID



 



        //文本



        MimeBodyPart body2 = new MimeBodyPart();



        body2.setContent("请注意,我不是广告<img src='cid:yhbxb.png'>","text/html;charset=utf-8");



 



        //附件



        MimeBodyPart body3 = new MimeBodyPart();



        body3.setDataHandler(new DataHandler(new FileDataSource("src/resources/log4j.properties")));



        body3.setFileName("log4j.properties"); //附件设置名字



 



        MimeBodyPart body4 = new MimeBodyPart();



        body4.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.txt")));



        body4.setFileName(""); //附件设置名字



 



        //拼装邮件正文内容



        MimeMultipart multipart1 = new MimeMultipart();



        multipart1.addBodyPart(body1);



        multipart1.addBodyPart(body2);



        multipart1.setSubType("related"); //1.文本和图片内嵌成功!



 



        //new MimeBodyPart().setContent(multipart1); //将拼装好的正文内容设置为主体



        MimeBodyPart contentText =  new MimeBodyPart();



        contentText.setContent(multipart1);



 



        //拼接附件



        MimeMultipart allFile =new MimeMultipart();



        allFile.addBodyPart(body3); //附件



        allFile.addBodyPart(body4); //附件



        allFile.addBodyPart(contentText);//正文



        allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed;



 



 



        //放到Message消息中



        mimeMessage.setContent(allFile);



        mimeMessage.saveChanges();//保存修改



 



 



        return mimeMessage;



 



    }



 



}

JavaWebSend Email

Many websites now provide user registration functions. Usually after successful registration, we will receive an email from the registration website. The content of the email may include information such as our registered username and password, as well as a hyperlink to activate the account. Today we will also implement such a function. After the user successfully registers, the user's registration information will be sent to the user's registered mailbox in the form of Email. To implement the email sending function, we must use JavaMail.
Code:

  1. Create a new JavaWeb project, configure tomcat, and add jar packages
    image.png
  2. Write the corresponding user entity class
package com.kuang.pojo;



 



public class User {
    
    



 



    private String username;



    private String password;



    private String email;



 



    public User() {
    
    



    }



 



    public User(String username, String password, String email) {
    
    



        this.username = username;



        this.password = password;



        this.email = email;



    }



 



    public String getUsername() {
    
    



        return username;



    }



    public void setUsername(String username) {
    
    



        this.username = username;



    }



    public String getPassword() {
    
    



        return password;



    }



    public void setPassword(String password) {
    
    



        this.password = password;



    }



    public String getEmail() {
    
    



        return email;



    }



    public void setEmail(String email) {
    
    



        this.email = email;



    }



 



    @Override



    public String toString() {
    
    



        return "User{" +



                "username='" + username + '\'' +



                ", password='" + password + '\'' +



                ", email='" + email + '\'' +



                '}';



    }



}
  1. Front-end registration page
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



<html>



<head>



    <title>注册</title>



</head>



<body>



 



<form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">



    用户名:<input type="text" name="username"><br/>



    密码:<input type="password" name="password"><br/>



    邮箱:<input type="text" name="email"><br/>



    <input type="submit" value="注册">



</form>



 



</body>



</html>
  1. Email sending tools
package com.kuang.utils;



 



import com.kuang.pojo.User;



import com.sun.mail.util.MailSSLSocketFactory;



 



import javax.mail.*;



import javax.mail.internet.InternetAddress;



import javax.mail.internet.MimeMessage;



import java.util.Properties;



 



public class Sendmail extends Thread {
    
    



 



    //用于给用户发送邮件的邮箱



    private String from = "[email protected]";



    //邮箱的用户名



    private String username = "[email protected]";



    //邮箱的密码



    private String password = "授权码";



    //发送邮件的服务器地址



    private String host = "smtp.qq.com";



 



    private User user;



    public Sendmail(User user){
    
    



        this.user = user;



    }



 



    //重写run方法的实现,在run方法中发送邮件给指定的用户



    @Override



    public void run() {
    
    



        try{
    
    



            Properties prop = new Properties();



            prop.setProperty("mail.host", host);



            prop.setProperty("mail.transport.protocol", "smtp");



            prop.setProperty("mail.smtp.auth", "true");



 



            // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可



            MailSSLSocketFactory sf = new MailSSLSocketFactory();



            sf.setTrustAllHosts(true);



            prop.put("mail.smtp.ssl.enable", "true");



            prop.put("mail.smtp.ssl.socketFactory", sf);



 



            //1、创建定义整个应用程序所需的环境信息的 Session 对象



            Session session = Session.getDefaultInstance(prop, new Authenticator() {
    
    



                public PasswordAuthentication getPasswordAuthentication() {
    
    



                    //发件人邮件用户名、授权码



                    return new PasswordAuthentication("[email protected]", "授权码");



                }



            });



 



            //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态



            session.setDebug(true);



 



            //2、通过session得到transport对象



            Transport ts = session.getTransport();



 



            //3、使用邮箱的用户名和授权码连上邮件服务器



            ts.connect(host, username, password);



 



            //4、创建邮件



            MimeMessage message = new MimeMessage(session);



            message.setFrom(new InternetAddress(from)); //发件人



            message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail())); //收件人



            message.setSubject("用户注册邮件"); //邮件的标题



 



            String info = "恭喜您注册成功,您的用户名:" + user.getUsername() + ",您的密码:" + user.getPassword() + ",请妥善保管,如有问题请联系网站客服!!";



 



            message.setContent(info, "text/html;charset=UTF-8");



            message.saveChanges();



 



            //发送邮件



            ts.sendMessage(message, message.getAllRecipients());



            ts.close();



        }catch (Exception e) {
    
    



            throw new RuntimeException(e);



        }



    }



}
  1. Write the corresponding servlet processing class
package com.kuang.servlet;



 



import com.kuang.pojo.User;



import com.kuang.utils.Sendmail;



 



import javax.servlet.ServletException;



import javax.servlet.http.HttpServlet;



import javax.servlet.http.HttpServletRequest;



import javax.servlet.http.HttpServletResponse;



import java.io.IOException;



 



public class RegisterServlet extends HttpServlet {
    
    



    @Override



    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    



        try {
    
    



            //接收用户请求,封装成对象



            String username = request.getParameter("username");



            String password = request.getParameter("password");



            String email = request.getParameter("email");



            User user = new User(username,password,email);



 



            //用户注册成功之后,给用户发送一封邮件



            //我们使用线程来专门发送邮件,防止出现耗时,和网站注册人数过多的情况;



            Sendmail send = new Sendmail(user);



            //启动线程,线程启动之后就会执行run方法来发送邮件



            send.start();



 



            //注册用户



            request.setAttribute("message", "注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!!");



            request.getRequestDispatcher("info.jsp").forward(request, response);



        } catch (Exception e) {
    
    



            e.printStackTrace();



            request.setAttribute("message", "注册失败!!");



            request.getRequestDispatcher("info.jsp").forward(request, response);



        }



    }



 



 



    @Override



    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    



        doGet(req, resp);



    }



}
  1. Configure 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">



    <servlet>



        <servlet-name>register</servlet-name>



        <servlet-class>com.kuang.servlet.RegisterServlet</servlet-class>



    </servlet>



    



    <servlet-mapping>



        <servlet-name>register</servlet-name>



        <url-pattern>/RegisterServlet.do</url-pattern>



    </servlet-mapping>



</web-app>
  1. Send success or failure feedback page
<%@ page contentType="text/html;charset=UTF-8" language="java" %>



<html>



<head>



    <title>提示信息</title>



</head>



<body>



    ${message}



</body>



</html>

Run Tomcat test!
The email was sent successfully, OK!

Guess you like

Origin blog.csdn.net/qq_53517370/article/details/128861163