简介

web开发:

  • web,网页的意思,www.baidu.com·
  • 静态web
    • html,sss
    • 提供给所有人看的数据始终不会发生变化!
  • 动态web
    • 淘宝,几乎是所有的网站;
    • 提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同!
    • 技术栈:Servlet/JSP,ASP,PHP

web应用程序web应用程序

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

  • a.html、b.html.….多个web资源,这些web资源可以被外界访问,对外界提供服务;
  • 你们能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。
  • URL
  • 这个统一的web资源会被放在同一个文件夹下,web应用程序>Tomcat:服务器
  • 一个web应用由多部分组成(静态web,动态web)
    • html,css,js
    • jsp,servlet
    • Java程序
    • jar包
    • 配置文件(Properties)

Web酸用程序编写完毕后,若想提供给外界访问;需要一个服务蔬来统一管理

静态web

  • *.htm, *.html这些都是网员的后坠 、如果服务器上一直存在这些东四,我们就可以直接进行读取、需要网络;
  • 静态web存在的缺点
    • Web页面无法动态更新,所有用户看到都是同一个页面

      • 轮播图,点击特效:伪动态
      • JavaScript[实际开发中,它用的最多]
      • VBScript
    • 它无法和数据库交互(数据无法持久化,用户无法交互)

动态web

页面会动态展示,“web页面的展示效果因人而异”

缺点:

  • 加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布;

    • 停机维护

优点:

  • Web页面可以动态更新,所有用户看到都不是同一个页面

  • 它可以与数据库交互(数据持久化:注册,商品信息,用户信息………)

web服务器

技术讲解

ASP:

  • 微软:国内最早流行的就是ASP;
  • ·在HTML中嵌入了VB的脚本,ASP+COM;
  • ·在ASP开发中,基本一个页面都有几干行的业务代码,页面极其换乱
  • ·维护成本高!
  • C#
  • IIS

php:

  • PHP开发速度很快,功能很强大,跨平台,代码很简单(70%,WP)
  • ·无法承载大访问量的情况(局限性)

jSP/Servlet:
B/S;浏览和服务器C/S:客户端和服务器

  • sun公司主推的B/S架构
  • 基于Java语言的(所有的大公司,或者一些开源的组件,都是用Java写的)
  • 可以承载三高问题带来的影响;(高并发,高可用,高性能)
  • 语法像ASP,ASP->JSP,加强市场强度;

web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;
lIS
微软的;ASP.,Windows中自带的

Tomcat


面向百度编程:
Tomcat是Apache 软件基金会(Apache Software Foundation)的jakarta项目中的一个核心项目,最新的Servlet 和ISP 规范总是能在Tomcat中得到体现,因为Tomcat 技术先进、性能稳定,而且免费,因而深受lava爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。

Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个Java初学web的人来说,它是最佳的选择

Tomcat 实际上运行JSP页面和Serlet。Tomcat最新版易9.0

Tomcat

安装tomcat tomcat

官网:http://tomcat.apache.org/


Tomcat启动和配置

文件夹作用:


访问测试:http://localhost:8080/
可能遇到的问题:

  1. Java环境变量没有配置
  2. 闪退问题:需要配置兼容性
  3. 乱码问题:配置文件中设置

可以修改 conf/logging.properties 中的 java.util.logging.ConsoleHandler.encoding = GBK 解决乱码问题

配置

可以配置启动的端口号

  • tomcat的默认端口号为:8080
  • mysql:3306
  • http:80
  • https:443
<Connector port="8081" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />

可以配置主机的名称

  • 默认的主机名为:localhost->127.0.0.1
  • 默认网站应用存放的位置为:webapps
  <Host name="www.qinjiang.com"  appBase="webapps"unpackWARs="true" autoDeploy="true">

高难度面试题:
请你谈谈网站是如何进行访问的!

  1. 输入一个域名;回车

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

    1. 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问

       127.0.0.1 www.qinjiang.com
      
  3. 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;

4.可以配置一下环境变量(可选性)

csdn免登陆复制技巧

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4KQqNSEo-1609316574047)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228001630186.png)]

发布一个web网站

不会就先模仿

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

网站结构

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

HTTP协议:面试
Maven:构建工具

  • Maven安装包

Servlet入门

  • HelloWorld!
  • Servlet配置 ·原理

Http

什么是HTTP

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

  • 文本:html,字符串, …
  • 超文本:图片,音乐,视频,定位,地图.……
  • 端口:80

Https:安全的

两个时代

  • http1.0

    • HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
  • http2.0
    • HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源。

Http请求

  • 客户端–发请求(Request)–服务器

百度:

Request URL:https://www.baidu.com/   请求地址
Request Method:GET    get方法/post方法
Status Code:200 OK    状态码:200
Remote(远程) Address:14.215.177.39:443Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9    语言
Cache-Control:max-age=0
Connection:keep-alive

请求行

  • 请求行中的请求方式:GET
  • 请求方式:Get,Post,HEAD,DELETE,PUT,TRACT.…
    • get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
    • post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。

消息头

Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.

Http响应

  • 服务器–响应…….客户端

百度:

Cache-Control:private    缓存控制
Connection:Keep-Alive    连接
Content-Encoding:gzip    编码
Content-Type:text/html   类型

响应体

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

响应状态码

200:请求响应成功200
3xx:请求重定向·重定向:你重新到我给你新位置去;
4xx:找不到资源404·资源不存在;
5xx:服务器代码错误 500 502:网关错误

常见面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?

Maven

为什么要学习这个技术?

  1. 在Javaweb开发中,需要使用大量的jar包,我们手动去导入;
  2. 如何能够让一个东西自动帮我导入和配置这个jar包。

由此,Maven诞生了!

Maven项目架构管理工具

我们目前用来就是方便导入jar包的!
Maven的核心思想:约定大于配置

  • 有约束,不要去违反。

Maven会规定好你该如何去编写我们Java代码,必须要按照这个规范来;

下载安装Maven

官网:https://maven.apache.org/

下载完成后,解压即可;
电脑上的所有环境都放在一个文件夹下,方便管理;

配置环境变量

在我们的系统环境变量中配置如下配置:

  • M2_HOME maven目录下的bin目录
  • MAVEN_HOME maven的目录
  • 在系统的path中配置%MAVEN_HOME%\bin

    测试Maven是否安装成功,保证必须配置完毕!

阿里云镜像

  • 镜像:mirrors
  • 作用:加速我们的下载
  • 国内建议使用阿里云的镜像
<mirror><id>nexus-aliyun</id>  <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>  <name>Nexus aliyun</name>  <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

D:Enmvironment\apache-maven-3.6.2\conf\ettings.xml
(狂神老师配置源和仓库的文件位置)

本地仓库

在本地的仓库,远程仓库; 建立一个本地仓库:localRepository

<localRepository>D:\Environment\apache-maven-3.6.2\maven-repo</localRepository>

在IDEA中使用Maven

创建一个MavenWeb项目

  1. 等待项目初始化完毕

  2. 观察maven仓库中多了什么东西?

  3. IDEA中的Maven设置

    注意:IDEA项目创建成功后,看一眼Maven的配置

  4. 到这里,Maven在IDEA中的配置和使用就OK了!

创建一个普通的Maven项目

这个只有在Web应用下才会有!

标记文件夹功能

配置Tomcat

解决警告问题

必须要的配置:为什么会有这个问题:我们访问一个网站,需要指定一个文件夹名字;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4fcvZ8N-1609316574059)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228122448987.png)]

pom文件

pom.xml 是Maven的核心配置文件

<?xml version="1.0" encoding="UTF-8"?><!--Maven版本和头文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!--这里就是我们刚才配置的GAV--><groupId>com.kuang</groupId><artifactId>javaweb-01-maven</artifactId><version>1.0-SNAPSHOT</version><!--Package:项目的打包方式jar:java应用war:JavaWeb应用--><packaging>war</packaging><!--配置--><properties><!--项目的默认构建编码--><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!--编码版本--><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><!--项目依赖--><dependencies><!--具体依赖的jar包配置文件--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version></dependency></dependencies><!--项目构建用的东西--><build><finalName>javaweb-01-maven</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>

maven约定大于配置

我们之后可以能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:

<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources>
</build>

IDEA操作

解决遇到的问题

  1. Maven 3.6.2

    解决方法:降级为3.6.1

  2. Tomcat闪退

  3. IDEA中每次都要重复配置Maven
    在IDEA中的全局默认配置中去配置

  4. Maven项目中Tomcat无法配置

  5. maven默认web项目中的web.xml版本问题

  6. 替换为webapp4.0版本和tomcat一致

    <?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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>
    
  7. Maven仓库的使用

    地址:https://mvnrepository.com/

