JavaWeb概览

Internet上供外界访问的Web资源分为:静态web资源(如html页面)和动态web资源。静态web资源开发技术:HTML、CSS。动态web资源开发技术:JavaScript、JSP/Servlet、ASP、PHP等。在Java中,动态web资源开发技术统称为Java Web。基本框架包括使用Servlet或者Filter拦截请求,使用MVC的思想设计架构,使用约定,XMLAnnotation实现配置,运用Java面向对象的特点,面向对象实现请求和响应的流程,支持JspFreemarkerVelocity等视图。

基本概念

1.静态Web

缺点:

  • Web页面无法动态更新
    • 伪动态
    • JavaScript
    • VBScript
  • 无法与数据库交互

2.动态Web


Web服务器

1.ASP

ASP(Active Server Pages),Microsoft公司开发的服务器端脚本环境,可用来创建动态交互式网页并建立强大的web应用程序。除服务器端脚本代码外,ASP文件也可以包含文本、HTML和com组件调用。通过ASP,可以结合HTML网页、ASP指令和ActiveX组件创建动态、交互且高效的WEB服务器应用程序。同时,ASP也支持VBScriptJScript等脚本语言,默认为VBScript,而其中JScript是微软公司的ECMAScript标准的实现,并且有自己的扩展。

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
<body>
<%
response.write("My first ASP script!")
%>
</body>
</html>

2.PHP

PHP(Hypertext Preprocessor)是一种开源的通用计算机脚本语言,尤其适用于网络开发并可嵌入HTML中使用。PHP的语法借鉴吸收C语言、Java和Perl等流行计算机语言的特点,易于一般程序员学习。PHP的主要目标是允许网络开发人员快速编写动态页面,但PHP也被用于其他很多领域。

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
<body>
<?php
echo "Hello World!";
?>
</body>
</html>

3.JSP/Servlet

JSP(Jakarta Server Pages)是由Sun公司主导创建的一种动态网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。JSP文件在运行时会被其编译器转换成更原始的Servlet代码。JSP编译器可以把JSP文件编译成用Java代码写的Servlet,然后再由Java编译器来编译成能快速执行的二进制机器码,也可以直接编译成二进制码。

B/S: browser server

C/S: client server

1
2
3
4
5
6
7
8
9
10
<html>
<head>
<title>第一个 JSP 程序</title>
</head>
<body>
<%
out.println("Hello World!");
%>
</body>
</html>

1.Tomcat

Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台和Tomcat阀等。由于Tomcat本身也内含了HTTP服务器,因此也可以视作单独的Web服务器。Apache Tomcat包含了配置管理工具,也可以通过编辑XML格式的配置文件来进行配置。

2.IIS

互联网信息服务(Internet Information Services),是由微软公司提供的基于运行Microsoft Windows的互联网基本服务。IIS包括FTP/FTPS、NNTP、和HTTP/HTTPS、SMTP等服务。IIS可设置的内容包括:虚拟目录及访问权限、默认文件名称、以及是否允许浏览目录。


Tomcat

Apache Tomcat

1.Tomcat目录

目录及文件 说明
bin 用于存放Tomcat的启动、停止等批处理脚本和Shell脚本
bin/startup.bat 用于Windows下启动Tomcat
bin/startup.sh 用于Linux下启动Tomcat
bin/shutdown.bat 用于Windows下停止Tomcat
bin/shutdown.sh 用于Linux下停止Tomcat
conf 用于存放Tomcat的相关配置文件
conf/Catalina 用于存储针对每个虚拟机的Context配置
conf/context.xml 用于定义所有Web应用均需要加载的Context配置,如果Web应用指定了context.xml,该文件配置将被覆盖
conf/catalina.properties Tomcat环境变量配置
conf/catalina.policy 当Tomcat在安全模式下运行时,此文件为默认的安全策略配置
conf/logging.properties Tomcat日志配置文件,可修改Tomcat日志级别以及日志路径等
conf/server.xml Tomcat服务器核心配置文件,用于配置Tomcat的链接器、监听端口、处理请求的虚拟主机等。
conf/tomcat-users.xml 用于定义Tomcat默认用户及角色映射信息,Tomcat的Manager模块即用该文件定义的用户进行安全认证
conf/web.xml Tomcat所有应用默认的部署描述文件,主要定义了基础Servlet和MIME映射
lib Tomcat服务器依赖库目录,包含Tomcat服务器运行环境依赖Jar包
logs Tomcat默认的日志存放目录
webapps Tomcat默认的Web应用部署目录
work Web应用JSP代码生成和编译临时目录

2.测试启动

Apache Tomcat/10.0.12

http://localhost:8080/

3.默认端口

  • Tomcat:8080
  • Mysql:3306
  • http:80
  • https:443

4.IDEA配置Tomcat

IDEA:Ultimate版本(收费,支持Web开发:Tomcat)\Community版(开源免费)

1.Run->Run/Debug Configurations->Tomcat(Local)->HTTP port:8080

2.Edit Configurations -> Tomcat ->Deployment->Add(需要运行项目war)

3.Edit Configurations -> Tomcat ->Deployment->Application context(项目初始路径名)

5.Application Server not specified

关联本地的tomcat:Application sever选择本地Tomcat安装路径

6.No artifacts marked for deployment

Fix->war

7.IDEA tomcat 热部署(修改jsp文件)

1.下方Services->Deploy All

2.修改Tomcat配置On’Update’action\On frame deactivation -> Update classes and resources

8.IDEA下方Services中Tomcat localhost Log可查看Tomcat报错信息。


关于Tomcat10 Maven依赖问题

From the Tomcat 10.0.0-M1 release announcement:

Users of Tomcat 10 onwards should be aware that, as a result of the move from Java EE to Jakarta EE as part of the transfer of Java EE to the Eclipse Foundation, the primary package for all implemented APIs has changed from javax.* to jakarta.*. This will almost certainly require code changes to enable applications to migrate from Tomcat 9 and earlier to Tomcat 10 and later.

1
2
3
4
5
6
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>

That is never going to work on Tomact 10. You can’t use Java EE 8 libraries with a Jakarta EE 9 server.

1.如果你无法处理这之间的关系,推荐仍然使用Tomcat9(Spring仍然无法兼容Tomcat10).

2.2015年,Tomcat 8开始支持 JavaEE8,javax 项目由 Sun 公司转给 glassfish 维护运营,相应地被拆分为jakarta多个项目,但这并不能说明仅仅将javax替换成jakarta即可。


HTTP

1.协议版本

  • HTTP/0.9

HTTP/0.9只支持GET方法,不支持多媒体内容的MIME类型、各种 HTTP首部,或者版本号

  • HTTP/1.0

1.0是第一个得到广泛使用的HTTP版本。HTTP/1.0添加了版本号、各种 HTTP首部、一些额外的方法,以及对多媒体对象的处理。HTTP/1.0使得包含生动图片的Web页面和交互式表格成为可能。

  • HTTP/1.0+

HTTP中添加各种新特性,包括持久的keep-alive 连接、虚拟主机支持,以及代理连接支持都被加入到HTTP之中,并成为非官方的事实标准。

  • HTTP/1.1

HTTP/1.1重点是校正HTTP设计中的结构性缺陷,明确语义,引入重要的性能优化措施,并删除一些不好的特性,包含了对20世纪 90年代末正在发展中的更复杂的Web应用程序和部署方式的支持。

  • HTTP/2.0(HTTP-NG)

HTTP/2支持请求与响应的多路复用减少延迟,压缩HTTP首部字段降低协议开销,增加对请求优先级和服务器端推送的支持。


Maven

Apache Maven,是一个软件项目管理及自动构建工具,由Apache软件基金会所提供。基于项目对象模型(POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。Maven也可被用于构建和管理各种项目,例如C#,Ruby,Scala和其他语言编写的项目。Maven曾是Jakarta项目的子项目,现为由Apache软件基金会主持的独立Apache项目。

Maven不仅是构建工具,还是一个依赖管理工具(第三方的开源类库,通过一组坐标Maven能够找到任何一个Java类库,如jar文件)和项目信息管理工具。它提供了中央仓库,可以自动下载构件。

1.下载安装

Maven

2.配置环境变量

1
2
3
4
5
#新建系统变量
M2_HOME:<maven安装路径>\bin
MAVEN_HOME:<maven安装路径>
#新建系统环境变量Path
%MAVEN_HOME%\bin
1
mvn --version

3.配置镜像

AliYun

1
2
3
4
5
6
7
<!--conf\settings.xml-->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>

4.配置本地仓库(localRepository)

1
2
<!--conf\settings.xml-->
<localRepository>D:\Applications\apache-maven-3.8.3\repo</localRepository>

5.IDEA/Maven

1.New Project->Maven->Create from archetype(maven-archetype-webapp)->next->Artifact Coordinates(Groupld/Artifactld)->Maven home path/User settings file/Local resposity-> BUILD SUCCESS

2.New Project->Maven->右键项目名->Add Frameworks Support->Java EE(Web Application)

  • New->Maven->Next->rtifact Coordinates(Groupld/Artifactld)->Finish
  • File->Build,Execution,Deployment->Build Tools->Repositories
  • Build->Fresh图标

3.新建Empty Project->(File->Project Structure )Project SDK(1.8)/Java Project language level(SDK default)->File->New Module->Java (Web Application/Maven webapps)

  • 如无Web Application可新建一个空Module之后右击项目Add Framework Support选择Web Application即可
  • 可在本项目中File->New Module新建另一个项目

4.当前工程右击new Module新建子工程即可继承父pom.xml导入的依赖。

通常无法找到对应库或者依赖需要在File->Project Settings->Artifacts->WEB-INF文件夹下新建lib文件夹->点击+号添加Library文件即可

1.IDEA创建maven项目后无.iml文件

在IDEA terminal:mvn idea:module

2.webapp版本与tomcat一致(webapp/WEB-INF/web.xml)

3.依赖爆红:

  • File->Settings->Build,Execution,Deloyment->Build Tools->Maven(Maven home path/User settings file/Local repository)是否为本地安装目录->Invalidate Caches
  • 在Maven Repository中下载Jar包至Maven指定本地仓库
  • 在Maven中刷新即可

4.修改maven的编码格式为utf-8:

  • mvn -v:默认编码为GBK

  • 设置环境变量:

    • 变量名 MAVEN_OPTS

    • 变量值 -Xms256m -Xmx512m -Dfile.encoding=UTF-8

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
</web-app>

6.POM(Project Object Model项目对象模型

Maven项目的核心是pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?xml version="1.0" encoding="UTF-8"?> <!--该xml文档的版
本和编码方式-->

<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"><!--project是所有pom.xml的根元素,声明了一些POM相关的命名空间及xsd元素-->
<modelVersion>4.0.0</modelVersion> <!--当前POM模型的版本-->

<groupId>com.noob</groupId> <!--定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联-->
<artifactId>JavaWeb</artifactId> <!--定义了当前Maven项目在组中唯一的ID-->
<version>1.0-SNAPSHOT</version> <!--version指定了该项目当前的版本--> <!--含groupId、artifactId和version的三行。这三个元素定义了一个项目基本的坐标,在Maven的世界,任何的jar、pom或者war都是以基于这些基本的坐标进行区分的-->
<packaging>war</packaging> <!--打包方式 jar:Java war:JavaWeb-->

<name>JavaWeb Maven Webapp</name> <!--声明一个对于用户更为友好的项目名称-->
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<!--项目配置-->
<properties>
<!--项目的默认构建编码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<!--项目依赖-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<finalName>JavaWeb</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

7.Maven Repository


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* HelloServlet.java*/
package com.noob;

import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
public class HelloServlet extends HttpServlet {


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
//响应类型
response.setContentType("text/html");
//h
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>HelloTomcat!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>HelloTomcat!</h1>");
out.println("</body>");
out.println("</html>");
}

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

1
2
3
4
5
6
7
8
9
10
11
<!--header.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p>Tomcat Servlet Maven</p>
</body>
</html>
1
2
3
4
5
6
7
8
<!--pom.xml-->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
<!--Webapp/WEB-INF/web.xml-->
<!--注册servlet-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.noob.HelloServlet</servlet-class>
</servlet>
<!--映射-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<!--路径-->
<url-pattern>/test</url-pattern>
</servlet-mapping>

默认index.jsp生成页面

/header.html header.html

/test HelloServlet.java生成页面

注意:访问HelloServlet.java生成页面报500时,下载tomcat9在IDEA中重新Edit Configurations一个Tomcat9的配置运行该项目即可(或者使用Tomcat10的配置依赖)。


Servlet

1.Servlet(Java Servlet)是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类。

2.Servlet接口-实现->GenericServlet类-继承->HttpServlet类

1.配置依赖(Tomcat9 10使用的依赖存在区别,注意区分)

Tomcat10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--pom.xml-->
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp/jakarta.servlet.jsp-api -->
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>

Tomcat9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</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>
<scope>provided</scope>
</dependency>

1.依赖变红一般检查idea的maven配置,查看maven软件、配置文件和本地仓库的配置(Settings->Build,Execution,Deployment->Maven)

2.下载的依赖都在定义maven的本地仓库中查看。

3.Maven Project右键Module新建子工程。

  • 父项目
1
2
3
<modules>
<module>Servlet1</module>
</modules>
  • 子项目
1
2
3
4
5
6
7
8
9
10
<parent>
<groupId>org.example</groupId> <!--父项目组名-->
<artifactId>MavenTomcatProject</artifactId><!--父项目名-->
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>Servlet1</artifactId>
<packaging>war</packaging>
<!--File -> Invalidate caches刷新-->

无父节点<parent></parent>手动添加即可。


1
2
3
4
5
6
7
8
9
10
11
public interface Servlet {
void init(ServletConfig var1) throws ServletException;

ServletConfig getServletConfig();

void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

String getServletInfo();

void destroy();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//HelloServlet.java
package com.noob;

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

import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet Had Run");
PrintWriter writer = resp.getWriter();
writer.print("Hello Servlet!");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!--Web.xml-->
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.noob.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

</web-app>


Mapping

1.一个Servlet指定一个映射路径。

1
2
3
4
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

2.一个Servlet指定多个映射路径。

1
2
3
4
5
6
7
8
9
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>

3.一个Servlet可以指定通用映射路径。

1
2
3
4
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>

4.默认请求路径

1
2
3
4
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

5.指定前缀或后缀(*前不能加项目映射路径)

1
2
3
4
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.noob;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

public class ErrorServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");

PrintWriter writer = resp.getWriter();

writer.print("<h1>404 Not Found.</h1>");

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
1
2
3
4
5
6
7
8
9
10
<!-- 明确指定的映射路径优先级最高-->
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.noob.ErrorServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

ServletContext

web容器在启动时会为每个web程序创建一个对应的ServletContext对象,代表当前的web应用。

1.共享数据

访问hello页面为username赋值,之后访问get页面即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.noob.Servlet;

import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Running");
/*
this.getInitParameter() 初始化参数
this.getServletConfig() Servlet配置
this.getServletContext() Servlet上下文
*/
ServletContext context = this.getServletContext();
String username = "Servlet";
context.setAttribute("username",username); //将数据保存在ServletContext中

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.noob.Servlet;

import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

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

String username =(String)context.getAttribute("username");
resp.setHeader("Content-Type", "text/html;charset=UTF-8");
resp.getWriter().print("Name:"+username);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.noob.Servlet.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>getUsername</servlet-name>
<servlet-class>com.noob.Servlet.GetServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>getUsername</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>

</web-app>

2.获取初始化参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.noob.Servlet;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url=context.getInitParameter("url");
resp.getWriter().print(url);

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>

<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>com.noob.Servlet.ServletDemo</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>

3.请求转发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.noob.Servlet;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class ServletDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("Runed Demo02");
/*
RequestDispatcher requestdspatcher = context.getRequestDispatcher("/hello");
requestdspatcher.forward(req,resp);
*/
context.getRequestDispatcher("/demo").forward(req,resp);

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>Demo2</servlet-name>
<servlet-class>com.noob.Servlet.ServletDemo02</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Demo2</servlet-name>
<url-pattern>/Demo2</url-pattern>
</servlet-mapping>

4.读取资源文件

Properties:properties都被打包到同一路径:classes,即classpath

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.noob.Servlet;

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

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ServletDemo3 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 usr = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(usr+":"+pwd);

}

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

}
}
1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>Demo3</servlet-name>
<servlet-class>com.noob.Servlet.ServletDemo3</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Demo3</servlet-name>
<url-pattern>/Demo3</url-pattern>
</servlet-mapping>
1
2
3
#db.properties
username=root
password=123456