设置响应编码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rcrIQ7YZ-1609316574062)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228135608735.png)]

Servlet

Servlet简介

  • Servlet就是sun公司开发动态web的一门技术
  • Sun在这些APi中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
    • 编写一个类,实现Serlet接口
    • 把开发好java类部署到web服务器中。

把实现了Servlet接口的Java程序叫做,Servlet

HelloServlet

Serlvet接口Sun公司有两个默认的实现类:HttpServlet,GenericServled

HelloServlet

  1. 构建一个普通的Maven项目,删掉里面的sc目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就是Maven主工程;
  2. 关于Maven父子工程的理解;
    父项目中会有
      <modules><module>servlet-01</module></modules>

子项目会有

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

父项目中的java子项目可以直接使用

son extends father
  1. Maven环境优化

    1. 修改web.xml为最新的
    2. 将maven的结构搭建完整
<?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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>

2.编写一个Servlet程序

  1. 编写一个普通类
  2. 实现Servlet接口,这里我们直接继承HttpServlet
     public class HelloServlet extends HttpServlet {//由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletOutputStream outputStream = resp.getOutputStream();PrintWriter writer = resp.getWriter(); //响应流writer.print("Hello,Serlvet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}}

3.编写Servlet的映射

为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需
要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;

      <!--注册Servlet--><servlet><servlet-name>hello</servlet-name><servlet-class>com.kuang.servlet.HelloServlet</servlet-class></servlet><!--Servlet的请求路径--><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping>
  1. 配置Tomcat
    注意:配置项目发布的路径就可以了

  2. 启动测试,OK!

项目的一些描述信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OY7ikb0B-1609316574076)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228144307374.png)]

Servlet原理

Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:

Mapping问题

一个Servlet可以指定一个映射路径
.

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

一个servlet可以指定多个映射路径

      <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello2</url-pattern></servlet-mapping><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello3</url-pattern></servlet-mapping><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello4</url-pattern></servlet-mapping><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello5</url-pattern></servlet-mapping>

一个servlet可以指定通用映射路径

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

默认请求路径

会把首页干掉

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

指定一些后缀或者前缀等等…

  <!--可以自定义后缀实现请求映射注意点,*前面不能加项目映射的路径hello/sajdlkajda.qinjiang--><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>*.qinjiang</url-pattern></servlet-mapping>