HttpServletResponse

web服务器在接受到客户端的HTTP请求时,针对该请求会分别创建一个代表请求的HttpServletRequest对象(可获取客户端的请求参数)以及一个代表响应的HttpServletResponse对象(可发送给客户端的响应信息)。

1.向浏览器发送数据

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

2.向浏览器发送响应头

1
2
3
4
5
6
7
8
9
10
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, 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 var1, int var2);

3.响应状态码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

1.应用

  • 向浏览器输出信息
  • 下载文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.noob;

import jakarta.servlet.Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*获取下载路径*/
String realPath = "C:\\Users\\29921\\Desktop\\MavenTomcatProject\\Response\\src\\main\\resources\\images.png";
System.out.println("下载文件路径:"+realPath);
/*文件名*/
String filename = realPath.substring(realPath.lastIndexOf("\\")+1);
/*浏览器支持 下载文件的HTTP响应头 中文文件 URLEncoder.encode(filename,"UTF-8")*/
resp.setHeader("Content-Disposition","attachment;filename="+filename);
/*获取下载文件的输入流*/
FileInputStream in = new FileInputStream(realPath);
/*创建缓冲区*/
int len = 0;
byte[] buffer = new byte[1024];
/*获取OutputStream对象*/
ServletOutputStream out = resp.getOutputStream();
/*将FileOutputStream流写入buffer缓冲区,使用OutputStream将缓冲区数据输出到客户端*/
while((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>filedown</servlet-name>
<servlet-class>com.noob.FileServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>filedown</servlet-name>
<url-pattern>/down</url-pattern>
</servlet-mapping>
  • 验证码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.noob;

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

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/* 浏览器3秒自动刷新 */
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,29);
/* 给图片写数据 */
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);

resp.setContentType("image/jpeg");
/* 浏览器缓存 */
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();
String num = random.nextInt(9999999)+"";
StringBuffer sb = new StringBuffer();
/* 确保7位数字 */
for(int i=0;i<7-num.length();i++){
sb.append("0");
}
num = sb.toString()+num;
return num;
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>com.noob.ImageServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/image</url-pattern>
</servlet-mapping>
  • 重定向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.noob;

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

import java.io.IOException;

public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
resp.setHeader("Location","/Response/image");
resp.setStatus(302);
*/
resp.sendRedirect("/Response/image");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.noob;

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

import java.io.IOException;

public class RequestDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String usr = req.getParameter("username");
String pwd = req.getParameter("password");
System.out.println(usr+":"+pwd);
/* Response为tomcat配置的初始路径/服务器根目录/webapp名 */
resp.sendRedirect("/Response/success.jsp");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%--
index.jsp
--%>
<html>
<body>
<h2>Hello World!</h2>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%--${pageContext.requset.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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%--
success.jsp
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>
Success
</h1>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<servlet>
<servlet-name>RedirectServlet</servlet-name>
<servlet-class>com.noob.RedirectServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/red</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>RequestDemo</servlet-name>
<servlet-class>com.noob.RequestDemo</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>RequestDemo</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>

HttpServletRequest

HttpServletRequest代表客户端的请求,当用户通过HTTP请求访问服务器时,HTTP请求的所有信息会被封装到HttpServletRequest。

1.获取前端传递的数据

1
2
String getParameter(String var1);
String[] getParameterValues(String var1);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.noob.servlet;


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

import java.io.IOException;
import java.util.Arrays;

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

String usr = req.getParameter("username");
String pwd = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobby");
System.out.println(usr);
System.out.println(pwd);
System.out.println(Arrays.toString(hobbys));

/* 通过请求转发 */
req.getRequestDispatcher("/success.jsp").forward(req,resp);

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.noob.servlet.LoginServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<%--
index.jsp
--%>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>
登录
</h1>
<div style="text-align: center">
<form action="${pageContext.request.contextPath}/login" method="post"> <%-- post提交表单 --%>
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
爱好:
<input type="checkbox" name="hobby" value="Film">Film
<input type="checkbox" name="hobby" value="Tea">Tea
<input type="checkbox" name="hobby" value="Smoke">Smoke
<input type="checkbox" name="hobby" value="Code">Code
<input type="submit">
</form>
</div>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%--
success.jsp
--%>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>
Success
</h1>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- pom.xml -->
<?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>
<parent>
<groupId>org.example</groupId>
<artifactId>MavenTomcatProject</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>Request</artifactId>
<packaging>war</packaging>

</project>

Cookie

Cookie(Cookies),类型为"小型文本文件",指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。Cookie保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie。内存 Cookie 由浏览器维护,保存在内存中,浏览器关闭即消失,存在时间短暂。硬盘Cookie保存在硬盘里,有过期时间,除非用户手动清理或到了过期时间,硬盘Cookie不会清除,存在时间较长。所以,按存在时间,可分为非持久Cookie和持久Cookie。因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。服务器可以设置或读取Cookie中包含的信息,借此维护用户跟服务器会话中的状态。

1.Google Chrome C:\Users%USERNAME%\AppData\Local\Google\Chrome\UserData\Default\

Microsoft Edge C:\Users\29921\AppData\Local\MicrosoftEdge

2.一个Cooike只能保存一个信息,一个Web站点可向浏览器发送多个Cookie,最多存放20个Cookie,Cookie大小限制为4kb。

3.Cookie删除

  • 不设置有效期,关闭浏览器,Cookie失效
  • 设置有效期为0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.noob.Cookie;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Date;

public class CookieDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*中文乱码*/
resp.setHeader("Content-Type", "text/html; charset=UTF-8");

PrintWriter out = resp.getWriter();

Cookie[] cookies = req.getCookies();
/*
初始时cookies长度并不为0,而是有一个key为JSESSIONID的cookie
System.out.println(cookies.length);
System.out.println(cookies[0].getName());
*/

if(cookies.length!=1){
out.write("You Had Visited This Website:");


for(int i=0;i<cookies.length;i++){
Cookie cookie = cookies[i];
if(cookie.getName().equals("lastLoginTime")){ /*获得cooike中的key以及之后的value*/
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else{
out.print("First Visit This Website");
}
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");

/*设置cookie有效期为1天*/
/*
cookie.setMaxAge(24*60*60);
*/
resp.addCookie(cookie);


}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.noob.Cookie;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class CookieDemo2 extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*删除该Cookie*/
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
cookie.setMaxAge(0);
resp.addCookie(cookie);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.noob.Cookie;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;

public class CookieDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Content-Type", "text/html; charset=UTF-8");

PrintWriter out = resp.getWriter();

Cookie[] cookies = req.getCookies();

if(cookies.length!=1){
out.write("You Had Visited This Website:");


for(int i=0;i<cookies.length;i++){
Cookie cookie = cookies[i];
if(cookie.getName().equals("name")){ /*获得cooike中的key以及之后的value*/
/* 解码 */
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));
}
}
}else{
out.print("First Visit This Website");
}
/* 编码 */
Cookie cookie = new Cookie("name", URLEncoder.encode("小曲奇","UTF-8"));
resp.addCookie(cookie);
}

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

Session

1.会话(session)是一种持久网络协议,在用户(或用户代理)端和服务器端之间创建关联,从而起到交换数据包的作用机制,session在网络协议(如telnet或FTP)中是非常重要的部分。在不包含会话层(如UDP)或者是无法长时间驻留会话层(如HTTP)的传输协议中,会话的维持需要依靠在传输数据中的高级别程序。例如,在浏览器和远程主机之间的HTTP传输中,HTTP cookie就会被用来包含一些相关的信息,例如session ID,参数和权限信息等。

2.Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个Session对象。当会话过期或被放弃后,服务器将终止该会话。

Cookie和Session不同点

1.作用范围:Cookie 保存在客户端(浏览器),Session保存在服务器端。

2.存取方式:Cookie 只能保存ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说UserId 等。

3.有效期不同,Cookie可设置为长时间保持,比如我们经常使用的默认登录功能,Session一般失效时间较短,客户端关闭或者Session超时都会失效。

4.隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对Cookie 要好一些。

5.存储大小不同,单个Cookie保存的数据不能超过 4K,Session可存储数据远高于Cookie。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.noob.Cookie;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;

public class SessionDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");

HttpSession session = req.getSession();

/* session.setAttribute("name","会话"); */
session.setAttribute("name",new Person("会话",14));
String sessionId =session.getId();
/* 判断session是不是新创建 */
if(session.isNew()){
resp.getWriter().write("session创捷成功,ID:"+sessionId);
}else{
resp.getWriter().write("session已创建,ID为"+sessionId);
}

/*
session创建
jsessionid就是用来判断当前用户对应于哪个fsession
Cookie cookie = new Cookie("JSESSIONID",sessionId);
resp.addCookie(cookie);
*/

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.noob.Cookie;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;

public class SessionDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");

HttpSession session = req.getSession();
/*
String name = (String) session.getAttribute("name");
System.out.println(name);
*/
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.noob.Cookie;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;

public class SessionDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
/*手动注销session*/
session.invalidate();
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.noob.Cookie;

public class Person {
private String name;
private int age;

public Person(String name,int age){
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Person{"+
"name='"+name+'\''+
",age="+age+
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<servlet>
<servlet-name>cookie</servlet-name>
<servlet-class>com.noob.Cookie.CookieDemo</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>cookie</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>demo2</servlet-name>
<servlet-class>com.noob.Cookie.CookieDemo2</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>demo2</servlet-name>
<url-pattern>/demo2</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>demo3</servlet-name>
<servlet-class>com.noob.Cookie.CookieDemo3</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>demo3</servlet-name>
<url-pattern>/demo3</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>demo4</servlet-name>
<servlet-class>com.noob.Cookie.SessionDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo4</servlet-name>
<url-pattern>/demo4</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>demo5</servlet-name>
<servlet-class>com.noob.Cookie.SessionDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo5</servlet-name>
<url-pattern>/demo5</url-pattern>
</servlet-mapping>


<servlet>
<servlet-name>demo6</servlet-name>
<servlet-class>com.noob.Cookie.SessionDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo6</servlet-name>
<url-pattern>/demo6</url-pattern>
</servlet-mapping>

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

JSP

JSP与PHP、ASP、ASP.NET等语言类似,运行在服务端的语言,由 Sun Microsystems公司倡导和许多公司参与共同创建的一种使软件开发者可以响应客户端请求,而动态生成 HTML、XML 或其他格式文档的Web网页的技术标准。JSP技术是以Java语言作为脚本语言的,JSP网页为整个服务器端的Java库单元提供了一个接口来服务于HTTP的应用程序。JSP文件后缀名为*.jsp

原理

JSP最终会被转换为一个Java类编译为class文件被用户访问(本质是一个Servlet)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.apache.jasper.runtime;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import javax.servlet.jsp.JspFactory;
import org.apache.commons.logging.LogFactory;
import org.apache.jasper.compiler.Localizer;

public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
protected HttpJspBase() {
}

public final void init(ServletConfig config) throws ServletException {
super.init(config);
this.jspInit();
this._jspInit();
}

public String getServletInfo() {
return Localizer.getMessage("jsp.engine.info");
}

public final void destroy() {
this.jspDestroy();
this._jspDestroy();
}

public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this._jspService(request, response);
}

public void jspInit() {
}

public void _jspInit() {
}

public void jspDestroy() {
}

protected void _jspDestroy() {
}

public abstract void _jspService(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException;

static {
if (JspFactory.getDefaultFactory() == null) {
JspFactoryImpl factory = new JspFactoryImpl();
if (System.getSecurityManager() != null) {
String basePackage = "org.apache.jasper.";

try {
factory.getClass().getClassLoader().loadClass(basePackage + "runtime.JspFactoryImpl$PrivilegedGetPageContext");
factory.getClass().getClassLoader().loadClass(basePackage + "runtime.JspFactoryImpl$PrivilegedReleasePageContext");
factory.getClass().getClassLoader().loadClass(basePackage + "runtime.JspRuntimeLibrary");
factory.getClass().getClassLoader().loadClass(basePackage + "runtime.JspRuntimeLibrary$PrivilegedIntrospectHelper");
factory.getClass().getClassLoader().loadClass(basePackage + "runtime.ServletResponseWrapperInclude");
factory.getClass().getClassLoader().loadClass(basePackage + "servlet.JspServletWrapper");
} catch (ClassNotFoundException var3) {
LogFactory.getLog(HttpJspBase.class).error("Jasper JspRuntimeContext preload of class failed: " + var3.getMessage(), var3);
}
}

JspFactory.setDefaultFactory(factory);
}

}
}

1.index.jsp->index_jsp.java

C:\Users\yourUserName\AppData\Local\JetBrains\IntelliJIdea2021.2\tomcat

example.jsp->example_jsp.java

1
2
3
4
5
6
7
8
<!--import org.apache.jasper.runtime.HttpJspBase; -->

<!-- https://mvnrepository.com/artifact/tomcat/jasper-runtime -->
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-runtime</artifactId>
<version>5.5.23</version>
</dependency>
1
2
3
4
5
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/10.0.12
* Generated at: 2021-10-26 06:18:32 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {

private static final jakarta.servlet.jsp.JspFactory _jspxFactory =
jakarta.servlet.jsp.JspFactory.getDefaultFactory();

private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

private static final java.util.Set<java.lang.String> _jspx_imports_packages;

private static final java.util.Set<java.lang.String> _jspx_imports_classes;

static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("jakarta.servlet");
_jspx_imports_packages.add("jakarta.servlet.http");
_jspx_imports_packages.add("jakarta.servlet.jsp");
_jspx_imports_classes = null;
}

private volatile jakarta.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}

public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}