优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;

  <!--404--><servlet><servlet-name>error</servlet-name><servlet-class>com.kuang.servlet.ErrorServlet</servlet-class></servlet><servlet-mapping><servlet-name>error</servlet-name><url-pattern>/*</url-pattern></servlet-mapping>

ServletContext

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

共享数据

我在这个Servlet中保存的数据,可以在另外一个servlet中拿到;

public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//this.getInitParameter()   初始化参数//this.getServletConfig()   Servlet配置//this.getServletContext()  Servlet上下文ServletContext context = this.getServletContext();String username = "秦疆"; //数据context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username}}public class GetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String username = (String) context.getAttribute("username");resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().print("名字"+username);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}<servlet><servlet-name>hello</servlet-name><servlet-class>com.kuang.servlet.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping><servlet><servlet-name>getc</servlet-name><servlet-class>com.kuang.servlet.GetServlet</servlet-class></servlet><servlet-mapping><servlet-name>getc</servlet-name><url-pattern>/getc</url-pattern></servlet-mapping>

测试访问结果;

获取初始化参数

    <!--配置一些web应用初始化参数--><context-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/mybatis</param-value></context-param>
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 doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();System.out.println("进入了ServletDemo04");//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径//requestDispatcher.forward(req,resp); //调用forward实现请求转发;context.getRequestDispatcher("/gp").forward(req,resp);
}

读取资源文件classpath

Properties

  • 在java目录下新建properties
  • 在resources目录下新建properties

发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U40JTNEB-1609316574078)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228164917411.png)]

思路:需要一个文件流

username=root12312
password=zxczxczxc

public class ServletDemo05 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/aa.properties");Properties prop = new Properties();prop.load(is);String user = prop.getProperty("username");String pwd = prop.getProperty("password");resp.getWriter().print(user+":"+pwd);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

访问测试即可ok;

HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest
对象,代表响应的一个HttpServletResponse;
  • 如果要获取客户端请求过来的参数:找HttpServletRequest

  • 如果要给客户端响应一些信息:找HttpServletResponse

    1、简单分类

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

 servletOutputstream getOutputstream() throws IOException;Printwriter getwriter() throws IOException;

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

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

响应的状态码

下载文件

  1. 向浏览器输出消息
  2. 下载文件
    1. 要获取下载文件的路径
    2. 下载的文件名是啥?
    3. 设置想办法让浏览器能够支持下载我们需要的东西URLEncoder.encode(fileName,“UTF-8”)
    4. 获取下载文件的输入流
    5. 创建缓冲区
    6. 获取OutputStream对象
    7. 将FileOutputStream流写入到bufer缓冲区
    8. 使用OutputStream将缓冲区中的数据输出到客户端!
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 要获取下载文件的路径String realPath = "F:\\班级管理\\西开【19525】\\2、代码\\JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\秦疆.png";System.out.println("下载文件的路径:"+realPath);// 2. 下载的文件名是啥?String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);// 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));// 4. 获取下载文件的输入流FileInputStream in = new FileInputStream(realPath);// 5. 创建缓冲区int len = 0;byte[] buffer = new byte[1024];// 6. 获取OutputStream对象ServletOutputStream out = resp.getOutputStream();// 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端!while ((len=in.read(buffer))>0){out.write(buffer,0,len);}in.close();out.close();
}

验证码功能

验证怎么来的?

  • 前端实现
  • 后端实现,需要用到Java的图片类,生产一个图片
package com.kuang.servlet;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;public class ImageServlet extends HttpServlet {@Overrideprotected 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,20);//给图片写数据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();for (int i = 0; i < 7-num.length() ; i++) {sb.append("0");}num = sb.toString() + num;return num;}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}<servlet><servlet-name>ImageServlet</servlet-name><servlet-class>com.kuang.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>Imageservlet</servlet-name><url-pattern>/img</url-pattern>
</servlet-mapping>

重定向


常见场景:

  • 用户登录
 void sendRedirect(String var1) throws IOException;

测试:

@override
protected void doGet(HttpservletRequest req, HttpservletResponse resp) throws ServletException, IOException {resp. sendRedirect("/r/img");//重定向/*resp. setHeader("Location","/r/img");resp. setstatus (302);*
}



index.jsp

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

RequestTest.java

public class RequestTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//处理方求String username = req.getParameter( "username");String password  req.getParameter(  "password");System.out.println(username+":"+password);resp.sendRedirect("/r/success.jsp");
}
}

重定向页面success.jsp

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

web.xml配置

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

导入依赖的jar包

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

HttpServletRequest

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

获取参数,请求转发


自己创建类,且需要继承HttpServlet类

@Override
protected void doGet(HttpservletRequest req. HttpservletResponse resp) throws ServletException, IOException {req. setcharacterEncoding("utf-8");resp.setcharacterEncoding("utf-8");String username = req.getParameter("username");String password = req.getParameter("password");String[] hobbys = req.getParameterValues("hobbys");System.out.println("==========");//后台接收中文乱码问题System. out.println(username);System. out.println(password);System. out.println(Arrays.tostring(hobbys));System. out.println("============");System. out.println(req.getContextPath());//通过请求转发//这里的/代表当前的web应用req.getRequestDispatcher("/success.jsp").forward(req,resp);
}

Cookie、Session

会话

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话;

有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话;

你能怎么证明你是西开的学生?

你 西开

  1. 发票 西开给你发票
  2. 学校登记 西开标记你来过了

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

客户端 服务端

  1. 服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie
  2. 服务器登记你来过了,下次你来的时候我来匹配你; seesion

保存会话的两种技术

cookie

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

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息? 我们可以把信息或者数据放在Session中!

常见常见:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!

Cookie

  1. 从请求中拿到cookie信息
  2. 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie

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

一个网站cookie是否存在上限!聊聊细节问题

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

删除Cookie;

  • 不设置有效期,关闭浏览器, 自动失效;
  • 设置有效期时间为 0 ;

编码解码:

URLEncoder.encode("秦疆","utf-8")
URLDecoder.decode(cookie.getValue(),"UTF-8")
package com.kuang.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.concurrent.CopyOnWriteArrayList;public class CookieDemo01 extends HttpServlet  {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");PrintWriter out = resp.getWriter();Cookie[] cookies = req.getCookies();if(cookies!=null){out.write("nishangyici");for (int i = 0; i < cookies.length; i++) {Cookie cookie = cookies[i];if(cookie.getName().equals("lastLoginTime")){long lastLoginTime = Long.parseLong(cookie.getValue());Date date = new Date(lastLoginTime);out.write(date.toLocaleString());}}}else{out.write("zheshinidiyici");}Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

Session(重点)


什么是Session:

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



Session和cookie的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务器创建;

使用场景:

  • 保存一个登录用户的信息;
  • 购物车信息;
  • 在整个网站中经常会使用的数据,我们将它保存在Session中;

使用Session:

package com.kuang.servlet;import com.kuang.pojo.Person;import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;public class SessionDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("UTF-8");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=utf-8");//得到SessionHttpSession session = req.getSession();//给Session中存东西session.setAttribute("name",new Person("秦疆",1));//获取Session的IDString sessionId = session.getId();//判断Session是不是新创建if (session.isNew()){resp.getWriter().write("session创建成功,ID:"+sessionId);}else {resp.getWriter().write("session以及在服务器中存在了,ID:"+sessionId);}//Session创建的时候做了什么事情;
//        Cookie cookie = new Cookie("JSESSIONID",sessionId);
//        resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
//得到Session
HttpSession session = req.getSession();Person person = (Person) session.getAttribute("name");System.out.println(person.toString());HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销Session
session.invalidate();

会话自动过期:web.xml配置

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4J5UtIGc-1609316574080)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228235433351.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10fKYsof-1609316574081)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228235656922.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Jx56kug-1609316574081)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201228235902022.png)]

JSP原理

思路:JSP到底怎么执行的!

  • 代码层面没有任何问题

  • 服务器内部工作

    tomcat中有一个work目录;

    IDEA中使用Tomcat的会在IDEA的tomcat中生产一个work目录

    我电脑的地址:

    C:\Users\Administrator.IntelliJIdea2018.1\system\tomcat\Unnamed_javaweb-session-cookie\work\Catalina\localhost\ROOT\org\apache\jsp

    发现页面转变成了Java程序!

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!

JSP最终也会被转换成为一个Java类!

全部导入jar

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DU0SNvFS-1609316574085)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229001204098.png)]

JSP 本质上就是一个Servlet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tXkc1m6-1609316574087)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229002724413.png)]

//初始化public void _jspInit() {}
//销毁public void _jspDestroy() {}
//JSPServicepublic void _jspService(.HttpServletRequest request,HttpServletResponse response)
  1. 判断请求

  2. 内置一些对象

    final javax.servlet.jsp.PageContext pageContext;  //页面上下文
    javax.servlet.http.HttpSession session = null;    //session
    final javax.servlet.ServletContext application;   //applicationContext
    final javax.servlet.ServletConfig config;         //config
    javax.servlet.jsp.JspWriter out = null;           //out
    final java.lang.Object page = this;               //page:当前
    HttpServletRequest request                        //请求
    HttpServletResponse response                      //响应
    12345678
    
  3. 输出页面前增加的代码

    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;
    123456789
    
  4. 以上的这些个对象我们可以在JSP页面中直接使用!

在JSP页面中;

只要是 JAVA代码就会原封不动的输出;

如果是HTML代码,就会被转换为:

out.write("<html>\r\n");

这样的格式,输出到前端!

JSP基础语法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G4py4yRQ-1609316574089)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229003705147.png)]

任何语言都有自己的语法,JAVA中有,。 JSP 作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),Java所有语法都支持!

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>TEST02</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><name>TEST02 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><!--Servlet依赖--><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency><!--    JSP依赖--><!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version></dependency><!--jstl表达式依赖--><dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version></dependency><!--standard标签库--><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency></dependencies><build><finalName>TEST02</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>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rVwFF33-1609316574092)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229004718836.png)]

JSP表达式

  <%--JSP表达式作用:用来将程序的输出,输出到客户端<%= 变量或者表达式%>--%><%= new java.util.Date()%>

jsp脚本片段

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

脚本片段的再实现

  <%int x = 10;out.println(x);%><p>这是一个JSP文档</p><%int y = 2;out.println(y);%><hr><%--在代码嵌入HTML元素--%><%for (int i = 0; i < 5; i++) {%><h1>Hello,World  <%=i%> </h1><%}%>

JSP声明

  <%!static {System.out.println("Loading Servlet!");}private int globalVar = 0;public void kuang(){System.out.println("进入了方法Kuang!");}%>

JSP声明:会被编译到JSP生成Java的类中!其他的,就会被生成到_jspService方法中!

在JSP,嵌入Java代码即可!

<%%>
<%=%>
<%!%><%--注释--%>

JSP的注释,不会在客户端显示,HTML就会!

JSP指令

<%@page args.... %>
<%@include file=""%><%--@include会将两个页面合二为一--%><%@include file="common/header.jsp"%>
<h1>网页主体</h1><%@include file="common/footer.jsp"%><hr><%--jSP标签jsp:include:拼接页面,本质还是三个--%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0UOaBRqZ-1609316574095)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229102752359.png)]

9大内置对象

  • PageContext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application 【SerlvetContext】 存东西
  • config 【SerlvetConfig】
  • out
  • page ,不用了解
  • exception
pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","秦疆4号");  //保存的数据只在服务器中有效,从打开服务器到关闭服务器

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!

session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;

JSP标签、JSTL标签、EL表达式

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

EL表达式: ${ }

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象

JSP标签

<%--jsp:include--%><%--
http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
--%><jsp:forward page="/jsptag2.jsp"><jsp:param name="name" value="kuangshen"></jsp:param><jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

JSTL表达式

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

格式化标签

SQL标签

XML 标签

核心标签 (掌握部分)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f58b9NIx-1609316574097)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229112309307.png)]

JSTL标签库使用步骤

  • 引入对应的 taglib
  • 使用其中的方法
  • 在Tomcat 也需要引入 jstl的包,否则会报错:JSTL解析错误

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ntzkg4IC-1609316574099)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229122605140.png)]

c:if

<head><title>Title</title>
</head>
<body><h4>if测试</h4><hr><form action="coreif.jsp" method="get"><%--EL表达式获取表单中的数据${param.参数名}--%><input type="text" name="username" value="${param.username}"><input type="submit" value="登录">
</form><%--判断如果提交的用户名是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin"><c:out value="管理员欢迎您!"/>
</c:if><%--自闭合标签--%>
<c:out value="${isAdmin}"/></body>

c:choose c:when

<body><%--定义一个变量score,值为85--%>
<c:set var="score" value="55"/><c:choose><c:when test="${score>=90}">你的成绩为优秀</c:when><c:when test="${score>=80}">你的成绩为一般</c:when><c:when test="${score>=70}">你的成绩为良好</c:when><c:when test="${score<=60}">你的成绩为不及格</c:when>
</c:choose></body>

c:forEach

<%ArrayList<String> people = new ArrayList<>();people.add(0,"张三");people.add(1,"李四");people.add(2,"王五");people.add(3,"赵六");people.add(4,"田六");request.setAttribute("list",people);
%><%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin,   哪里开始
end,     到哪里
step,   步长
--%>
<c:forEach var="people" items="${list}"><c:out value="${people}"/> <br>
</c:forEach><hr><c:forEach var="people" items="${list}" begin="1" end="3" step="1" ><c:out value="${people}"/> <br>
</c:forEach>

JavaBean

实体类

JavaBean有特定的写法:

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法;

一般用来和数据库的字段做映射 ORM;

ORM :对象关系映射

  • 表—>类
  • 字段–>属性
  • 行记录---->对象

people表

id name age address
1 秦疆1号 3 西安
2 秦疆2号 18 西安
3 秦疆3号 100 西安
class People{private int id;private String name;private int id;private String address;
}class A{new People(1,"秦疆1号",3,"西安");new People(2,"秦疆2号",3,"西安");new People(3,"秦疆3号",3,"西安");
}
  • 过滤器
  • 文件上传
  • 邮件发送
  • JDBC 复习 : 如何使用JDBC , JDBC crud, jdbc 事务

MVC三层架构

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

以前的架构

用户直接访问控制层,控制层就可以直接操作数据库;

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码架构:没有什么是加一层解决不了的!
程序猿调用
↑
JDBC (实现该接口)
↑
Mysql Oracle SqlServer ....(不同厂商)

MVC三层架构

Model

  • 业务处理 :业务逻辑(Service)
  • 数据持久层:CRUD (Dao - 数据持久化对象)

View

  • 展示数据
  • 提供链接发起Servlet请求 (a,form,img…)

Controller (Servlet)

  • 接收用户的请求 :(req:请求参数、Session信息….)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

    登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库
    

Filter (重点)

比如 Shiro安全框架技术就是用Filter来实现的

Filter:过滤器 ,用来过滤网站的数据;

  • 处理中文乱码
  • 登录验证….

(比如用来过滤网上骂人的话,我***我自己 0-0)


Filter开发步骤:

  1. 导包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BKFVbqYl-1609316574102)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229132428680.png)]

<dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version>
</dependency>
<dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version>
</dependency><dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version>
</dependency>
<dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>

2.编写过滤器

  1. 导包不要错 (注意)

实现Filter接口,重写对应的方法即可

  public class CharacterEncodingFilter implements Filter {//初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!public void init(FilterConfig filterConfig) throws ServletException {System.out.println("CharacterEncodingFilter初始化");}//Chain : 链/*1. 过滤中的所有代码,在过滤特定请求的时候都会执行2. 必须要让过滤器继续同行chain.doFilter(request,response);*/public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=UTF-8");System.out.println("CharacterEncodingFilter执行前....");chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!System.out.println("CharacterEncodingFilter执行后....");}//销毁:web服务器关闭的时候,过滤器会销毁public void destroy() {System.out.println("CharacterEncodingFilter销毁");}}