public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}

public jakarta.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}

public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
/* 初始化 */
public void _jspInit() {
}
/* 销毁 */
public void _jspDestroy() {
}
/* JSPService */
public void _jspService(final jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response)
throws java.io.IOException, jakarta.servlet.ServletException {

if (!jakarta.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
final java.lang.String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET, POST or HEAD. Jasper also permits OPTIONS");
return;
}
}
/* 内置对象 */
final jakarta.servlet.jsp.PageContext pageContext; /* 页面上下文 */
jakarta.servlet.http.HttpSession session = null; /* session */
final jakarta.servlet.ServletContext application; /* applicationContext */
final jakarta.servlet.ServletConfig config; /* config */
jakarta.servlet.jsp.JspWriter out = null; /* out */
final java.lang.Object page = this; /* 当前page */
jakarta.servlet.jsp.JspWriter _jspx_out = null; /* 请求 */
jakarta.servlet.jsp.PageContext _jspx_page_context = null; /* 响应 */


try {

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;

out.write("<html>\n");
out.write("<body>\n");
out.write("<h2>Hello World!</h2>\n");
out.write("</body>\n");
out.write("</html>\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof jakarta.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}

1
2
3
4
5
6
7
8
9
<html>
<body>
<h2>Hello World!</h2>
<%
String name = "Hello JSP";
%>
name:<%=name%>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* Code */  
try {
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;

out.write("<html>\n");
out.write("<body>\n");
out.write("<h2>Hello World!</h2>\n");

String name = "Hello JSP";

out.write("\n");
out.write("name:");
out.print(name);
out.write("\n");
out.write("</body>\n");
out.write("</html>\n");
} /* Code */

基础语法

1.脚本程序

可以包含任意量的Java语句、变量、方法或表达式:

1
<% 代码片段 %>

等价的XML语句:

1
2
3
<jsp:scriptlet>
代码片段
</jsp:scriptlet>

2.JSP表达式

1.一个JSP表达式中包含的脚本语言表达式,先被转化成String,然后插入到表达式出现的地方。

2.由于表达式的值会被转化成String,所以可以在一个文本行中使用表达式而不用去管它是否是HTML标签。

3.表达式元素中可以包含任何符合Java语言规范的表达式,但是不能使用分号来结束表达式。

1
<%= 表达式 %>

等价的XML语句:

1
2
3
<jsp:expression>
表达式
</jsp:expression>

3.JSP声明

一个声明语句可以声明一个或多个变量、方法,供后面的Java代码使用(转换到JSP生成的Java类中,而非JSP生成的Java类中的_jspService方法)。在JSP文件中,您必须先声明这些变量和方法然后才能使用它们。

1
<%! declaration; [ declaration; ]+ ... %>

或者,您也可以编写与其等价的XML语句,就像下面这样:

1
2
3
<jsp:declaration>
代码片段
</jsp:declaration>

4.JSP注释

JSP注释主要有两个作用:为代码作注释以及将某段代码注释掉。

语法 描述
<%– 注释 --%> JSP注释,注释内容不会被发送至浏览器也不会被编译
<!– 注释 --> HTML注释,通过浏览器查看网页源代码时可看到注释内容

5.JSP指令

JSP指令用来设置与整个JSP页面相关的属性。

1
<%@ directive attribute="value" %>
指令 描述
<%@ page … %> 定义页面的依赖属性,比如脚本语言、error页面、缓存需求等等
<%@ include … %> 包含其他文件
<%@ taglib … %> 引入标签库的定义,可以是自定义标签

  • web/index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>

<%--JSP表达式--%>
<%= new java.util.Date()%>
<hr>
<%--jsp脚本片段--%>
<%
int sum = 0;
for(int i=0;i<=100;i++){
sum+=i;
}
out.print("<h1>Sum="+sum+"</h1>");
%>

<%
int x = 10;
out.print(x);
%>
<p>JSP文档</p>
<%
int y=2001;
out.print(y);
%>
<%--在代码中嵌入HTML元素--%>
<%
for(int i=0; i<5;i++){
%>
<h1>Hello JSP <h1>
<%}%>
<hr>

<%-- JSP声明 --%>
<%!
static {
System.out.println("Loading Service");
}
private int globalVar=0;

public void test(){
System.out.println("test method");
}
%>

</body>
</html>
  • web/hello.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.*" %>
<%--配置错误页面--%>
<%--
<%@ page errorPage="error/error.jsp" %>
--%>

<%-- 显式声明这是一个错误页面 --%>
<%--
<%@ page isErrorPage="true" %>
<%@ page pageEncoding="UTF-8"%>
--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<%= new Date() %>
<%
int x = 1/0;
%>
</body>
</html>
  • web/test.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.*" %>
<%--配置错误页面--%>
<%--
<%@ page errorPage="error/error.jsp" %>
--%>

<%-- 显式声明这是一个错误页面 --%>
<%--
<%@ page isErrorPage="true" %>
<%@ page pageEncoding="UTF-8"%>
--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<%= new Date() %>
<%
int x = 1/0;
%>
</body>
</html>
  • web/error/404.jsp
1
2
3
4
5
6
7
8
9
10
11
12
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>404 Not Found</h1>
<%--${pageContext.request.contextPath}/img/500.jpg--%>
<%-- tomcat启动项目名(webapp[webapp生成模板]/web[添加框架] 根路径 web文件夹war打包) /JspLearn_war_exploded/img/404.png--%>
<img src="./img/404.png" alt="404">
</body>
</html>
  • web/error/error.jsp
1
2
3
4
5
6
7
8
9
10
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Some errors have occurred</h1>
<img src="https://zerostione.github.io/ImageUp//Image/Blog/JavaWeb/p15.png" alt="500"/>
</body>
</html>
  • web/common/footer.jsp
1
2
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>This is Footer</h1>
  • web/common/header.jsp
1
2
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>This is Header</h1>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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">
<error-page>
<error-code>500</error-code>
<location>/error/error.jsp</location>
</error-page>

<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
</web-app>

内置对象与作用域

JSP支持九个自动定义的变量(隐含对象)

对象 描述
request HttpServletRequest类的实例
response HttpServletResponse类的实例
out PrintWriter类的实例,用于把结果输出至网页上
session HttpSession类的实例
application ServletContext类的实例,与应用上下文有关
config ServletConfig类的实例
pageContext PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问
page 类似于Java类中的this关键字
exception exception 类的对象,代表发生错误的 JSP 页面中对应的异常对象

1.JSP中的四种作用域包括page、request、session和application。

2.page代表与一个页面相关的对象和属性。request代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域 session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>

<%-- 内置对象 --%>
<%
/*page->request->session->application*/
pageContext.setAttribute("name1","JSP1");
request.setAttribute("name2","JSP2");
session.setAttribute("name3","JSP3");
application.setAttribute("name4","JSP4");
%>
<%

String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
/*pageContext.forward("/pageContextDemo2.jsp");*/
%>

<%--使用EL表达式输出 ${} --%>
<h1>取出的值为:</h1>
<h2>${name1}</h2>
<h2>${name2}</h2>
<h2>${name3}</h2>
<h2>${name4}</h2>
</body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<%--pageContextDemo2.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%

String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
%>
<%--使用EL表达式输出 ${} --%>
<h1>取出的值为:</h1>
<h2>${name1}</h2>
<h2>${name2}</h2>
<h2>${name3}</h2>
<h2>${name4}</h2>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
pageContext.forward("/index.jsp");
%>
</body>
</html>

1.HttpServletRequest类

request对象是javax.servlet.http.HttpServletRequest类的实例。每当客户端请求一个页面时,JSP引擎就会产生一个新的对象来代表这个请求。

request对象提供了一系列方法来获取HTTP信息头,包括表单数据,cookies,HTTP方法等等。

常用的获取HTTP信息头的方法:

  • String getContextPath():返回request URI中指明的上下文路径

  • String getParameter(String name):返回此request中name指定的参数,若不存在则返回null

  • Cookie[] getCookies():返回客户端所有的Cookie的数组

  • Object getAttribute(String name):返回名称为name的属性值,如果不存在则返回null

2.HttpServletResponse类

response 对象是 javax.servlet.http.HttpServletResponse 类的一个实例。就像服务器会创建request对象一样,它也会创建一个客户端响应。

response对象定义了处理创建HTTP信息头的接口。通过使用这个对象,开发者们可以添加新的cookie或时间戳,还有HTTP状态码等等。

常用的用来设置HTTP响应头的方法:

  • void addCookie(Cookie cookie):添加指定的cookie至响应中
  • void sendRedirect(String location):使用指定的URL向客户端发送一个临时的间接响应
  • void setContentType(String type):设置响应的内容的类型,如果响应还未被提交的话

JSTL EL

1.JSP标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- http://localhost:8080/jsptag.jsp?name=JSTL&&age=12--%>
<%-- 不要在forward中写注释,会导致500错误 --%>
<jsp:forward page="/jsptag2.jsp">

<jsp:param name="name" value="JSTL"></jsp:param>
<jsp:param name="age" value="2001"></jsp:param>
</jsp:forward>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>test</h1>
<%-- 取出参数 --%>
名字:<%=request.getParameter("name")%>
年龄:<%=request.getParameter("age")%>
</body>
</html>

2.JSP 标准标签库(JSTL)

JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。

1.核心标签

2.格式化标签

3.SQL标签

4.XML标签

5.JSTL函数

1
2
3
4
5
6
7
8
9
10
11
12
<!-- JSTl表达式依赖 -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

核心标签是最常用的JSTL标签。引用核心标签库:

1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Tomcat导入爆红未导入taglibs-standard-impl包,可参考下问题同时解决。


1
解决org.apache.jasper.JasperException:The absolute uri: http://java.sun.com/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application问题(该URI适用JSTL 1.0,而非JSTL 1.2

->Tomcat10+上安装JSTL(参考)

1
2
3
4
5
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>2.0.0</version>
</dependency>

也可以/WEB-INF/libWeb项目的文件夹中或者Tomcat10的apache-tomcat-10.0.12/lib实现相同效果

->Tomcat9-上安装JSTL

1
2
3
4
5
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>1.2.6</version>
</dependency>

也可以/WEB-INF/libWeb项目的文件夹中或者Tomcat10的apache-tomcat-9.0.54/lib实现相同效果

->确保web.xml版本正确

  • Servlet 5.0 (Tomcat 10) 兼容:
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">

<!-- Config here. -->

</web-app>
  • Servlet 4.0 (Tomcat 9)
1
2
3
4
5
6
7
8
9
10
<?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">

<!-- Config here. -->

</web-app>
标签 描述
<c:out> 在JSP中显示数据,就像<%= … >
<c:set> 保存数据
<c:remove> 删除数据
<c:catch> 用来处理产生错误的异常状况,并且将错误信息储存起来
<c:if> 在一般使用的if一样
<c:choose> 本身只当做<c:when>和<c:otherwise>的父标签
<c:when> <c:choose>的子标签,用来判断条件是否成立
<c:otherwise> <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
<c:import> 检索一个绝对或相对 URL,然后将其内容暴露给页面
<c:forEach> 基础迭代标签,接受多种集合类型
<c:forTokens> 根据指定的分隔符来分隔内容并迭代输出
<c:param> 用来给包含或重定向的页面传递参数
<c:redirect> 重定向至一个新的URL.
<c:url> 使用可选的查询参数来创造一个URL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%--coreif.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<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>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="欢迎管理员登录">
</c:out>
</c:if>
<c:out value="${isAdmin}"></c:out>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 定义一个变量score值为85--%>
<c:set var="score" value="96" />

<c:choose>
<c:when test="${score>=90}">
Grade:A
</c:when>
<c:when test="${score>=80}">
Grade:B
</c:when>
<c:when test="${score>=70}">
Grade:C
</c:when>
<c:when test="${score>=60}">
Grade:D
</c:when>
</c:choose>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
ArrayList<String> people =new ArrayList<>();
people.add(0,"Tom");
people.add(1,"Kate");
people.add(2,"Bob");
people.add(3,"John");
request.setAttribute("list",people);
%>

<c:forEach var="pep" items="${list}">
<c:out value="${pep}"/> <br>
</c:forEach>

<hr>

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

3.EL

表达式语言(Expression Language,EL表达式,简称EL),是Java中的一种特殊的通用编程语言,借鉴于JavaScript和XPath。主要作用是在Java Web应用程序嵌入到网页(如JSP)中,用以访问页面的上下文以及不同作用域中的对象,取得对象属性的值,或执行简单的运算或判断操作。EL在得到某个数据时,会自动进行数据类型的转换。

  • ${开始,以}作为结束:
1
${EL表达式}
  • 获取某对象的值可以直接写入对象的名称,如获取对象名为"user"的对象的值:
1
${user}
  • 获取某对象的属性的值使用点操作符(.操作符),如获取对象user的name属性和age属性的值的语法如下:
1
2
${user.name}
${user.age}

JavaBean

JavaBeans是Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中。特点是可序列化,提供无参构造器,提供getter方法和setter方法访问对象的属性。(一般用于和数据库的字段做映射 ORM[表->类 字段->属性 行行为->对象])

people表

id name age address
1 Jack 12 北京
2 Tom 23 西安
3 John 24 成都
1
2
3
4
5
6
class People{
private int id;
private String name;
private int id;
private String address;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.noob.Cookie;

//实体类与数据库的表结构一一对应
public class People {
private int id;
private String name;
private int age;
private String address;

public People() {
}

public People(int id, String name, int age, String address) {
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

@Override
public String toString() {
return "People{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
People people = new People();
people.setAddress();
people.setAge();
people.setId();
people.setName();
--%>
<jsp:useBean id="people" class="com.noob.Cookie.People" scope="page"/>
<jsp:setProperty name="people" property="address" value="北京" />
<jsp:setProperty name="people" property="name" value="Tim" />
<jsp:setProperty name="people" property="age" value="12" />
<jsp:setProperty name="people" property="id" value="1" />

姓名:<jsp:getProperty name="people" property="name"/>
id:<jsp:getProperty name="people" property="id"/>
年龄:<jsp:getProperty name="people" property="age"/>
地址:<jsp:getProperty name="people" property="address"/>
</body>
</html>

->报500错误重新新建Webapp项目即可


MVC

MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。MVC模式最早由Trygve Reenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件架构。MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式透过对复杂度的简化,使程序结构更加直观。软件系统透过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。

1.模型(Model)-程序员编写程序应有的功能(实现算法等 业务逻辑 Service)、数据库专家进行数据管理和数据库设计(可以实现具体的功能 CRUD)。
2.视图(View)-界面设计人员进行图形界面设计。
3.控制器(Controller)-负责转发请求,对请求进行处理,控制视图跳转。


Filter

1.Filter(过滤器),通过Filter可以拦截所有对Web服务器管理的任意Web资源的请求,从而实现特殊的控制功能。例如实现url权限的控制,过滤敏感信息以及压缩响应格式等一些高级的功能。

2.Servlet过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。

3.可以将一个或多个Servlet 过滤器附加到一个Servlet或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages(JSP)文件和HTML页面。调用Servlet前调用所有附加的 Servlet过滤器。

4.Servlet过滤器是可用于Servlet 编程的Java类,可以实现以下目的:

  • 在客户端的请求访问后端资源之前,拦截这些请求。

  • 在服务器的响应发送回客户端之前,处理这些响应。

5.当Web容器启动Web应用程序时,为在部署描述符中声明的每一个过滤器创建一个实例。Filter的执行顺序与在web.xml配置文件中的配置顺序一致,一般把Filter配置在所有的Servlet之前。过滤器通过Web部署描述符(web.xml中的XML标签来声明,然后映射到您的应用程序的部署描述符中的Servlet名称或URL模式。

6.FilterChain:在一个Web工程中,对同一个Web资源访问时,可以有多个Filter过滤器对其进行拦截,多个过滤器在tomcat服务器启动时,组成过滤器链FilterChain。

每一个Filter必须执行chain.doFilter(request,response)方法,才能将控制权交到下一个过滤器或者目标资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.noob.filter;

import jakarta.servlet.*;

import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
/*初始化 web服务器启动初始化*/
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
res.setContentType("text/html;charset=utf-8");
chain.doFilter(req,res); /*继续执行请求,否则程序会被拦截停止*/

}
/*销毁 web服务器关闭filter被销毁*/

public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.noob.servlet;

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

import java.io.IOException;

public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
resp.setCharacterEncoding("utf-16");
或者
resp.setContentType("text/html;charset=utf-8");
解决乱码
*/
resp.getWriter().write("你好世界");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.noob.filter.CharacterEncodingFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是/servlet下的请求,都经过该过滤器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>ServletDemo</servlet-name>
<servlet-class>com.noob.servlet.ServletDemo</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ServletDemo</servlet-name>
<url-pattern>/servlet/demo</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>ServletDemo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>

</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp/jakarta.servlet.jsp-api -->
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.0.0</version>
</dependency>


<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>2.0.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>

Listener

Listener(监听器),用于监听Web应用中某些对象的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当监听范围的对象的状态发生变化的时候,服务器自动调用监听器对象中对应的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.noob.listener;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;

public class OnlineCountListener implements HttpSessionListener {
/*
创建session监听
一旦创建session就会触发该事件
*/
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
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监听*/
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);
}
}
1
2
3
<listener>
<listener-class>com.noob.listener.OnlineCountListener</listener-class>
</listener>
1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>当前有<span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
<!--Tomcat10编写jsp getServletConfig()会报错但不影响使用 也可更换Tomcat9-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

GUI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.noob.listener;

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class Pannel {
public static void main(String[] args) {
Frame frame = new Frame("Tset");
Panel pannel = new Panel(null);
frame.setLayout(null);

frame.setBounds(100,100,500,500);
frame.setBackground(new Color(0,0,200));
pannel.setBounds(50,50,300,300);
pannel.setBackground(new Color(0,255,0));
frame.add(pannel);
frame.setVisible(true);
/* 监听关闭时间 */
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
System.out.println("打开");
}

@Override
public void windowClosing(WindowEvent e) {
System.out.println("关闭中");
System.exit(0);
}

@Override
public void windowClosed(WindowEvent e) {
System.out.println("已关闭");
}

@Override
public void windowIconified(WindowEvent e) {

}

@Override
public void windowDeiconified(WindowEvent e) {

}

@Override
public void windowActivated(WindowEvent e) {
System.out.println("已激活");
}

@Override
public void windowDeactivated(WindowEvent e) {
System.out.println("未激活");
}
});
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.noob.filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class SysFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest req, ServletResponse rep, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) rep;
/* 当用户注销后或者未登录就进入sys目录的话,会一直重定向的,造成网页奔溃*/
if(request.getSession().getAttribute("USER_SESSION")==null){
response.sendRedirect("/error.jsp");
}
chain.doFilter(request,response);
}

@Override
public void destroy() {

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.noob.servlet;

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

import java.io.IOException;
/*
将Tomcat10配置Deployment中的Application context改为/确保login.jsp跳转正确
否则实际地址为http://localhost:8080/[Application context]/servlet/login
login.jsp找不到报404
*/
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");


if(username.equals("admin")){
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");
}else{
resp.sendRedirect("/sys/error.jsp");
}
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.noob.servlet;

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

import java.io.IOException;

public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session = req.getSession().getAttribute("USER_SESSION");
if(user_session!=null){
req.getSession().removeAttribute("USER_SESSION");
resp.sendRedirect("/login.jsp");
}
}

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

webapp/sys/error.jsp - webapp/error.jsp

1
2
3
4
5
6
7
8
9
10
<%@ 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>

webapp/success/error.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
Object userSession = request.getSession().getAttribute("USER_SESSION");
if(userSession==null){
response.sendRedirect("/login.jsp");
}
--%>

登录成功
<h1>主页</h1>
<p> <a href="/servlet/logout">注销</a> </p>
</body>
</html>

webapp/login.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录</h1>

<form action="/servlet/login" method="post">
<input type="text" name="username">
<input type="submit">

</form>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.noob.filter.CharacterEncodingFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是/servlet下的请求,都经过该过滤器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>ServletDemo</servlet-name>
<servlet-class>com.noob.servlet.ServletDemo</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ServletDemo</servlet-name>
<url-pattern>/servlet/demo</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>ServletDemo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>

<listener>
<listener-class>com.noob.listener.OnlineCountListener</listener-class>
</listener>

<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.noob.servlet.LoginServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/login</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.noob.servlet.LogoutServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.noob.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
</web-app>

JDBC

1.Java数据库连接(Java Database Connectivity,JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC是面向关系型数据库的。
2.JDBC驱动程序共分四种类型:

  • JDBC-ODBC桥
  • 本地API驱动
  • 网络协议驱动
  • 本地协议驱动

数据库依赖(Mysql驱动)

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.noob.test;

import java.sql.*;

public class JdbcDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
/*配置信息*/
String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
String username = "root";
String password = "0513";

/*加载驱动*/
Class.forName("com.mysql.jdbc.Driver");
/*连接数据库,代表数据库*/
Connection connection = DriverManager.getConnection(url,username,password);
/*向数据库发送SQL的对象statement:CRUD*/
Statement statement = connection.createStatement();
/*编写SQL*/
String sql="select * from users";
String sql2="delete from users where id=3";
/*执行查询SQL语句,返回一个ResultSet(结果集)*/
/*受影响的行数*/
int lines = statement.executeUpdate(sql2);
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"));
}
/*关闭连接,释放资源 先开后关*/
rs.close();
statement.close();
connection.close();
}
}