1. 在web.xml中配置 Filter<filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><!--只要是 /servlet的任何请求,会经过这个过滤器--><url-pattern>/servlet/*</url-pattern><!--<url-pattern>/*</url-pattern>--><!-- 别偷懒写个 /* --></filter-mapping>

监听器

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

让开始的时候人数为1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VUr3baNY-1609316574106)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229141531472.png)]

  1. 编写一个监听器

    实现监听器的接口…

    依赖的jar包

    //统计网站在线人数 : 统计session
    public class OnlineCountListener implements HttpSessionListener {//创建session监听: 看你的一举一动//一旦创建Session就会触发一次这个事件!public void sessionCreated(HttpSessionEvent se) {ServletContext ctx = se.getSession().getServletContext();System.out.println(se.getSession().getId());Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");if (onlineCount==null){onlineCount = new Integer(1);}else {int count = onlineCount.intValue();onlineCount = new Integer(count+1);}ctx.setAttribute("OnlineCount",onlineCount);}//销毁session监听//一旦销毁Session就会触发一次这个事件!public void sessionDestroyed(HttpSessionEvent se) {ServletContext ctx = se.getSession().getServletContext();Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");if (onlineCount==null){onlineCount = new Integer(0);}else {int count = onlineCount.intValue();onlineCount = new Integer(count-1);}ctx.setAttribute("OnlineCount",onlineCount);}/*Session销毁:1. 手动销毁  getSession().invalidate();2. 自动销毁*/
    }
  2. web.xml中注册监听器

    <!--注册监听器-->
    <listener><listener-class>com.kuang.listener.OnlineCountListener</listener-class>
    </listener>
    
  3. 看情况是否使用!

<h1>当前有<span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1>

过滤器、监听器常见应用

监听器:GUI编程中经常使用;

public class TestPanel {public static void main(String[] args) {Frame frame = new Frame("中秋节快乐");  //新建一个窗体Panel panel = new Panel(null); //面板frame.setLayout(null); //设置窗体的布局frame.setBounds(300,300,500,500);frame.setBackground(new Color(0,0,255)); //设置背景颜色panel.setBounds(50,50,300,300);panel.setBackground(new Color(0,255,0)); //设置背景颜色frame.add(panel);frame.setVisible(true);//监听事件,监听关闭事件frame.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {super.windowClosing(e);}});}
}

用户登录之后才能进入主页!用户注销后就不能进入主页了!

  1. 用户登录之后,向Sesison中放入用户的数据

  2. 进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;if (request.getSession().getAttribute(Constant.USER_SESSION)==null){response.sendRedirect("/error.jsp");
    }chain.doFilter(request,response);
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5RPdJatm-1609316574109)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229151643266.png)]

JDBC

什么是JDBC : Java连接数据库!

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-conneter-java… 连接驱动(必须要导入)

实验环境搭建

CREATE TABLE users(id INT PRIMARY KEY,`name` VARCHAR(40),`password` VARCHAR(40),email VARCHAR(60),birthday DATE
);INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');SELECT    * FROM users;

导入数据库依赖

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

IDEA中连接数据库:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ir0qBVC9-1609316574113)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229152523631.png)]

JDBC 固定步骤:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement : CRUD
  4. 编写SQL (根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭连接(先开的后关)
public class TestJdbc {public static void main(String[] args) throws ClassNotFoundException, SQLException {//配置信息//useUnicode=true&characterEncoding=utf-8 解决中文乱码String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";String username = "root";String password = "123456";//1.加载驱动Class.forName("com.mysql.jdbc.Driver");//2.连接数据库,代表数据库Connection connection = DriverManager.getConnection(url, username, password);//3.向数据库发送SQL的对象Statement,PreparedStatement : CRUDStatement statement = connection.createStatement();//4.编写SQLString sql = "select * from users";//5.执行查询SQL,返回一个 ResultSet  : 结果集ResultSet rs = statement.executeQuery(sql);while (rs.next()){System.out.println("id="+rs.getObject("id"));System.out.println("name="+rs.getObject("name"));System.out.println("password="+rs.getObject("password"));System.out.println("email="+rs.getObject("email"));System.out.println("birthday="+rs.getObject("birthday"));}//6.关闭连接,释放资源(一定要做) 先开后关rs.close();statement.close();connection.close();}
}

预编译SQL

public class TestJDBC2 {public static void main(String[] args) throws Exception {//配置信息//useUnicode=true&characterEncoding=utf-8 解决中文乱码String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";String username = "root";String password = "123456";//1.加载驱动Class.forName("com.mysql.jdbc.Driver");//2.连接数据库,代表数据库Connection connection = DriverManager.getConnection(url, username, password);//3.编写SQLString sql = "insert into  users(id, name, password, email, birthday) values (?,?,?,?,?);";//4.预编译PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,2);//给第一个占位符? 的值赋值为1;preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;preparedStatement.setString(4,"24736743@qq.com");//给第四个占位符? 的值赋值为1;preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());//5.执行SQLint i = preparedStatement.executeUpdate();if (i>0){System.out.println("插入成功@");}//6.关闭连接,释放资源(一定要做) 先开后关preparedStatement.close();connection.close();}
}

事务

要么都成功,要么都失败!

ACID原则:保证数据的安全。

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务转账:
A:1000
B:1000A(900)   --100-->   B(1100)

Junit单元测试

依赖

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

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!

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

失败的时候是红色:

搭建一个环境

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);@Testpublic void test() {//配置信息//useUnicode=true&characterEncoding=utf-8 解决中文乱码String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";String username = "root";String password = "123456";Connection connection = null;//1.加载驱动try {Class.forName("com.mysql.jdbc.Driver");//2.连接数据库,代表数据库connection = DriverManager.getConnection(url, username, password);//3.通知数据库开启事务,false 开启connection.setAutoCommit(false);String sql = "update account set money = money-100 where name = 'A'";connection.prepareStatement(sql).executeUpdate();//制造错误//int i = 1/0;String sql2 = "update account set money = money+100 where name = 'B'";connection.prepareStatement(sql2).executeUpdate();connection.commit();//以上两条SQL都执行成功了,就提交事务!System.out.println("success");} catch (Exception e) {try {//如果出现异常,就通知数据库回滚事务connection.rollback();} catch (SQLException e1) {e1.printStackTrace();}e.printStackTrace();}finally {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}

SMBMS(超市管理项目)

SMBMS(超市管理项目)

数据库:

项目如何搭建?
考虑是不是用maven? jar包,依赖

搭建项目准备工作

  1. 搭建一个maven web 项目

  2. 配置Tomcat

  3. 测试项目是否能够跑起来

  4. 导入项目中需要的jar包;
    jsp,Servlet,mysql驱动jstl,stand…

  5. 构建项目包结构

  6. 编写实体类
    ROM映射:表-类映射

  7. 编写基础公共类
    1、数据库配置文件(mysql5.xx和8.xx的编写有差异)

    driver=com.mysql.jdbc.Driver
    #在和mysql传递数据的过程中,使用unicode编码格式,并且字符集设置为utf-8
    url=jdbc:mysql://127.0.0.1:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8
    user=root
    password=root
    

2、编写数据库的公共类

package dao;import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;/*** 操作数据库的基类--静态类* @author Administrator**/
public class BaseDao {static{//静态代码块,在类加载的时候执行init();}private static String driver;private static String url;private static String user;private static String password;//初始化连接参数,从配置文件里获得public static void init(){Properties params=new Properties();String configFile = "database.properties";InputStream is=BaseDao.class.getClassLoader().getResourceAsStream(configFile);try {params.load(is);} catch (IOException e) {e.printStackTrace();}driver=params.getProperty("driver");url=params.getProperty("url");user=params.getProperty("user");password=params.getProperty("password");}   /*** 获取数据库连接* @return*/public static Connection getConnection(){Connection connection = null;try {Class.forName(driver);connection = DriverManager.getConnection(url, user, password);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return connection;}/*** 查询操作* @param connection* @param pstm* @param rs* @param sql* @param params* @return*/public static ResultSet execute(Connection connection,PreparedStatement pstm,ResultSet rs,String sql,Object[] params) throws Exception{pstm = connection.prepareStatement(sql);for(int i = 0; i < params.length; i++){pstm.setObject(i+1, params[i]);}rs = pstm.executeQuery();return rs;}/*** 更新操作* @param connection* @param pstm* @param sql* @param params* @return* @throws Exception*/public static int execute(Connection connection,PreparedStatement pstm,String sql,Object[] params) throws Exception{int updateRows = 0;pstm = connection.prepareStatement(sql);for(int i = 0; i < params.length; i++){pstm.setObject(i+1, params[i]);}updateRows = pstm.executeUpdate();return updateRows;}/*** 释放资源* @param connection* @param pstm* @param rs* @return*/public static boolean closeResource(Connection connection,PreparedStatement pstm,ResultSet rs){boolean flag = true;if(rs != null){try {rs.close();rs = null;//GC回收} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();flag = false;}}if(pstm != null){try {pstm.close();pstm = null;//GC回收} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();flag = false;}}if(connection != null){try {connection.close();connection = null;//GC回收} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();flag = false;}}return flag;}}

. 3、编写字符编码过滤器

  1. 导入静态资源

登录功能实现

  1. 编写前端页面
  2. 设置首页
    1.设置欢迎首页
  <welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list>
  1. 编写dao层登录用户登录的接口
public User getLoginUser(Connection connection, String userCode) throws Exception;
  1. 编写dao层接口的实现类
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;import dao.BaseDao;
import pojo.User;public class UserDaoImpl implements UserDao{//持久层只做查询数据库的内容public User getLoginUser(Connection connection, String userCode) throws Exception{//准备三个对象PreparedStatement pstm = null;ResultSet rs = null;User user = null;//判断是否连接成功if(null != connection){String sql = "select * from smbms_user where userCode=?";Object[] params = {userCode};rs = BaseDao.execute(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;}
}
  1. 业务层接口
//用户登录
public User login(String userCode, String userPassword);
  1. 业务层实现类
import java.sql.Connection;//import org.junit.Test;import dao.BaseDao;
import dao.user.UserDao;
import dao.user.UserDaoImpl;
import pojo.User;public class UserServiceImpl implements UserService{//业务层都会调用dao层.所以我们要引入Dao层(重点)//只处理对应业务private UserDao userDao;public UserServiceImpl(){userDao = new UserDaoImpl();}public User login(String userCode,String userPassword) {// TODO Auto-generated method stubConnection connection = null;//通过业务层调用对应的具体数据库操作User user = null;try {connection = BaseDao.getConnection();user = userDao.getLoginUser(connection, userCode);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{BaseDao.closeResource(connection, null, null);}return user;}/*@Testpublic void test() {UserServiceImpl userService = new UserServiceImpl();String userCode = "admin";String userPassword = "12345678";User admin = userService.login(userCode, userPassword);System.out.println(admin.getUserPassword());}*/
}
  1. 编写Servlet
import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import pojo.User;
import util.Constants;
import service.user.UserService;
import service.user.UserServiceImpl;@SuppressWarnings("serial")
public class LoginServlet extends HttpServlet{//接受用户参数、调用业务层、转发视图@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO 自动生成的方法存根System.out.println("login ============ " );//获取用户名和密码String userCode = req.getParameter("userCode");String userPassword = req.getParameter("userPassword");//调用service方法,进行用户匹配UserService userService = new UserServiceImpl();User user = userService.login(userCode,userPassword);if(null != user){//登录成功//放入sessionreq.getSession().setAttribute(Constants.USER_SESSION,user);//页面跳转(frame.jsp)resp.sendRedirect("jsp/frame.jsp");}else{//页面跳转(login.jsp)带出提示信息--转发req.setAttribute("error", "用户名或密码不正确");req.getRequestDispatcher("login.jsp").forward(req,resp);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO 自动生成的方法存根doGet(req, resp);}
}
  1. 注册Servlet
<servlet><servlet-name>LoginServlet</servlet-name><servlet-class>com.kuang.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>LoginServlet</servlet-name><url-pattern>/login.do</url-pattern>
</servlet-mapping>
  1. 测试访问,保证以上功能可以成功

登录功能优化

注销功能
思路:移除session,返回登录页面

public class LogoutServlet extends HttpServlet {public void doPOST(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//清除sessionrequest.getSession().removeAttribute(Constants.USER_SESSION);response.sendRedirect(request.getContextPath()+"/login.jsp");//返回登录页面}}

注册xml

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

登录拦截优化

编写一个过滤器,并注册

import java.io.IOException;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import pojo.User;
import util.Constants;public class SysFilter implements Filter{public void init(FilterConfig filterConfig) throws ServletException{}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)throws IOException, ServletException {// TODO 自动生成的方法存根HttpServletRequest request =  (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)resp;//过滤器,从session中获取用户User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);if(user == null){//已经被移除或者注销了,或者未登录response.sendRedirect("/smbms/error.jsp");}else {chain.doFilter(req, resp);}}@Overridepublic void destroy() {// TODO 自动生成的方法存根}
}

注册xml

<!-- 用户登录过滤器 -->
<filter><filter-name>SysFilter</filter-name><filter-class>filter.SysFilter</filter-class>
</filter>
<filter-mapping><filter-name>SysFilter</filter-name><url-pattern>/jsp/*</url-pattern>
</filter-mapping>

测试,登录,注销,权限,都要保证OK

js乱码解决

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6aB8YiOC-1609316574114)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201229213417430.png)]

密码修改

  1. 导入前端素材
<li><a href="${pageContext.request.contextPath }/jsp/pwdmodify.jsp">密码修改</a></li>
  1. 写项目,建议从底层向上写
  2. UserDao接口
//修改当前用户密码public int updatePwd(Connection connection,int id,int password)throws SQLException, Exception;
  1. UserDao接口实现类
@Override//修改当前密码public int updatePwd(Connection connection, int id, String password) throws Exception {// TODO 自动生成的方法存根PreparedStatement pstm = null;int execute =0;if(connection!=null) {String sql = "update smbms_user set userPassword = ? where id = ?";Object[] params = {password,id};execute = BaseDao.execute(connection, pstm, sql, params);BaseDao.closeResource(null, pstm, null);}return execute;          }
  1. UserService层
public boolean updatePwd(int id,String password)throws SQLException, Exception;
  1. UserService实现类
public boolean updatePwd(int id, String password) throws SQLException, Exception {// TODO 自动生成的方法存根Connection connection = null;boolean flag = false;//修改密码try {connection = BaseDao.getConnection();if(userDao.updatePwd(connection, id, password)>0) {flag = true;}} catch (SQLException e) {// TODO 自动生成的 catch 块e.printStackTrace();} finally {BaseDao.closeResource(connection, null, null);}return flag;}
  1. servlet记得实现复用,要提取出方法!
    dao层service层 自己写映射类和实现类
    下面是 servlet层 的主体
public class UserServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO 自动生成的方法存根String method = req.getParameter("method");if (method != "savepwd" && method != null) {this.updatePwd(req, resp);}//实现复用~~~~~~// 想添加新的增删改查,直接用if(method != "savepwd" && method != null);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO 自动生成的方法存根doGet(req, resp);}public void updatePwd(HttpServletRequest req, HttpServletResponse resp) {// 通过session获得用户idObject o = req.getSession().getAttribute(Constants.USER_SESSION);String newpassword = req.getParameter("newpassword");boolean flag = false;if (o != null && newpassword != null) {UserService userService = new UserServiceImpl();try {flag = userService.updatePwd(((User) o).getId(), newpassword);} catch (SQLException e) {// TODO 自动生成的 catch 块e.printStackTrace();} catch (Exception e) {// TODO 自动生成的 catch 块e.printStackTrace();}if (flag) {req.setAttribute("message", "密码修改成功,请退出,使用新密码登录");// 密码修改成功,移除session(移除后不能再次修改密码,建议不移除)req.getSession().removeAttribute(Constants.USER_SESSION);} else {// 密码修改失败req.setAttribute("message", "密码修改失败");}} else {// 密码修改有问题req.setAttribute("message", "新密码有问题");}try {req.getRequestDispatcher("/jsp/pwdmodify.jsp").forward(req, resp);} catch (ServletException e) {// TODO 自动生成的 catch 块e.printStackTrace();} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}
}

注册xml

<servlet><servlet-name>UserServlet</servlet-name><servlet-class>servlet.user.UserServlet</servlet-class></servlet><servlet-mapping><servlet-name>UserServlet</servlet-name><url-pattern>/jsp/user.do</url-pattern></servlet-mapping>
  1. 测试

优化密码修改使用Ajax

  1. 阿里巴巴的fastjson
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.68</version>
</dependency>
  1. 后台代码修改

导入阿里的包

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.68</version>
</dependency>
package com.kuang.servlet.user;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.kuang.pojo.User;
import com.kuang.service.user.UserService;
import com.kuang.service.user.UserServiceImpl;
import com.kuang.util.Constants;
import com.mysql.jdbc.StringUtils;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;@SuppressWarnings("serial")
public class UserServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO 自动生成的方法存根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);}// 想添加新的增删改查,直接用if(method != "savepwd" && method != null);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO 自动生成的方法存根doGet(req, resp);}public void updatePwd(HttpServletRequest req, HttpServletResponse resp) {// 通过session获得用户idObject o = req.getSession().getAttribute(Constants.USER_SESSION);String newpassword = req.getParameter("newpassword");boolean flag = false;if (o != null && newpassword != null) {UserService userService = new UserServiceImpl();try {flag = userService.updatePwd(((User) o).getId(), newpassword);} catch (SQLException e) {// TODO 自动生成的 catch 块e.printStackTrace();} catch (Exception e) {// TODO 自动生成的 catch 块e.printStackTrace();}if (flag) {req.setAttribute("message", "密码修改成功,请退出,使用新密码登录");// 密码修改成功,移除session(移除后不能再次修改密码,建议不移除)req.getSession().removeAttribute(Constants.USER_SESSION);} else {// 密码修改失败req.setAttribute("message", "密码修改失败");}} else {// 密码修改有问题req.setAttribute("message", "新密码有问题");}try {req.getRequestDispatcher("/jsp/pwdmodify.jsp").forward(req, resp);} catch (ServletException e) {// TODO 自动生成的 catch 块e.printStackTrace();} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}public void pwdmodify(HttpServletRequest req, HttpServletResponse resp) {// 通过session获得用户idObject o = req.getSession().getAttribute(Constants.USER_SESSION);String oldpassword = req.getParameter("oldpassword");Map<String, String> resultMap = new HashMap<String, String>();if(o==null) {//session失效,session过期了resultMap.put("result","seesionerror");}else if(StringUtils.isNullOrEmpty(oldpassword)){//输入密码为空resultMap.put("result","error");}else {//String userPassword = ((User)o).getUserPassword();//seesion中的用户密码if(oldpassword.equals(userPassword)) {resultMap.put("result","true");}else {resultMap.put("result","false");}}try {resp.setContentType("application/josn");PrintWriter writer = resp.getWriter();/** resultMap = ["result","sessionerror","result",error]* josn格式={key,value*///writer.write(JSONArray.toJSONString(resultMap));writer.write(JSONArray.toJSONString(resultMap));writer.flush();writer.close();} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}
}
  1. 测试

用户管理实现

  1. 导入分页的工具类-PageSupport
  2. 用户列表页面导入-userlist.jsp

1、获取用户数量

  1. UserDao
//根据用户名或者角色查询用户总数
public int getUserCount(Connection connection,String username ,int userRole)throws SQLException, Exception;
  1. UserDaoImpl
@Overridepublic int getUserCount(Connection connection, String userName, int userRole)throws Exception {// TODO Auto-generated method stubPreparedStatement 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");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);}Object[] params = list.toArray();System.out.println("sql ----> " + sql.toString());rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);if(rs.next()){count = rs.getInt("count");}BaseDao.closeResource(null, pstm, rs);}return count;}
  1. UserService
//查询记录数public int getUserCount(String username, int userRole);
  1. UserServiceImpl
//查询记录数@Overridepublic int getUserCount(String queryUserName, int queryUserRole) {// TODO Auto-generated method stubConnection connection = null;int count = 0;System.out.println("queryUserName ---- > " + queryUserName);System.out.println("queryUserRole ---- > " + queryUserRole);try {connection = BaseDao.getConnection();count = userDao.getUserCount(connection, queryUserName,queryUserRole);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{BaseDao.closeResource(connection, null, null);}//System.out.println("count"+count);return count;}

2、获取用户列表

1.UserDao

//通过条件查询-userListpublic List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize)throws Exception;
  1. UserDaoImpl
@Overridepublic List<User> getUserList(Connection connection, String userName,int userRole,int currentPageNo, int pageSize)throws Exception {// TODO Auto-generated method stubPreparedStatement 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)*页面大小//0,5   1,0  01234//5,5 5,0  56789//10,5    10,0 10~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.execute(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;}
  1. UserService
//根据条件查询用户列表public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);
  1. UserServiceImpl
@Overridepublic List<User> getUserList(String queryUserName,int queryUserRole,int currentPageNo, int pageSize) {// TODO Auto-generated method stubConnection 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) {// TODO Auto-generated catch block e.printStackTrace();}finally{BaseDao.closeResource(connection, null, null);}return userList;}

3、获取角色操作

为了我们的职责统一,我们可以把角色的操作单独放在一个包中,和pojo类对应。。。

  1. RoleDao
//获取角色列表public List<Role> getRoleList(Connection connection)throws Exception;
  1. RoleDaoIpml
public class RoleDaoImpl implements RoleDao {@Overridepublic List<Role> getRoleList(Connection connection) throws Exception {PreparedStatement pstm = null;ResultSet rs = null;List<Role> roleList = new ArrayList<Role>();if (connection != null) {String sql = "select * from smbms_role";Object[] params = {};rs = BaseDao.execute(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;}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kceXSlcC-1609316574117)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201230094842460.png)]

  1. RoleService
public interface RoleService {//角色列表查询public List<Role> getRoleList();  }
  1. RoleServiceIpml
public class RoleServiceImpl implements RoleService{private RoleDao roleDao;public RoleServiceImpl(){roleDao = new RoleDaoImpl();}@Overridepublic 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;}}

4、用户显示的Servlet

  1. 获取用户前端的数据(查询)
  2. 判断请求是否需要执行,看参数的值判断
  3. 为了实现分页,需要计算出当前页面和总页面,页面大小…
  4. 用户列表展示
  5. 返回前端
//重点、难点private void query(HttpServletRequest req, HttpServletResponse resp) {// TODO 自动生成的方法存根//查询用户列表//从前端获取数据//查询用户列表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);}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();//总共有几页//(totalCount+pageSize-1/pageSize)取整// pageSupport.getTotalCount()//System.out.println("totalCount ="+totalCount);//System.out.println("pageSize ="+pageSize);//System.out.println("totalPageCount ="+totalPageCount);//控制首页和尾页//如果页面小于 1 就显示第一页的东西if(currentPageNo < 1) {currentPageNo = 1;}else if(currentPageNo > totalPageCount) {//如果页面大于了最后一页就显示最后一页currentPageNo =totalPageCount;}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) {// TODO 自动生成的 catch 块e.printStackTrace();} catch (IOException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}

小黄鸭调试法:自言自语

项目原理流程图:

上传文件和导包

文件上传注意事项

  • 1.为保证服务器安全,上传文件应该放在外界无法直接访问你得目录下,比如放在WEB-INF目录下
  • 2.为防止文件覆盖现象的发生,要为文件产生一个唯一的文件名 (添加时间戳 或者 uuid 或者MD5 或者位运算)
  • 3.要限制上传文件的大小
  • 4.可以限制上传文件的类型,在收到上传文件名时,要判断后缀名是否合格。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsBoF7TL-1609316574123)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201230111632383.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cC5HaVaX-1609316574126)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201230111841125.png)]

需要用到的类详解

  • ServletFileUpload 负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时,需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造号DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法,或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><%--通过表单上传文件--%><%--注意:文件一般比较大,所以上传文件都是使用post方式提交get方式只能提交4-5kb的数据,而post没有限制${pageContext.request.contextPath}:获取到webapp路径--%><form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data"><p>上传用户:<input type="text" name="username"><br/></p><p>上传文件1:<input type="file" name="file1"></p><p>上传文件2:<input type="file" name="file2"></p><p><input type="submit" value="点击上传"> | <input type="reset" value="重置"></p></form>
</body>
</html>
package edu.cqupt.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.*;
import java.util.List;
import java.util.UUID;public class FileServlet  extends HttpServlet {@Overrideprotected void doPost(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 tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");File file = new File(tempPath);if(!file.exists()){file.mkdir();}String msg = null;try {//1.创建 DiskFileItemFactoryDiskFileItemFactory factory = getDiskFileItemFactory(file);//2.获取ServletFileUploadServletFileUpload upload = getServletFileUpload(factory);// 3.处理上传文件msg = uploadParseRequest(upload,req,uploadPath);} catch (FileUploadException e) {e.printStackTrace();}// 请求转发消息req.setAttribute("msg",msg);req.getRequestDispatcher("info.jsp").forward(req,resp);}public static DiskFileItemFactory getDiskFileItemFactory(File file){DiskFileItemFactory factory = new DiskFileItemFactory();factory.setSizeThreshold(1024*1024);    // 缓存区大小为1Mfactory.setRepository(file);            // 临时目录的保存目录,需要一个filereturn  factory;}public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){ServletFileUpload upload = new ServletFileUpload(factory);upload.setProgressListener(new ProgressListener() {@Overridepublic void update(long pBytesRead, long pContenLength, int pItems) {System.out.println("总大小:" + pContenLength + "已上传:" + pBytesRead );}});upload.setHeaderEncoding("UTF-8");upload.setFileSizeMax(1024*1024*10);upload.setSizeMax(1024*1024*10);return upload;}public static String  uploadParseRequest(ServletFileUpload upload,HttpServletRequest req,String uploadPath) throws FileUploadException, IOException {String message = null;List<FileItem> fileItems = upload.parseRequest(req); // 把前端请求解析,封装成一个FileItem对象for (FileItem fileItem : fileItems) {if (fileItem.isFormField()) {     // 普通表单String name = fileItem.getName();String value = fileItem.getString("utf-8");System.out.println(name + ":" + value);} else {  //判断是文件表单String uploadFileName = fileItem.getName(); // ===== 处理文件 =============if (uploadFileName.trim().equals("") || uploadFileName == null) {continue;}String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);// UUID.randomUUID() 随机生成一个唯一识别的通用码// 网络中传输东西,都需要序列化// POJO, 实体类, 如果想要生成在多个电脑上运行, 传输-->需要把对象都序列化// JNI java native Interface// implements Serializable :标记接口 ,JVM --> Java栈 本地方法栈 native --> c++String uuidPath = UUID.randomUUID().toString();// 可以 使用UUID(唯一识别的通用码),保证文件唯一String realPath = uploadPath + "/" + uuidPath; // ========= 存放地址 ========File realPathFile = new File(realPath);if (!realPathFile.exists()) {realPathFile.mkdir();}InputStream is = fileItem.getInputStream(); // ========= 文件传输 ========FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);byte[] buffer = new byte[1024];int len = 0;while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}fos.close();is.close();message = "文件上传成功";fileItem.delete();  //上传成功,清除临时文件}}return message;}
}

发送邮件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IejcoJ5V-1609316574127)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201230142142319.png)]

加载包pom.xml

vgzetyyijkuo****ddfa

   <!-- 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>

注册页面 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>注册</title>
</head>
<body><form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post"><div class="txt txt0"><span style="letter-spacing:8px;">用户名:</span><input name="username" type="text" class="txtphone" placeholder="请输入用户名"/></div><div class="txt txt0"><span style="letter-spacing:4px;">登录密码:</span><input name="password" type="text" class="txtphone" placeholder="请输入密码"/></div><div class="txt txt0"><span style="letter-spacing:4px;">邮箱:</span><input name="email" type="text" class="txtphone" placeholder="请输入邮箱"/></div><div class="txt txt0"><input type="submit" value="注册"/></div></form>
</body>
</html>

注册成功跳转页面:info.jsp

<%--Created by IntelliJ IDEA.User: ASUSDate: 2020/8/29Time: 22:30To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>${message}
</body>
</html>

用户实体类User.java

package edu.cqupt.pojo;import java.io.Serializable;
public class User implements Serializable {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;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +", email='" + email + '\'' +'}';}
}

RegisterServlet.java

package edu.cqupt.servlet;import edu.cqupt.pojo.User;
import edu.cqupt.utils.SendEmail;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 {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");String email = req.getParameter("email");System.out.println(username);System.out.println(password);System.out.println(email);User user = new User(username, password, email);SendEmail send = new SendEmail(user);send.start();       // 使用线程,加快邮件发送req.setAttribute("message","注册成功,请查收邮件");req.getRequestDispatcher("info.jsp").forward(req,resp);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

SendEmail.java

package edu.cqupt.utils;import com.sun.mail.util.MailSSLSocketFactory;
import edu.cqupt.pojo.User;import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;public class SendEmail extends Thread{private String from = "发送方@qq.com";private String username = "发送方@qq.com";private String password = "邮箱授权码";private String host = "smtp.qq.com";private  User user;public SendEmail(User user) {this.user = user;}@Overridepublic void run() {try {Properties prop = new Properties();prop.setProperty("mail.host", "smtp.qq.com");prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.auth", "true");//QQ邮箱,设置SSL加密MailSSLSocketFactory sf = new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable", "true");prop.put("mail.smtp.socketFactory", sf);// 使用JavaMail发送邮件的5个步骤// 1、创建sessionSession session = Session.getInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(username, password);}});// 2. 开启Session的debug模式:truesession.setDebug(false);// 3.通过session得到transport对象Transport ts = session.getTransport();ts.connect(host, username, password);// 4. 创建邮件Message message = new MimeMessage(session);message.setFrom(new InternetAddress(from));message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));message.setSubject("注册邮件");String info = "Yours username:" + user.getUsername() + "password:" + user.getPassword();message.setContent(info, "text/html;chartset=UTF-8");// 5.发送邮件ts.sendMessage(message, message.getAllRecipients());// 6.关闭连接ts.close();}catch (Exception e){throw new RuntimeException(e);}}
}

邮件发送

2.jar包的支持

activation-1.1.1.jar

mail-1.4.7.jar

3.授权码的获取

4.简易文本邮件发送的实现

由上图我们可以确定几个必须步骤

1.创建session对象

2.创建Transport对象

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

4.创建一个Message对象(需要传递session)

  • message需要指明发件人、收件人以及文件内容

5.发送邮件

6.关闭连接

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 MailDemo01 {public static void main(String[] args) throws Exception {Properties prop=new Properties();prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session=Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication("XXXX@qq.com","授权码");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器ts.connect("smtp.qq.com","XXXX@qq.com","授权码");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人message.setFrom(new InternetAddress("XXXX@qq.com"));//指明邮件的收件人message.setRecipient(Message.RecipientType.TO,new InternetAddress("XXXX@qq.com"));//邮件标题message.setSubject("发送的标题");//邮件的文本内容message.setContent("内容","text/html;charset=UTF-8");//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}
}

5.复杂文件内容的发送

5.1文件构成解析

除了邮件内容部分,其他的部分代码往往是相同的,除了需要根据不同的邮箱运营商编写不同的配置代码外。邮件内容也被分为很多个部分,由文件、图片、附件等构成,编写邮件内容的过程,类似于积木的拼接,另外值得注意的是文本内容一般为HTML的格式发送。

每一个文本、图片、附件可以分为一个MimeBodyPart,由MimeMultipart完成组装

5.2包含图片的发送

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 MailDemo02 {public static void main(String[] args) throws Exception {Properties prop=new Properties();prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session=Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication("11927XXX@qq.com","授权码");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器ts.connect("smtp.qq.com","11927XXX@qq.com","授权码");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人message.setFrom(new InternetAddress("11927XXX@qq.com"));//指明邮件的收件人message.setRecipient(Message.RecipientType.TO,new InternetAddress("11927XXX@qq.com"));//邮件标题message.setSubject("java发出");//邮件的文本内容//=================================准备图片数据=======================================MimeBodyPart image=new MimeBodyPart();//图片需要经过数据化的处理DataHandler dh=new DataHandler(new FileDataSource("D:\\Bert\\1594126632(1).jpg"));//在part中放入这个处理过图片的数据image.setDataHandler(dh);//给这个part设置一个ID名字image.setContentID("bz.jpg");//准备正文的数据MimeBodyPart text=new MimeBodyPart();text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");//描述数据关系MimeMultipart mm=new MimeMultipart();mm.addBodyPart(text);mm.addBodyPart(image);mm.setSubType("related");//设置到消息中,保存修改message.setContent(mm);message.saveChanges();//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}
}

5.3包含附件的发送

import com.sun.mail.util.MailSSLSocketFactory;import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;public class MailDemo03 {public static void main(String[] args) throws Exception {Properties prop=new Properties();prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session=Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication("1192XXXX@qq.com","授权码");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器ts.connect("smtp.qq.com","1192XXXX@qq.com","授权码");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人message.setFrom(new InternetAddress("1192XXXX@qq.com"));//指明邮件的收件人message.setRecipient(Message.RecipientType.TO,new InternetAddress("1192XXXX@qq.com"));//邮件标题message.setSubject("java发出");//邮件的文本内容//=================================准备图片数据MimeBodyPart image=new MimeBodyPart();//图片需要经过数据化的处理DataHandler dh=new DataHandler(new FileDataSource("D:\\Bert\\1594126632(1).jpg"));//在part中放入这个处理过图片的数据image.setDataHandler(dh);//给这个part设置一个ID名字image.setContentID("bz.jpg");//=================================准备正文数据MimeBodyPart text=new MimeBodyPart();text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");//=================================准备附件数据MimeBodyPart body1= new MimeBodyPart();body1.setDataHandler(new DataHandler(new FileDataSource("D:\\Bert\\cmd.txt")));body1.setFileName("1.txt");//描述数据关系MimeMultipart mm=new MimeMultipart();mm.addBodyPart(body1);mm.addBodyPart(text);mm.addBodyPart(image);mm.setSubType("mixed");//设置到消息中,保存修改message.setContent(mm);message.saveChanges();//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}
}

实战:注册通知邮件

index.JSP

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

实体类

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;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +", email='" + email + '\'' +'}';}
}

绑定路径

  <servlet><servlet-name>RegisterServlet</servlet-name><servlet-class>cn.csn.MailDemo01.servlet.RegisterServlet</servlet-class></servlet><servlet-mapping><servlet-name>RegisterServlet</servlet-name><url-pattern>/RegisterServlet.do</url-pattern></servlet-mapping>

servlet

import cn.csn.MailDemo01.pojo.User;
import cn.csn.MailDemo01.utils.Sendmail;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class RegisterServlet extends HttpServlet {@Overrideprotected 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);Sendmail send=new Sendmail(user);send.start();System.out.println("success");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}
}

发送邮件核心类

import cn.csn.MailDemo01.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="XXX@qq.com";private String host="smtp.qq.com";private User user;public Sendmail(User user){this.user=user;}@Overridepublic void run() {try {Properties prop=new Properties();prop.setProperty("mail.host",host);///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session= Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(from,"授权码");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器ts.connect(host,from,"授权码");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人message.setFrom(new InternetAddress(from));//指明邮件的收件人message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail()));//邮件标题message.setSubject("注册通知");//邮件的文本内容message.setContent("恭喜你("+user.getUsername()+")成功注册!"+"密码:"+user.getPassword(),"text/html;charset=UTF-8");//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}catch (Exception e){System.out.println(e);}}
}

这里引入多线程的目的是为了提高用户的体验,防止因发送文件时间过长,导致前端响应过久,因此这里采用异步响应。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IGkz32bF-1609316574129)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201230152905585.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-me0Qj3SH-1609316574130)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images\image-20201230153222045.png)]