1.警告:Loading class `com.mysql.jdbc.Driver’. This is deprecated.

com.mysql.jdbc.Driver已被弃用,使用新的驱动com.mysql.cj.jdbc.Driver.

2.PreparedStatement接口继承Statement(始终以PreparedStatement代替Statement,防止sql注入,且执行速度更高):

  • PreparedStatement实例包含已编译的SQL语句。包含于PreparedStatement对象中的SQL语句可具有一个或多个IN参数。IN参数的值在SQL语句创建时未被指定。相反的,该语句为每个IN参数保留一个问号(?)作为占位符,每个问号的值必须在该语句执行之前,通过对应的set方法来提供。

  • 由于PreparedStatement对象已预编译过,所以其执行速度要快于Statement对象。因此,多次执行的 SQL语句经常创建PreparedStatement对象,以提高效率。

  • 作为Statement的子类,PreparedStatement继承了Statement的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代I 参数占位符的值。同时,三种方法execute、 executeQuery和 executeUpdate已被更改以使之不再需要参数。这些方法的Statement形式(接受SQL语句参数的形式)不应该用于PreparedStatement对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.noob.test;

import java.sql.*;

public class JdbcDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
/*配置信息*/
String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
String username = "root";
String password = "0513";

/*加载驱动*/
Class.forName("com.mysql.jdbc.Driver");
/*连接数据库,代表数据库*/
Connection connection = DriverManager.getConnection(url,username,password);
/*编写SQL*/
String sql="insert into users(id, name, password, email, birthday) VALUES (?,?,?,?,?); ";
/*预编译*/
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,3); //第一个占位符?赋值为3
preparedStatement.setString(2,"Kiki");
preparedStatement.setString(3,"12122332");
preparedStatement.setString(4,"kiki@gmail.com");
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));/*外Date为java.sql.Date*/

/*执行sql*/
int i = preparedStatement.executeUpdate();
if(i>0){
System.out.println("执行成功");
}
/*关闭连接,释放资源*/
preparedStatement.close();
connection.close();

}
}
1
2
3
4
5
6
7
CREATE TABLE users (
id INT PRIMARY KEY,
`name` VARCHAR (40),
`password` VARCHAR (40),
email VARCHAR (40),
birthday DATE
) ;

事务

1.事务控制何时更改提交并应用于数据库。将单个SQL语句或一组SQL语句视为一个逻辑单元,如果任何语句失败,整个事务将失败。

2.数据库系统保证在一个事务中的所有SQL要么全部执行成功,要么全部不执行,即数据库事务具有ACID特性:

  • Atomicity:原子性
  • Consistency:一致性
  • Isolation:隔离性
  • Durability:持久性
1
2
3
4
5
6
7
8
9
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);

1
2
3
4
5
start transaction ;
update account set money=money-100 where name='A';
update account set money=money+100 where name='B';
rollback ;
commit ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.noob.test;

import org.junit.Test;

import java.sql.*;

public class JdbcDemo3 {
@Test
public void testjdbc() throws ClassNotFoundException, SQLException {

String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
String username = "root";
String password = "0513";
Connection connection=null;

try{
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, username, password);
/*开启事务 关闭自动提交 开启手动提交*/
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();
} catch (Exception e){
try{
/*如果出现异常,数据库进行回滚*/
connection.rollback();
}catch (SQLException e1){
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try{
connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}

Junit

JUnit是一个[ava语言的单元测试框架。它由Kent Beck和Erich Gamma建立。JUnit有它自己的JUnit扩展生态圈。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
-->
1
2
3
4
5
6
7
8
9
package com.noob.test;
/*import org.junit.jupiter.api.Test;*/
import org.junit.Test;
public class Demo {
@Test
public void Run(){
System.out.println("Test Junit");
}
}

无法导入junit包:删除pom.xml中junit依赖中的<scope>test</scope>。


订单超市管理系统SMBMS

来源:KuangStudy SMBMS

前端提交表单->Servlet->Service->Dao

1.创建对应数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
CREATE DATABASE `smbms`;

USE `smbms`;

DROP TABLE IF EXISTS `smbms_address`;

CREATE TABLE `smbms_address` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`contact` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人姓名',
`addressDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '收货地址明细',
`postCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '邮编',
`tel` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系人电话',
`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者',
`modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间',
`userId` BIGINT(20) DEFAULT NULL COMMENT '用户ID',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


INSERT INTO `smbms_address`(`id`,`contact`,`addressDesc`,`postCode`,`tel`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`,`userId`) VALUES (1,'王丽','北京市东城区东交民巷44号','100010','13678789999',1,'2016-04-13 00:00:00',NULL,NULL,1),(2,'张红丽','北京市海淀区丹棱街3号','100000','18567672312',1,'2016-04-13 00:00:00',NULL,NULL,1),(3,'任志强','北京市东城区美术馆后街23号','100021','13387906742',1,'2016-04-13 00:00:00',NULL,NULL,1),(4,'曹颖','北京市朝阳区朝阳门南大街14号','100053','13568902323',1,'2016-04-13 00:00:00',NULL,NULL,2),(5,'李慧','北京市西城区三里河路南三巷3号','100032','18032356666',1,'2016-04-13 00:00:00',NULL,NULL,3),(6,'王国强','北京市顺义区高丽营镇金马工业区18号','100061','13787882222',1,'2016-04-13 00:00:00',NULL,NULL,3);


DROP TABLE IF EXISTS `smbms_bill`;