tomcat可能缺少包导致运行失败

JAVAWEB(笔记)相关推荐

  1. JavaWeb笔记:JDBC总结

    JavaWeb笔记:JDBC总结 目录 JavaWeb笔记:JDBC总结 一.JDBC概述 二.开发一个JDBC程序(重要) 三.JDBC常用的类和接口详解 1.java.sql.Drivermana ...

  2. JavaWeb笔记:CSS总结

    JavaWeb笔记:CSS总结 目录 JavaWeb笔记:CSS总结 一.css的简介 二.css选择器 三.css属性 四.css盒子模型 一.css的简介     1.什么是css        ...

  3. JavaWeb笔记:Html总结

    JavaWeb笔记:Html总结 目录 JavaWeb笔记:Html总结 一.html简介 二.html基本标签 三.html表单标签(重点) 一.html简介     1.html是什么       ...

  4. JavaWeb笔记:第07章 MVC |EL |JST |Filter |Listener |JQuery |AJAX |Maven |JSON |Redis |Linux |Nginx

    JavaWeb笔记:第07章 MVC |EL |JST |Filter |Listener |JQuery |AJAX |Maven |JSON |Redis |Linux |Nginx 1. MVC ...

  5. 【javaweb笔记1】自用

    javaweb笔记 一.tomcat 安装 1. 官网下载 2.安装 3.卸载 4.启动 5.控制台中文乱码 6.闪退 7.IDEA使用tomcat的maven插件 7.IDEA不使用插件配置 mav ...

  6. 25-day24黑马javaweb笔记-redis

    目录 25-day24黑马javaweb笔记-redis 概念 什么是NOSQL 主流的NOSQL产品 什么是Redis 下载安装 命令操作 1. redis的数据结构: 2. 字符串类型 strin ...

  7. JavaWeb笔记-备份下

    JavaWeb笔记-备份下 html 简介: 超文本标记语言 Hyper Text Markup Language 网页语言 超文本:超出文本的范畴,使用html可以轻松实现 标记:html所有操作都 ...

  8. JavaWEB笔记13 jQuery介绍及常用操作

    JavaWEB笔记13 jQuery介绍及常用操作 文章目录 JavaWEB笔记13 jQuery介绍及常用操作 一.jQuery简介: 1.jQuery介绍: 2.jQuery书写风格: 二.jQu ...

  9. 09-day6黑马javaweb笔记-html基础

    09-day6黑马javaweb笔记-html基础 web概念概述 Javaweb 使用Java语言开发基于互联网的项目 软件架构: C/S: Client/Server 客户端/服务器端 * 在用户 ...

  10. JavaWeb笔记01-HTML基础标签介绍

    JavaWeb笔记01-HTML基础标签介绍 文章目录 JavaWeb笔记01-HTML基础标签介绍 1. html简介 2. 开始和结束标签 3. title标签 4. meta标签 5. 换行标签 ...

最新文章

  1. 2021年大数据Flink(三):​​​​​​​Flink安装部署 Local本地模式
  2. ecplise常用快捷键
  3. 二十四种设计模式:备忘录模式(Memento Pattern)
  4. winserver的consul部署实践与.net core客户端使用(附demo源码)
  5. 【渝粤题库】国家开放大学2021春2718动物生理基础题目
  6. scrumndash;yesterday once more
  7. Android 系统(82)---ART 和 Dalvik
  8. tensorflow之lenet训练手写字及应用
  9. 深入内核:Oracle数据提交与事务隔离的深度解析
  10. 仿今日头条项目——个人中心
  11. 使用计算机粘贴板的步骤,电脑中快速打开剪贴板查看器的方法
  12. Hadoop(一) 原理简介、基本构建
  13. mac免安装mysql配置_mysql免安装版配置使用
  14. iphone电脑wifi连接服务器未响应,苹果wifi连接不上怎么回事_苹果电脑连接不上wifi的解决步骤-win7之家...
  15. Oracle数据库Clob类型Blob类型与String互转
  16. windows7浏览器无法打开html,win7网页无法打开出现HTML Parsing Error的解法
  17. java逻辑循环经典案例(不死神兔、百钱百鸡、逢七过、评委打分、数组翻转)
  18. 图论(十三)——平面图和对偶图
  19. 手机百度浏览器底部fixed悬浮框屏蔽,出来一会自动消失了
  20. Linux:如何在后台运行一个程序?

热门文章

  1. P4331 [BalticOI 2004]Sequence 数字序列(左偏树)
  2. AtCoder Regular Contest 060
  3. Codeforces Round #740 (Div. 2) F. Top-Notch Insertions 线段树 / 平衡树 + 组合数学
  4. Codeforces Round #735 (Div. 2)
  5. 牛客题霸 [字符串变形]C++题解/答案
  6. ABB (2020牛客国庆集训派对day1)
  7. [AtCoder Beginner Contest 215] A-G题解
  8. P3343-[ZJOI2015]地震后的幻想乡【dp,数学期望】
  9. nssl1438-战略威慑【枚举,树的直径】
  10. 【矩阵乘法】Matrix Power Series(poj 3233)