CREATE TABLE `smbms_bill` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`billCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '账单编码',
`productName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品名称',
`productDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品描述',
`productUnit` VARCHAR(10) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '商品单位',
`productCount` DECIMAL(20,2) DEFAULT NULL COMMENT '商品数量',
`totalPrice` DECIMAL(20,2) DEFAULT NULL COMMENT '商品总额',
`isPayment` INT(10) DEFAULT NULL COMMENT '是否支付(1:未支付 2:已支付)',
`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',
`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',
`providerId` BIGINT(20) DEFAULT NULL COMMENT '供应商ID',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


INSERT INTO `smbms_bill`(`id`,`billCode`,`productName`,`productDesc`,`productUnit`,`productCount`,`totalPrice`,`isPayment`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`,`providerId`) VALUES (2,'BILL2016_002','香皂、肥皂、药皂','日用品-皂类','块','1000.00','10000.00',2,1,'2016-03-23 04:20:40',NULL,NULL,13),(3,'BILL2016_003','大豆油','食品-食用油','斤','300.00','5890.00',2,1,'2014-12-14 13:02:03',NULL,NULL,6),(4,'BILL2016_004','橄榄油','食品-进口食用油','斤','200.00','9800.00',2,1,'2013-10-10 03:12:13',NULL,NULL,7),(5,'BILL2016_005','洗洁精','日用品-厨房清洁','瓶','500.00','7000.00',2,1,'2014-12-14 13:02:03',NULL,NULL,9),(6,'BILL2016_006','美国大杏仁','食品-坚果','袋','300.00','5000.00',2,1,'2016-04-14 06:08:09',NULL,NULL,4),(7,'BILL2016_007','沐浴液、精油','日用品-沐浴类','瓶','500.00','23000.00',1,1,'2016-07-22 10:10:22',NULL,NULL,14),(8,'BILL2016_008','不锈钢盘碗','日用品-厨房用具','个','600.00','6000.00',2,1,'2016-04-14 05:12:13',NULL,NULL,14),(9,'BILL2016_009','塑料杯','日用品-杯子','个','350.00','1750.00',2,1,'2016-02-04 11:40:20',NULL,NULL,14),(10,'BILL2016_010','豆瓣酱','食品-调料','瓶','200.00','2000.00',2,1,'2013-10-29 05:07:03',NULL,NULL,8),(11,'BILL2016_011','海之蓝','饮料-国酒','瓶','50.00','10000.00',1,1,'2016-04-14 16:16:00',NULL,NULL,1),(12,'BILL2016_012','芝华士','饮料-洋酒','瓶','20.00','6000.00',1,1,'2016-09-09 17:00:00',NULL,NULL,1),(13,'BILL2016_013','长城红葡萄酒','饮料-红酒','瓶','60.00','800.00',2,1,'2016-11-14 15:23:00',NULL,NULL,1),(14,'BILL2016_014','泰国香米','食品-大米','斤','400.00','5000.00',2,1,'2016-10-09 15:20:00',NULL,NULL,3),(15,'BILL2016_015','东北大米','食品-大米','斤','600.00','4000.00',2,1,'2016-11-14 14:00:00',NULL,NULL,3),(16,'BILL2016_016','可口可乐','饮料','瓶','2000.00','6000.00',2,1,'2012-03-27 13:03:01',NULL,NULL,2),(17,'BILL2016_017','脉动','饮料','瓶','1500.00','4500.00',2,1,'2016-05-10 12:00:00',NULL,NULL,2),(18,'BILL2016_018','哇哈哈','饮料','瓶','2000.00','4000.00',2,1,'2015-11-24 15:12:03',NULL,NULL,2);

DROP TABLE IF EXISTS `smbms_provider`;

CREATE TABLE `smbms_provider` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`proCode` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商编码',
`proName` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商名称',
`proDesc` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商详细描述',
`proContact` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '供应商联系人',
`proPhone` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '联系电话',
`proAddress` VARCHAR(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址',
`proFax` VARCHAR(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '传真',
`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


INSERT INTO `smbms_provider`(`id`,`proCode`,`proName`,`proDesc`,`proContact`,`proPhone`,`proAddress`,`proFax`,`createdBy`,`creationDate`,`modifyDate`,`modifyBy`) VALUES (1,'BJ_GYS001','北京三木堂商贸有限公司','长期合作伙伴,主营产品:茅台、五粮液、郎酒、酒鬼酒、泸州老窖、赖茅酒、法国红酒等','张国强','13566667777','北京市丰台区育芳园北路','010-58858787',1,'2013-03-21 16:52:07',NULL,NULL),(2,'HB_GYS001','石家庄帅益食品贸易有限公司','长期合作伙伴,主营产品:饮料、水饮料、植物蛋白饮料、休闲食品、果汁饮料、功能饮料等','王军','13309094212','河北省石家庄新华区','0311-67738876',1,'2016-04-13 04:20:40',NULL,NULL),(3,'GZ_GYS001','深圳市泰香米业有限公司','初次合作伙伴,主营产品:良记金轮米,龙轮香米等','郑程瀚','13402013312','广东省深圳市福田区深南大道6006华丰大厦','0755-67776212',1,'2014-03-21 16:56:07',NULL,NULL),(4,'GZ_GYS002','深圳市喜来客商贸有限公司','长期合作伙伴,主营产品:坚果炒货.果脯蜜饯.天然花茶.营养豆豆.特色美食.进口食品.海味零食.肉脯肉','林妮','18599897645','广东省深圳市福龙工业区B2栋3楼西','0755-67772341',1,'2013-03-22 16:52:07',NULL,NULL),(5,'JS_GYS001','兴化佳美调味品厂','长期合作伙伴,主营产品:天然香辛料、鸡精、复合调味料','徐国洋','13754444221','江苏省兴化市林湖工业区','0523-21299098',1,'2015-11-22 16:52:07',NULL,NULL),(6,'BJ_GYS002','北京纳福尔食用油有限公司','长期合作伙伴,主营产品:山茶油、大豆油、花生油、橄榄油等','马莺','13422235678','北京市朝阳区珠江帝景1号楼','010-588634233',1,'2012-03-21 17:52:07',NULL,NULL),(7,'BJ_GYS003','北京国粮食用油有限公司','初次合作伙伴,主营产品:花生油、大豆油、小磨油等','王驰','13344441135','北京大兴青云店开发区','010-588134111',1,'2016-04-13 00:00:00',NULL,NULL),(8,'ZJ_GYS001','慈溪市广和绿色食品厂','长期合作伙伴,主营产品:豆瓣酱、黄豆酱、甜面酱,辣椒,大蒜等农产品','薛圣丹','18099953223','浙江省宁波市慈溪周巷小安村','0574-34449090',1,'2013-11-21 06:02:07',NULL,NULL),(9,'GX_GYS001','优百商贸有限公司','长期合作伙伴,主营产品:日化产品','李立国','13323566543','广西南宁市秀厢大道42-1号','0771-98861134',1,'2013-03-21 19:52:07',NULL,NULL),(10,'JS_GYS002','南京火头军信息技术有限公司','长期合作伙伴,主营产品:不锈钢厨具等','陈女士','13098992113','江苏省南京市浦口区浦口大道1号新城总部大厦A座903室','025-86223345',1,'2013-03-25 16:52:07',NULL,NULL),(11,'GZ_GYS003','广州市白云区美星五金制品厂','长期合作伙伴,主营产品:海绵床垫、坐垫、靠垫、海绵枕头、头枕等','梁天','13562276775','广州市白云区钟落潭镇福龙路20号','020-85542231',1,'2016-12-21 06:12:17',NULL,NULL),(12,'BJ_GYS004','北京隆盛日化科技','长期合作伙伴,主营产品:日化环保清洗剂,家居洗涤专卖、洗涤用品网、墙体除霉剂、墙面霉菌清除剂等','孙欣','13689865678','北京市大兴区旧宫','010-35576786',1,'2014-11-21 12:51:11',NULL,NULL),(13,'SD_GYS001','山东豪克华光联合发展有限公司','长期合作伙伴,主营产品:洗衣皂、洗衣粉、洗衣液、洗洁精、消杀类、香皂等','吴洪转','13245468787','山东济阳济北工业区仁和街21号','0531-53362445',1,'2015-01-28 10:52:07',NULL,NULL),(14,'JS_GYS003','无锡喜源坤商行','长期合作伙伴,主营产品:日化品批销','周一清','18567674532','江苏无锡盛岸西路','0510-32274422',1,'2016-04-23 11:11:11',NULL,NULL),(15,'ZJ_GYS002','乐摆日用品厂','长期合作伙伴,主营产品:各种中、高档塑料杯,塑料乐扣水杯(密封杯)、保鲜杯(保鲜盒)、广告杯、礼品杯','王世杰','13212331567','浙江省金华市义乌市义东路','0579-34452321',1,'2016-08-22 10:01:30',NULL,NULL);


DROP TABLE IF EXISTS `smbms_role`;

CREATE TABLE `smbms_role` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`roleCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色编码',
`roleName` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色名称',
`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '修改者',
`modifyDate` DATETIME DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


INSERT INTO `smbms_role`(`id`,`roleCode`,`roleName`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`) VALUES (1,'SMBMS_ADMIN','系统管理员',1,'2016-04-13 00:00:00',NULL,NULL),(2,'SMBMS_MANAGER','经理',1,'2016-04-13 00:00:00',NULL,NULL),(3,'SMBMS_EMPLOYEE','普通员工',1,'2016-04-13 00:00:00',NULL,NULL);


DROP TABLE IF EXISTS `smbms_user`;

CREATE TABLE `smbms_user` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`userCode` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户编码',
`userName` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户名称',
`userPassword` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户密码',
`gender` INT(10) DEFAULT NULL COMMENT '性别(1:女、 2:男)',
`birthday` DATE DEFAULT NULL COMMENT '出生日期',
`phone` VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '手机',
`address` VARCHAR(30) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '地址',
`userRole` BIGINT(20) DEFAULT NULL COMMENT '用户角色(取自角色表-角色id)',
`createdBy` BIGINT(20) DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` DATETIME DEFAULT NULL COMMENT '创建时间',
`modifyBy` BIGINT(20) DEFAULT NULL COMMENT '更新者(userId)',
`modifyDate` DATETIME DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `smbms_user`(`id`,`userCode`,`userName`,`userPassword`,`gender`,`birthday`,`phone`,`address`,`userRole`,`createdBy`,`creationDate`,`modifyBy`,`modifyDate`) VALUES (1,'admin','系统管理员','1234567',1,'1983-10-10','13688889999','北京市海淀区成府路207号',1,1,'2013-03-21 16:52:07',NULL,NULL),(2,'liming','李明','0000000',2,'1983-12-10','13688884457','北京市东城区前门东大街9号',2,1,'2014-12-31 19:52:09',NULL,NULL),(5,'hanlubiao','韩路彪','0000000',2,'1984-06-05','18567542321','北京市朝阳区北辰中心12号',2,1,'2014-12-31 19:52:09',NULL,NULL),(6,'zhanghua','张华','0000000',1,'1983-06-15','13544561111','北京市海淀区学院路61号',3,1,'2013-02-11 10:51:17',NULL,NULL),(7,'wangyang','王洋','0000000',2,'1982-12-31','13444561124','北京市海淀区西二旗辉煌国际16层',3,1,'2014-06-11 19:09:07',NULL,NULL),(8,'zhaoyan','赵燕','0000000',1,'1986-03-07','18098764545','北京市海淀区回龙观小区10号楼',3,1,'2016-04-21 13:54:07',NULL,NULL),(10,'sunlei','孙磊','0000000',2,'1981-01-04','13387676765','北京市朝阳区管庄新月小区12楼',3,1,'2015-05-06 10:52:07',NULL,NULL),(11,'sunxing','孙兴','0000000',2,'1978-03-12','13367890900','北京市朝阳区建国门南大街10号',3,1,'2016-11-09 16:51:17',NULL,NULL),(12,'zhangchen','张晨','0000000',1,'1986-03-28','18098765434','朝阳区管庄路口北柏林爱乐三期13号楼',3,1,'2016-08-09 05:52:37',1,'2016-04-14 14:15:36'),(13,'dengchao','邓超','0000000',2,'1981-11-04','13689674534','北京市海淀区北航家属院10号楼',3,1,'2016-07-11 08:02:47',NULL,NULL),(14,'yangguo','杨过','0000000',2,'1980-01-01','13388886623','北京市朝阳区北苑家园茉莉园20号楼',3,1,'2015-02-01 03:52:07',NULL,NULL),(15,'zhaomin','赵敏','0000000',1,'1987-12-04','18099897657','北京市昌平区天通苑3区12号楼',2,1,'2015-09-12 12:02:12',NULL,NULL);

2.新建Maven Webapp项目

  • 配置Tomcat
    • Edit Configuration
    • web.xml
  • 导入依赖
    • pom.xml
  • 连接数据库
    • DataBase ->smbms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!--pom.xml-->
<?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>com.noob</groupId>
<artifactId>smbms</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.0.0</version>
</dependency>

<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>2.0.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>

</dependencies>

</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<!--web.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<!--字符编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.noob.filter.CharacterEncodingFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>



<!--设置欢迎界面-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>

<!--Servlet-->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.noob.servlet.LoginServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.noob.servlet.LogoutServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>
<!--用户登录过滤器-->
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.noob.filter.SysFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.noob.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/jsp/user.do</url-pattern>
</servlet-mapping>

<!--默认Session过期时间-->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>

3.创建包结构(项目开发规范)

1
2
3
4
5
6
7
8
com
|--noob
|--dao (数据库访问层)
|--filter (过滤器)
|--pojo (数据库对象)
|--service (业务逻辑)
|--servlet
|--util (工具类)

4.编写实体类(ORM映射:表-类映射)

  • User类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package com.noob.pojo;

import java.util.Date;

public class User {
private Integer id; //id
private String userCode; //用户编码
private String userName; //用户名称
private String userPassword; //用户密码
private Integer gender; //性别
private Date birthday; //出生日期
private String phone; //电话
private String address; //地址
private Integer userRole; //用户角色
private Integer createdBy; //创建者

private Date creationDate; //创建日期
private Integer modifyBy; //更新者
private Date modifyDate; //更新日期

private Integer age; //年龄
private String userRoleName; //用户角色名称

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUserCode() {
return userCode;
}

public void setUserCode(String userCode) {
this.userCode = userCode;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getUserPassword() {
return userPassword;
}

public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}

public Integer getGender() {
return gender;
}

public void setGender(Integer gender) {
this.gender = gender;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public Integer getUserRole() {
return userRole;
}

public void setUserRole(Integer userRole) {
this.userRole = userRole;
}

public Integer getCreatedBy() {
return createdBy;
}

public void setCreatedBy(Integer createBy) {
this.createdBy = createBy;
}

public Date getCreationDate() {
return creationDate;
}

public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}

public Integer getModifyBy() {
return modifyBy;
}

public void setModifyBy(Integer modifyBy) {
this.modifyBy = modifyBy;
}

public Date getModifyDate() {
return modifyDate;
}

public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}

public Integer getAge() {
/*计算当前年龄*/
Date date = new Date();
Integer age = date.getYear()-birthday.getYear();
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public String getUserRoleName() {
return userRoleName;
}

public void setUserRoleName(String userRoleName) {
this.userRoleName = userRoleName;
}

}
  • Bill类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import java.math.BigDecimal;
import java.util.Date;
public class Bill {
private Integer id; //id
private String billCode; //账单编码
private String productName; //商品名称
private String productDesc; //商品描述
private String productUnit; //商品单位
private BigDecimal productCount; //商品数量
private BigDecimal totalPrice; //总金额
private Integer isPayment; //是否支付
private Integer providerId; //供应商ID
private Integer createdBy; //创建者
private Date creationDate; //创建时间
private Integer modifyBy; //更新者
private Date modifyDate; //更新时间

private String providerName; //供应商名称


public String getProviderName() {
return providerName;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBillCode() {
return billCode;
}
public void setBillCode(String billCode) {
this.billCode = billCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductDesc() {
return productDesc;
}
public void setProductDesc(String productDesc) {
this.productDesc = productDesc;
}
public String getProductUnit() {
return productUnit;
}
public void setProductUnit(String productUnit) {
this.productUnit = productUnit;
}
public BigDecimal getProductCount() {
return productCount;
}
public void setProductCount(BigDecimal productCount) {
this.productCount = productCount;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
public Integer getIsPayment() {
return isPayment;
}
public void setIsPayment(Integer isPayment) {
this.isPayment = isPayment;
}

public Integer getProviderId() {
return providerId;
}
public void setProviderId(Integer providerId) {
this.providerId = providerId;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Integer getModifyBy() {
return modifyBy;
}
public void setModifyBy(Integer modifyBy) {
this.modifyBy = modifyBy;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
}
  • Role类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.util.Date;
public class Role {
private Integer id; //id
private String roleCode; //角色编码
private String roleName; //角色名称
private Integer createdBy; //创建者
private Date creationDate; //创建时间
private Integer modifyBy; //更新者
private Date modifyDate; //更新时间

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Integer getModifyBy() {
return modifyBy;
}
public void setModifyBy(Integer modifyBy) {
this.modifyBy = modifyBy;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
}
  • Provider类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import java.util.Date;
public class Provider {
private Integer id; //id
private String proCode; //供应商编码
private String proName; //供应商名称
private String proDesc; //供应商描述
private String proContact; //供应商联系人
private String proPhone; //供应商电话
private String proAddress; //供应商地址
private String proFax; //供应商传真
private Integer createdBy; //创建者
private Date creationDate; //创建时间
private Integer modifyBy; //更新者
private Date modifyDate; //更新时间

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProCode() {
return proCode;
}
public void setProCode(String proCode) {
this.proCode = proCode;
}
public String getProName() {
return proName;
}
public void setProName(String proName) {
this.proName = proName;
}
public String getProDesc() {
return proDesc;
}
public void setProDesc(String proDesc) {
this.proDesc = proDesc;
}
public String getProContact() {
return proContact;
}
public void setProContact(String proContact) {
this.proContact = proContact;
}
public String getProPhone() {
return proPhone;
}
public void setProPhone(String proPhone) {
this.proPhone = proPhone;
}
public String getProAddress() {
return proAddress;
}
public void setProAddress(String proAddress) {
this.proAddress = proAddress;
}
public String getProFax() {
return proFax;
}
public void setProFax(String proFax) {
this.proFax = proFax;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Integer getModifyBy() {
return modifyBy;
}
public void setModifyBy(Integer modifyBy) {
this.modifyBy = modifyBy;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
}

5.编写基础公共类

  • 数据库配置文件(main->resource->db.properties)
1
2
3
4
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true
username=root
password=0513
  • 数据库公共类(Dao->BaseDao.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.noob.dao;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/*操作数据库的公共类*/
public class BaseDao {
private static String drive;
private static String url;
private static String username;
private static String password;

/*静态代码块类加载时即初始化*/
static {
Properties properties = new Properties();
/*通过类加载器读取对应的资源*/
InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");

try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
drive = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
}
/*获取数据库的连接*/
public static Connection getConnection(){
Connection connection = null;
try {
Class.forName(drive);
connection = DriverManager.getConnection(url,username,password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}

/*编写查询公共方法*/
public static ResultSet excute(Connection connection,String sql,Object[] params,ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException {
/*预编译sql*/
preparedStatement = connection.prepareStatement(sql);

for(int i=0;i<params.length;i++){
/*setObject占位符从一开始,数组从0开始*/
preparedStatement.setObject(i+1,params[i]);
}
resultSet = preparedStatement.executeQuery();
return resultSet;

}

/*编写增删改公共方法*/
public static int excute(Connection connection,String sql,Object[] params, PreparedStatement preparedStatement) throws SQLException {
preparedStatement = connection.prepareStatement(sql);

for(int i=0;i<params.length;i++){
/*setObject占位符从一开始,数组从0开始*/
preparedStatement.setObject(i+1,params[i]);
}
int updateRows = preparedStatement.executeUpdate();
return updateRows;

}

/*释放资源*/
public static boolean closeResource(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet){
boolean flag = true;
if(resultSet!=null){
try {
resultSet.close();
//GC回收
resultSet=null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
//GC回收
preparedStatement=null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
if(connection!=null){
try {
connection.close();
//GC回收
connection=null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
return flag;
}
}
  • 编写字符过滤器并注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.noob.filter;

import jakarta.servlet.*;

import java.io.IOException;

public class CharacterEncodingFilter implements Filter {

public void init(FilterConfig filterConfig) throws ServletException {

}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

chain.doFilter(request,response);
}

public void destroy() {

}
}

6.编写或导入静态资源

1
2
3
4
5
webapp
|-calendar
|-css
|-js
|-image

登录

文件结构

1.编写前端页面(webapp->login.jsp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>系统登录 - 超市订单管理系统</title>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/css/style.css" />
<script type="text/javascript">
/* if(top.location!=self.location){
top.location=self.location;
} */
</script>
</head>
<body class="login_bg">
<section class="loginBox">
<header class="loginHeader">
<h1>超市订单管理系统</h1>
</header>
<section class="loginCont">
<form class="loginForm" action="${pageContext.request.contextPath }/login.do" name="actionForm" id="actionForm" method="post" >
<div class="info">${error}</div>
<div class="inputbox">
<label for="userCode">用户名:</label>
<input type="text" class="input-text" id="userCode" name="userCode" placeholder="请输入用户名" required/>
</div>
<div class="inputbox">
<label for="userPassword">密码:</label>
<input type="password" id="userPassword" name="userPassword" placeholder="请输入密码" required/>
</div>
<div class="subBtn">

<input type="submit" value="登录"/>
<input type="reset" value="重置"/>
</div>
</form>
</section>
</section>
</body>
</html>

2.设置首页

1
2
3
4
<!--设置欢迎界面-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>

3.编写Dao层用户登录的接口

1
2
3
4
5
6
7
8
9
10
11
package com.noob.dao.user;

import com.noob.pojo.User;

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

public interface UserDao {
/*得到要登录用户*/
public User getLoginUser(Connection connection, String usercode) throws SQLException;
}

4.编写Dao接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.noob.dao.user;

import com.noob.dao.BaseDao;
import com.noob.pojo.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDaoImpl implements UserDao{

public User getLoginUser(Connection connection, String usercode )throws SQLException {
PreparedStatement pstm = null;
ResultSet rs = null;
User user = null;
if (connection != null) {
String sql = "select * from smbms_user where userCode=?";
Object[] params = {usercode};
rs = BaseDao.excute(connection, pstm, rs, sql, params);
if(rs.next()){
user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setUserPassword(rs.getString("userPassword"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setAddress(rs.getString("address"));
user.setUserRole(rs.getInt("userRole"));
user.setCreatedBy(rs.getInt("createdBy"));
user.setCreationDate(rs.getTimestamp("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getTimestamp("modifyDate"));
}
BaseDao.closeResource(null,pstm,rs);
}
return user;
}
}

5.编写业务层接口

1
2
3
4
5
6
7
8
package com.noob.service.user;

import com.noob.pojo.User;

public interface UserService {
/*用户登录*/
public User login(String userCode, String password);
}

6.编写业务层实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.noob.service.user;

import com.noob.dao.BaseDao;
import com.noob.dao.user.UserDao;
import com.noob.dao.user.UserDaoImpl;
import com.noob.pojo.User;
import org.junit.Test;

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

public class UserServiceImpl implements UserService{
/*业务层需要调用Dao层,即需要引入Dao层*/
private UserDao userDao;
public UserServiceImpl(){
userDao = new UserDaoImpl();
}

public User login(String userCode, String password) {
Connection connection = null;
User user = null;

try {
connection = BaseDao.getConnection();
/*调用业务层调用对应的数据库操作*/
user = userDao.getLoginUser(connection,userCode);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.closeResource(connection,null ,null);
}
return user;


}
@Test
public void test(){
UserServiceImpl userService = new UserServiceImpl();
User admin = userService.login("liming","12344");
System.out.println(admin.getUserPassword());
}
}

6.编写或导入相关页面:webapp-jsp

1
2
3
4
5
6
7
8
9
10
11
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@include file="/jsp/common/head.jsp"%>
<div class="right">
<img class="wColck" src="${pageContext.request.contextPath }/images/clock.jpg" alt=""/>
<div class="wFont">
<h2>${userSession.userName }</h2>
<p>欢迎来到超市订单管理系统!</p>
</div>
</div>
</section>
<%@include file="/jsp/common/foot.jsp" %>

7.编写工具类

1
2
3
4
5
package com.noob.util;

public class Constants {
public final static String USER_SESSION = "userSession";
}

8.编写Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.noob.servlet;

import com.noob.pojo.User;
import com.noob.service.user.UserService;
import com.noob.service.user.UserServiceImpl;
import com.noob.util.Constants;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class LoginServlet extends HttpServlet {
/*Servlet控制层,调用业务层代码*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LoginServlet Start");
/*从login.jsp获取用户名和密码*/
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
/*与数据库的密码进行对比,调用业务层*/
UserService userService = new UserServiceImpl();
User user = userService.login(userCode,userPassword);

/*数据库存在此人*/
if(user!=null){
/*将用户信息存放到Session中*/
req.getSession().setAttribute(Constants.USER_SESSION,user);
/*跳转到主页*/
resp.sendRedirect("jsp/frame.jsp");

}else{ /*查无此人,转发到登录页面,提示错误*/
req.setAttribute("error","用户名或者密码不正确");
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}

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

9.注册Servlet

1
2
3
4
5
6
7
8
9
10
<!--Servlet-->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.noob.servlet.LoginServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>

10.密码验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
用户不存在user调用getUserPassword()会报500错误,需要判空
法1:在Dao层进行判断,同时需要传入password
*/

/*1.UserDao.java*/

public User getLoginUser(Connection connection, String usercode,String passWord) throws SQLException;
/*2.UserServiceImpl.java*/

user = userDao.getLoginUser(connection, userCode,password);
/*3.UserDaoImpl.java*/

/*Code*/
BaseDao.closeResource(null,pstm,rs);
}
//判断密码
if(user!=null&&!passWord.equals(user.getUserPassword())){
user=null;
}
return user;
/*Code*/

/*法2 直接在UserServiceImpl.java业务层进行判断*/
BaseDao.closeResource(connection, null, null);
}
if(user!=null&&!password.equals(user.getUserPassword())){
user=null;
}
return user;
}

注销

移除Session,返回登录界面

1.编写Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.noob.servlet;

import com.noob.util.Constants;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*移除用户的Constants.USER_SESSION*/
req.getSession().removeAttribute(Constants.USER_SESSION);
resp.sendRedirect(req.getContextPath()+"/login.jsp"); /*返回登录界面*/
}

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

2.注册servlet

1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.noob.servlet.LogoutServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>

3.编写登录拦截Filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.noob.filter;


import com.noob.pojo.User;
import com.noob.util.Constants;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {

}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
/*从Session中获取用户*/
User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);
/*用户已被注销或未登录*/
if(user==null){
response.sendRedirect(request.getContextPath()+"/error.jsp");
}else{
chain.doFilter(req,resp);
}

}

public void destroy() {

}
}

4.注册Filter

1
2
3
4
5
6
7
8
9
10
<!--用户登录过滤器-->
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.noob.filter.SysFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>

修改密码

1.编写或导入前端代码(pwdmodify.jsp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="/jsp/common/head.jsp"%>
<div class="right">
<div class="location">
<strong>你现在所在的位置是:</strong>
<span>密码修改页面</span>
</div>
<div class="providerAdd">
<form id="userForm" name="userForm" method="post" action="${pageContext.request.contextPath }/jsp/user.do">
<input type="hidden" name="method" value="savepwd">
<!--div的classerror是验证错误,ok是验证成功-->
<div class="info">${message}</div>
<div class="">
<label for="oldPassword">旧密码:</label>
<input type="password" name="oldpassword" id="oldpassword" value="">
<font color="red"></font>
</div>
<div>
<label for="newPassword">新密码:</label>
<input type="password" name="newpassword" id="newpassword" value="">
<font color="red"></font>
</div>
<div>
<label for="newPassword">确认新密码:</label>
<input type="password" name="rnewpassword" id="rnewpassword" value="">
<font color="red"></font>
</div>
<div class="providerAddBtn">
<!--<a href="#">保存</a>-->
<input type="button" name="save" id="save" value="保存" class="input-button">
</div>
</form>
</div>
</div>
</section>
<%@include file="/jsp/common/foot.jsp" %>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/pwdmodify.js"></script>

2.编写UserDao接口

1
2
/*修改当前用户密码*/
public int updatePwd(Connection connection,int id,String password) throws SQLException;

3.编写UserDao接口实现类(UserDaoImpl.java)

1
2
3
4
5
6
7
8
9
10
11
    public int updatePwd(Connection connection, int id, String password) throws SQLException {
PreparedStatement pstm=null;
int excute = 0;
if(connection!=null){
String sql = "update smbms_user set userPassword = ? where id = ?" ;
Object[] params = {password,id};
excute = BaseDao.excute(connection,sql,params,pstm);
BaseDao.closeResource(null,pstm,null);
}
return excute;
}

4.编写UserService接口

1
2
/*根据用户ID修改密码*/
public boolean updatePwd(int id, String password);

5.编写UserService实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 public boolean updatePwd(int id, String pwd) {
Connection connection = null;
boolean flag=false;
/*修改密码*/
try {
connection = BaseDao.getConnection();
if(userDao.updatePwd(connection,id,pwd)>0){
flag = true;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.closeResource(connection,null,null);
}
return flag;
}

6.编写Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package com.noob.servlet;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.noob.pojo.User;
import com.noob.service.user.UserService;
import com.noob.service.user.UserServiceImpl;
import com.noob.util.Constants;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if(method.equals("savepwd")&&method!=null){
this.updatePwd(req,resp);
} else if(method.equals("pwdmodify")&&method!=null){
this.pwdModify(req,resp);
}
}

public void updatePwd(HttpServletRequest req,HttpServletResponse resp){
/*从Session里面获取ID*/
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String newpassword = req.getParameter("newpassword");
boolean flag = false;
if(o!=null && !StringUtils.isNullOrEmpty(newpassword)){
UserService userService = new UserServiceImpl();
flag = userService.updatePwd(((User)o).getId(),newpassword);
if(flag){
req.setAttribute("message","修改密码成功,请使用新密码重新登录");
/*密码修改成功,移除当前Session*/
req.getSession().removeAttribute(Constants.USER_SESSION);

}else{
req.setAttribute("message","修改密码失败");
}

}else{
req.setAttribute("message","新密码存在问题");
}
try {
req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//验证旧密码 session中有用户密码
public void pwdModify(HttpServletRequest req,HttpServletResponse resp){
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String oldpassword = req.getParameter("oldpassword");


Map<String,String> resultMap = new HashMap<String,String>();
if(o==null){ /*session失效*/
resultMap.put("result","sessionerror");
}else if(StringUtils.isNullOrEmpty(oldpassword)) { /*输入旧密码为空*/
resultMap.put("result","error");
}else{
String userPassword = ((User)o).getUserPassword(); //Session中用户的密码
if(oldpassword.equals(userPassword)){
resultMap.put("result","true");
}else{
resultMap.put("result","false");
}

}
/*JSONArray 阿里巴巴的JSON工具类
resultMap = ["result","sessionerror","result","error"]
Json格式 = {key:value}
*/
try{
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
/*
Ajax
JSONArray 阿里巴巴的JSON工具类, 转换格式 fastjson
resultMap = ["result","sessionerror","result","error"]
Json格式 = {key:value}
*/
writer.write(JSONArray.toJSONString(resultMap));
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}

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

7.注册Servlet

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.noob.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/jsp/user.do</url-pattern>
</servlet-mapping>

用户管理

1.编写或导入分页的工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.noob.util;

public class PageSupport {
//当前页码-来自于用户输入
private int currentPageNo = 1;

//总数量(表)
private int totalCount = 0;

//页面容量
private int pageSize = 0;

//总页数-totalCount/pageSize(+1)
private int totalPageCount = 1;

public int getCurrentPageNo() {
return currentPageNo;
}

public void setCurrentPageNo(int currentPageNo) {
if(currentPageNo > 0){
this.currentPageNo = currentPageNo;
}
}

public int getTotalCount() {
return totalCount;
}

public void setTotalCount(int totalCount) {
if(totalCount > 0){
this.totalCount = totalCount;
//设置总页数
this.setTotalPageCountByRs();
}
}
public int getPageSize() {
return pageSize;
}

public void setPageSize(int pageSize) {
if(pageSize > 0){
this.pageSize = pageSize;
}
}

public int getTotalPageCount() {
return totalPageCount;
}

public void setTotalPageCount(int totalPageCount) {
this.totalPageCount = totalPageCount;
}

public void setTotalPageCountByRs(){
if(this.totalCount % this.pageSize == 0){
this.totalPageCount = this.totalCount / this.pageSize;
}else if(this.totalCount % this.pageSize > 0){
this.totalPageCount = this.totalCount / this.pageSize + 1;
}else{
this.totalPageCount = 0;
}
}
}

2.用户列表资源编写或导入

  • userlist.jsp
  • rollpage.jsp

获取用户数量

1.编写UserDao接口

1
2
/*根据用户名或角查询用户总数*/
public int getUserCount(Connection connection,String username,int userRole) throws SQLException;

2.编写UserDao接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public int getUserCount(Connection connection, String username, int userRole) throws SQLException {
PreparedStatement pstm = null;
ResultSet rs =null;
int count = 0;
if(connection!=null){
StringBuffer sql = new StringBuffer();
sql.append("select count(1) as count from smbms_user u , smbms_role r where u.userRole = r.id");
ArrayList<Object> list=new ArrayList<Object>();
/*搜索限制条件*/
if(!StringUtils.isNullOrEmpty(username)){
sql.append(" and u.userName like ?");
/*模糊查询*/
list.add("%"+username+"%");
}
if(userRole>0){
sql.append(" and u.userRole = ?");
list.add(userRole);
}
Object[] params = list.toArray();
System.out.println("UserDaoImpl->getUserCount:"+sql.toString());
rs = BaseDao.excute(connection,pstm,rs,sql.toString(),params);
if(rs.next()){
count = rs.getInt("count"); /*从结果集中获取数量*/
}
BaseDao.closeResource(null,pstm,rs);
}
return count;


}

3.编写UserService接口

1
2
/*查询记录数*/
public int getUserCount(String username,int userRole);

4.编写UserService实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public int getUserCount(String username, int userRole) {
Connection connection = null;
int count=0;
try {
connection = BaseDao.getConnection();
count=userDao.getUserCount(connection,username,userRole);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.closeResource(connection,null,null);

}
return count;
}

@Test
public void testGetUserCount(){
UserServiceImpl userService = new UserServiceImpl();
int adminCount = userService.getUserCount(null,1);
System.out.println(adminCount);
}

获取用户列表

1.编写UserDao接口

1
2
/*通过条件查询-userList*/
public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize)throws Exception;

2.编写UserDao接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws Exception {

PreparedStatement pstm = null;
ResultSet rs = null;
List<User> userList = new ArrayList<User>();
if(connection != null){
StringBuffer sql = new StringBuffer();
sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id");
List<Object> list = new ArrayList<Object>();
if(!StringUtils.isNullOrEmpty(userName)){
sql.append(" and u.userName like ?");
list.add("%"+userName+"%");
}
if(userRole > 0){
sql.append(" and u.userRole = ?");
list.add(userRole);
}
/*在数据库中 分页使用 limit startIndex pageSize;
(当前页码—1*页面最大记录量=该页第一个数据起始位置
*/
sql.append(" order by creationDate DESC limit ?,?");
currentPageNo = (currentPageNo-1)*pageSize;
list.add(currentPageNo);
list.add(pageSize);

Object[] params = list.toArray();
System.out.println("sql ----> " + sql.toString());
rs = BaseDao.excute(connection, pstm, rs, sql.toString(), params);
while(rs.next()){
User _user = new User();
_user.setId(rs.getInt("id"));
_user.setUserCode(rs.getString("userCode"));
_user.setUserName(rs.getString("userName"));
_user.setGender(rs.getInt("gender"));
_user.setBirthday(rs.getDate("birthday"));
_user.setPhone(rs.getString("phone"));
_user.setUserRole(rs.getInt("userRole"));
_user.setUserRoleName(rs.getString("userRoleName"));
userList.add(_user);
}
BaseDao.closeResource(null, pstm, rs);
}
return userList;
}

3.编写UserService接口

1
2
/*根据条件查询用户列表*/
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);

4.编写UserService接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) {
Connection connection = null;
List<User> userList = null;
System.out.println("queryUserName ---- > " + queryUserName);
System.out.println("queryUserRole ---- > " + queryUserRole);
System.out.println("currentPageNo ---- > " + currentPageNo);
System.out.println("pageSize ---- > " + pageSize);
try {
connection = BaseDao.getConnection();
userList = userDao.getUserList(connection, queryUserName,queryUserRole,currentPageNo,pageSize);
} catch (Exception e) {
e.printStackTrace();
}finally{
BaseDao.closeResource(connection, null, null);
}
return userList;
}


获取角色列表

1.编写接口RoleDao

1
2
3
4
5
6
7
8
9
10
11
package com.noob.dao.role;

import com.noob.pojo.Role;

import java.sql.Connection;
import java.util.List;

public interface RoleDao {
/*获取角色列表*/
public List<Role> getRoleList(Connection connection) throws Exception;
}

2.编写接口RoleDao实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.noob.dao.role;

import com.noob.dao.BaseDao;
import com.noob.pojo.Role;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class RoleDaoImpl implements RoleDao{
public List<Role> getRoleList(Connection connection) throws Exception {

PreparedStatement pstm = null;
ResultSet rs = null;
ArrayList<Role> rolelist = new ArrayList<Role>();
if(connection!=null){
String sql = "select * from smbms_role";
Object[] params = {};
rs = BaseDao.excute(connection,pstm,rs,sql,params);

while(rs.next()){
Role _role = new Role();
_role.setId(rs.getInt("id"));
_role.setRoleCode(rs.getString("roleCode"));
_role.setRoleName(rs.getString("roleName"));
rolelist.add(_role);
}
BaseDao.closeResource(null,pstm,rs);
}
return rolelist;
}
}

3.编写RoleService接口

1
2
3
4
5
6
7
8
9
10
package com.noob.service.role;

import com.noob.pojo.Role;

import java.util.List;

public interface RoleService {
/*获取角色列表*/
public List<Role> getRoleList();
}

4.编写RoleService接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.noob.service.role;

import com.noob.dao.BaseDao;
import com.noob.dao.role.RoleDao;
import com.noob.dao.role.RoleDaoImpl;
import com.noob.pojo.Role;
import org.junit.Test;

import java.sql.Connection;
import java.util.List;

public class RoleServiceImpl implements RoleService{
/*引入Dao*/
private RoleDao roleDao;
public RoleServiceImpl(){
roleDao = new RoleDaoImpl();
}
public List<Role> getRoleList() {
Connection connection = null;
List<Role> roleList = null;

try {
connection = BaseDao.getConnection();
roleList = roleDao.getRoleList(connection);
} catch (Exception e) {
e.printStackTrace();
}finally {
BaseDao.closeResource(connection,null,null);
}
return roleList;

}
@Test
public void test(){
RoleServiceImpl roleService = new RoleServiceImpl();
List<Role> roleList = roleService.getRoleList();
for(Role role :roleList){
System.out.println(role.getRoleName());
}
}
}

5.编写Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package com.noob.servlet;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.noob.pojo.Role;
import com.noob.pojo.User;
import com.noob.service.role.RoleServiceImpl;
import com.noob.service.user.UserService;
import com.noob.service.user.UserServiceImpl;
import com.noob.util.Constants;
import com.noob.util.PageSupport;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if(method.equals("savepwd")&&method!=null){
this.updatePwd(req,resp);
} else if(method.equals("pwdmodify")&&method!=null){
this.pwdModify(req,resp);
}else if(method.equals("query")&&method!=null){
this.query(req,resp);
}
}

private void query(HttpServletRequest req, HttpServletResponse resp) {
/*查询用户列表*/
/*获取前端数据*/
String queryUserName = req.getParameter("queryname");
String temp = req.getParameter("queryUserRole");
String pageIndex = req.getParameter("pageIndex");
int queryUserRole = 0 ;
/*前端数据进行处理*/
//获取用户列表
UserServiceImpl userService = new UserServiceImpl();
List<User> userList = null;

//第一次走该请求一定是第一页且页面大小固定的;
int pageSize = 5;
int currentPageNo = 1;

if(queryUserName==null){
queryUserName="";
}
if(temp!=null&&!temp.equals("")){
queryUserRole =Integer.parseInt(temp); /*给查询赋值 0 1 2 3*/
}
if(pageIndex!=null){
currentPageNo = Integer.parseInt(pageIndex);
}
/*获取用户的总数*/

int totalCount = userService.getUserCount(queryUserName,queryUserRole);
//总页数支持
PageSupport pageSupport = new PageSupport();
pageSupport.setCurrentPageNo(currentPageNo);
pageSupport.setPageSize(pageSize);
pageSupport.setTotalCount(totalCount);
/*int totalPageCount = pageSupport.getTotalPageCount();*/
int totalPageCount = ((int)(totalCount/pageSize))+1;

/*
控制首页和尾页
如果页面小于1显示第一页的东西
*/
if (currentPageNo<1){
currentPageNo = 1;
}else if (currentPageNo>totalPageCount){ /*当前页面大于了最后一页*/
currentPageNo = totalPageCount;
}

/*
前端获取用户列表
userlist.jsp
<c:forEach var="user" items="${userList }" varStatus="status">
*/
userList = userService.getUserList(queryUserName, queryUserRole, currentPageNo, pageSize);
req.setAttribute("userList",userList);

RoleServiceImpl roleService = new RoleServiceImpl();
List<Role> roleList = roleService.getRoleList();

req.setAttribute("roleList",roleList);
req.setAttribute("totalCount",totalCount);
req.setAttribute("currentPageNo",currentPageNo);
req.setAttribute("totalPageCount",totalPageCount);
/*前端页面保持查询参数*/
req.setAttribute("queryUserName",queryUserName);
req.setAttribute("queryUserRole",queryUserRole);


/*返回前端*/
try {
req.getRequestDispatcher("userlist.jsp").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public void updatePwd(HttpServletRequest req,HttpServletResponse resp){
/*从Session里面获取ID*/
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String newpassword = req.getParameter("newpassword");
boolean flag = false;
if(o!=null && !StringUtils.isNullOrEmpty(newpassword)){
UserService userService = new UserServiceImpl();
flag = userService.updatePwd(((User)o).getId(),newpassword);
if(flag){
req.setAttribute("message","修改密码成功,请使用新密码重新登录");
/*密码修改成功,移除当前Session*/
req.getSession().removeAttribute(Constants.USER_SESSION);

}else{
req.setAttribute("message","修改密码失败");
}

}else{
req.setAttribute("message","新密码存在问题");
}
try {
req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//验证旧密码 session中有用户密码
public void pwdModify(HttpServletRequest req,HttpServletResponse resp){
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String oldpassword = req.getParameter("oldpassword");


Map<String,String> resultMap = new HashMap<String,String>();
if(o==null){ /*session失效*/
resultMap.put("result","sessionerror");
}else if(StringUtils.isNullOrEmpty(oldpassword)) { /*输入旧密码为空*/
resultMap.put("result","error");
}else{
String userPassword = ((User)o).getUserPassword(); //Session中用户的密码
if(oldpassword.equals(userPassword)){
resultMap.put("result","true");
}else{
resultMap.put("result","false");
}

}
/*JSONArray 阿里巴巴的JSON工具类
resultMap = ["result","sessionerror","result","error"]
Json格式 = {key:value}
*/
try{
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
/*
Ajax
JSONArray 阿里巴巴的JSON工具类, 转换格式 fastjson
resultMap = ["result","sessionerror","result","error"]
Json格式 = {key:value}
*/
writer.write(JSONArray.toJSONString(resultMap));
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}

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

前端乱码:js文件编码改为UTF-8-Bom即可。


文件上传

1.浏览器在上传的过程中将文件以流的形式提交到服务器端。

2.环境依赖:

3.在项目下新建lib文件夹(将jar加入)->Add as Libaray(不使用maven管理依赖),也可在Project Structure下Libraries下添加

4.文件上传:

  • 上传文件需要放在外界无法访问的目录下,如WEB-INF目录
  • 需要为上传文件建立一个唯一的文件名(防止文件覆盖)
  • 限制上传文件的最大值
  • 限制上传文件的类型并判断后缀名是否合法

5.ServletFileUpload负责处理上传的文件数据,并将表单中输入封装为FileItem对象。

  • 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。
  • 需要在进行解析前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory方法设置ServletFileUpload对象的fileItemFactory属性。

1.ServletFileUpload类

ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装在一个FileItem对象中. 使用其parseRequest(HttpServletRequest)方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。

  • FileServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package com.noob.servlet;

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.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*判断普通表单还是带文件表单*/
if(!ServletFileUpload.isMultipartContent(req)){
return; /*终止方法运行,即是普通表单*/

}
/*创建上传文件的保存目录,为了安全建议在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/upload");
File tmpFile = new File(tmpPath);
if(!tmpFile.exists()){
tmpFile.mkdir(); /*创建文件夹*/
}
/*
1.处理上传的文件一般需要通过流来获取,通过request.getInputstream(),原生态文件上传流获取,较为麻烦
2.推荐使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件;
*/
try {
/*1.创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小*/
DiskFileItemFactory factory = gteDiskFileItemFactory(tmpFile);
/*2.获取ServletFileUpload*/
ServletFileUpload upload = getServletFileUpload(factory);
/*3.处理上传文件*/
String msg = uploadParseRequest(upload,req,uploadPath);
/*Servlet请求转发消息*/
req.setAttribute("msg",msg);
req.getRequestDispatcher("/info.jsp").forward(req,resp);
}catch (FileUploadException e){

e.printStackTrace();
}

}

public static DiskFileItemFactory gteDiskFileItemFactory(File file){

/*1.创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小*/
DiskFileItemFactory factory = new DiskFileItemFactory();

/*通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;*/
factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M
factory.setRepository(file);
return factory;

}

public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){

/*2.获取ServletFileUpload*/
ServletFileUpload upload = new ServletFileUpload(factory);
/*监听文件上传进度*/
upload.setProgressListener(new ProgressListener() {

public void update(long pBytesRead, long lpContentLenght, int i) {

/*
pBytesRead:已读取到的文件大小
pContentLenght:文件大小
*/
System.out.println("总大小:"+lpContentLenght+"已上传:"+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 IOException, FileUploadException {

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;
}

/*截取字符串,获得上传的文件名*/
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
/*截取字符串,获得文件的后缀名*/
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
/*
如果文件后缀名fileExtName不是我们所需要的
return不处理,同时提示文件类型不对
*/

/*
使用UUID(唯一识别的通用码),保证文件名唯一
UUID.randomUUID 随机生一个唯一识别的通用码
*/
String uuidPath= UUID.randomUUID().toString();
System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"】");
String uuidFileName = UUID.randomUUID().toString();

/*获得文件上传的流*/
InputStream inputStream = fileItem.getInputStream();
/*创建一个文件输出流*/
FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+ fileExtName);
/*创建一个缓冲区*/
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;
}



@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
  • index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<!--
get:上传文件大小有限制
post:上传文件大小无限制
${pageContext.request.contextPath} :项目根目录
-->
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
上传用户: <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>
  • info.jsp
1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>

${msg}

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
├─out
│ ├─artifacts
│ │ └─FileWeb_war_exploded
│ │ │ index.jsp
│ │ │ info.jsp
│ │ │
│ │ └─WEB-INF
│ │ │ web.xml
│ │ │
│ │ ├─classes
│ │ │ └─com
│ │ │ └─noob
│ │ │ └─servlet
│ │ │ FileServlet$1.class
│ │ │ FileServlet.class
│ │ │
│ │ ├─lib
│ │ │ commons-fileupload-1.4.jar
│ │ │ commons-io-2.11.0.jar
│ │ │ jakarta.servlet-api-4.0.4.jar
│ │ │
│ │ └─upload
│ │ 20d57fc1-dd95-4067-a5d3-9d6d11325d58.jpg
│ │ b06e2c44-b3fb-404f-90c4-21b68ef86db3.m4a
│ │
│ └─production
│ └─FileWeb
│ └─com
│ └─noob
│ └─servlet
FileServlet$1.class
FileServlet.class
1
2
3
4
5
6
7
8
<servlet>
<servlet-name>FileServlet</servlet-name>
<servlet-class>com.noob.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>

邮件发送

1.发送邮件:SMTP协议

接受邮件:POP3协议

2.环境依赖 Tomcat9:

3.核心类:

  • Session对象:定义整个程序所需环境信息,比如主机名、端口号、采用的邮件发送和接受协议
  • Transport对象:用于发送邮件
  • Message对象:电子邮件
  • Store对象:用来接受文件

4.MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

非ASCII字符文本;非文本格式附件(二进制、声音、图像等);由多部分(multiple parts)组成的消息体;包含非ASCII字符的头信息(Header information)。


QQ邮箱

网页端登录QQ邮箱,设置->账号->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务->开启POP3/SMTP服务->得到授权码

发送普通邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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 MailDemo1 {
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"); //需要验证用户密码
/*prop.setProperty("mail.smtp.port", "587"); 设置端口*/
prop.setProperty("mail.smtp.starttls.required", "true");
prop.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");

/*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() {
/*发件人邮箱以及授权码 QQ特有*/
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("yourmail@qq.com", "授权码");
}
});
/*开启session的debug模式,这样可以查看到程序发送Email的运行状态*/
session.setDebug(true);
/*2.通过session得到transport对象*/
Transport ts = session.getTransport();
/*3.使用邮箱的用户名和授权码连上邮件服务器*/
ts.connect("smtp.qq.com", "yourmail@qq.com", "授权码");
/*4.
创建邮件:写文件
需要传递session
附件邮件*/
MimeMessage message = new MimeMessage(session);
/*指明邮件的发件人*/
message.setFrom(new InternetAddress("yourmail@qq.com"));
/*指明邮件的收件人*/
message.setRecipient(Message.RecipientType.TO, new InternetAddress("yourmail@qq.com"));
/*邮件标题*/
message.setSubject("Hello");
/*邮件的文本内容*/
message.setContent("<h1 style='color:red'>:( :p :)</h1>", "text/html;charset=UTF-8");
/*5.发送邮件*/
ts.sendMessage(message, message.getAllRecipients());
/*6.关闭连接*/
ts.close();
}
}

1.javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

  • 法一:

进入Java安装目录->jre\lib\security\java.security将其中

1
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \

删除SSLv3, TLSv1, TLSv1.1

1
jdk.tls.disabledAlgorithms=RC4, DES, MD5withRSA, \

重启项目即可

  • 法二:添加代码,明确指出协议即可
1
2
prop.setProperty("mail.smtp.starttls.required", "true");
prop.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");

发送图片

MimeBadyPart类:MIME消息,与MimeMessage类一样都是从Part接口继承过来。

MimeMultipart类:抽象类Multipart的实现子类,用来组合多个MIME消息,一个MimeMultipart对象可以包含多个代表MIME消息的MimeBadyPart对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.noob;

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 MailDemo2 {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();

MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);

prop.put("mail.host", "smtp.qq.com");
prop.put("mail.transport.protocol", "smtp");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.required", "true");
prop.put("mail.smtp.ssl.protocols", "TLSv1.2");
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);

Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("yourmail@qq.com", "授权码");
}
});
session.setDebug(true);

Transport ts = session.getTransport();
ts.connect("smtp.qq.com", "yourmail@qq.com", "授权码");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("yourmail@qq.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("yourmail@qq.com"));
message.setSubject("Hello Image");

/*准备图片数据*/
MimeBodyPart mimeBodyPart = new MimeBodyPart();
/*图片需要经过数据化的处理*/
DataHandler dataHandler = new DataHandler(new FileDataSource("图片路径"));
/*在part中放入处理过图片的数据*/
mimeBodyPart.setDataHandler(dataHandler);
/*设置part的Id名字*/
mimeBodyPart.setContentID("image.png");

/*准备文本数据*/
MimeBodyPart mimeBodyPart1 = new MimeBodyPart();
mimeBodyPart1.setContent("这是一张正文<img src='cid:image.png'>","text/html;charset=UTF-8");

/*描述数据关系*/
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(mimeBodyPart);
mimeMultipart.addBodyPart(mimeBodyPart1);
mimeMultipart.setSubType("related");

/*设置到消息中,并保存修改*/
message.setContent(mimeMultipart);
message.saveChanges();


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

}
}

发送附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package com.noob;

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 MailDemo2 {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();

MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);

prop.put("mail.host", "smtp.qq.com");
prop.put("mail.transport.protocol", "smtp");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.required", "true");
prop.put("mail.smtp.ssl.protocols", "TLSv1.2");
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);

Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("yourmail.com", "授权码");
}
});
session.setDebug(true);

Transport ts = session.getTransport();
ts.connect("smtp.qq.com", "yourmail.com", "授权码");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("yourmail.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("yourmail.com"));
message.setSubject("Hello Image");

/*准备图片数据*/
MimeBodyPart mimeBodyPart = new MimeBodyPart();
/*图片需要经过数据化的处理*/
DataHandler dataHandler = new DataHandler(new FileDataSource("图片路径"));
/*在part中放入处理过图片的数据*/
mimeBodyPart.setDataHandler(dataHandler);
/*设置part的Id名字*/
mimeBodyPart.setContentID("p1.jpg");

/*准备文本数据*/
MimeBodyPart mimeBodyPart1 = new MimeBodyPart();
mimeBodyPart1.setContent("这是一张正文<img src='cid:p1.jpg'>","text/html;charset=UTF-8");

/*准备附件数据*/
MimeBodyPart mimeBodyPart2 = new MimeBodyPart();
mimeBodyPart2.setDataHandler(new DataHandler(new FileDataSource("附件路径")));
mimeBodyPart2.setFileName("hello.txt");

/*拼装邮件正文内容*/
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(mimeBodyPart);
mimeMultipart.addBodyPart(mimeBodyPart1);
mimeMultipart.setSubType("related");

/*将拼接的正文内容设置为主体*/
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(mimeMultipart);

/*拼接附件*/
MimeMultipart allFile = new MimeMultipart();
allFile.addBodyPart(mimeBodyPart2);
allFile.addBodyPart(contentText);
allFile.setSubType("mixed");

/*设置到消息中,并保存修改*/
message.setContent(allFile);
message.saveChanges();

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

}
}

注册通知邮件

1.前端数据封装成实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.noob.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 + '\'' +
'}';
}
}

2.编写Servlet类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import com.noob.pojo.User;

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 {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*接受前端数据,封装成对象*/
String username=req.getParameter("username");
String password=req.getParameter("pwd");
String email=req.getParameter("email");


User user=new User(username,password,email);
System.out.println(user.toString());
Sendmail send=new Sendmail(user);
send.start();
System.out.println("success");
req.setAttribute("message","邮件已发送,请注意查收");
req.getRequestDispatcher("info.jsp").forward(req,resp);

}

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

3.编写发送邮件类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import com.noob.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="yourmail@qq.com";

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

private User user;

public Sendmail(User user){
this.user=user;
}
@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");
prop.put("mail.smtp.starttls.required", "true");
prop.put("mail.smtp.ssl.protocols", "TLSv1.2");

MailSSLSocketFactory sf=new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);

Session session= Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(from,"授权码");
}
});
session.setDebug(true);
Transport ts=session.getTransport();
ts.connect(host,from,"授权码");
MimeMessage message=new MimeMessage(session);
message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail()));
message.setSubject("注册通知");

message.setContent("恭喜你("+user.getUsername()+")成功注册!"+"密码:"+user.getPassword()
,"text/html;charset=UTF-8");

ts.sendMessage(message,message.getAllRecipients());
ts.close();
}catch (Exception e){
System.out.println(e);
}

}
}

4.编写前端文件

  • index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@page contentType="text/html;charset=utf-8" language="java" %>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>
<html>
<body>
<h2>Hello World!</h2>
<form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">
用户名:<input type="text" name="username">
密码:<input type="text" name="pwd">
邮箱:<input type="text" name="email">
<input type="submit" value="注册">

</form>
</body>
</html>
  • info.jsp
1
2
3
4
5
6
7
8
9
10
11
12
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>
网站提示:
</h1>
${message}
</body>
</html>

5.配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!--pom.xml-->
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>

<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
<!--web.xml-->
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.noob.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/RegisterServlet.do</url-pattern>
</servlet-mapping>