@[toc]7
web开发:
可以提供浏览器访问的程序;
Web酸用程序编写完毕后,若想提供给外界访问;需费一个服务蔬来统一管理
ASP:
php:
jSP/Servlet:
B/S;浏览和服务器C/S:客户端和服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;
lIS
微软的;ASP.,Windows中自带的
Tomcat
面向百度编程:
Tomcat是Apache 软件基金会(Apache Software Foundation)的jakarta项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat中得到体现,因为Tomcat 技术先进、性能稳定,而且免费,因而深受lava爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个Java初学web的人来说,它是最佳的选择
Tomcat 实际上运行JSP页面和Serlet。Tornct最新版易9.0
工作3-5年之后,可以尝试手写Tomcat服务器;
下载tomcat:
文件夹作用:
访问测试:http://localhost:8080/
可能遇到的问题:
可以修改 conf/logging.properties 中的 java.util.logging.ConsoleHandler.encoding = GBK 解决乱码问题(不建议改)
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
可以配置主机的名称
<Host name="www.qinjiang.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
// name 默认是loaclhost, 改了之后,需要去host里面改DNS映射关系
高难度面试题:
请你谈谈网站是如何进行访问的!
4.可以配置一下环境变量(可选性)
不会就先模仿
网站应该有的结构
--webapps :Tomcat服务器的web目录
-ROOT
-kuangstudy :网站的目录名
-WEB-INF
-classes : java程序
-lib:web应用所依赖的jar包
-web.xml :网站配置文件
-index.html 默认的首页
-static
-css
-js
-img
-.....
HTTP协议:面试
Maven:构建工具
Servlet入门
(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。
Https:安全的
百度:
Request URL:https://www.baidu.com/ 请求地址
Request Method:GET get方法/post方法
Status Code:200 OK 状态码:200
Remote(远程) Address:14.215.177.39:443
Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9 语言
Cache-Control:max-age=0
Connection:keep-alive
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
百度:
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诞生了!
我们目前用来就是方便导入jar包的!
Maven的核心思想:约定大于配置
Maven会规定好你该如何去编写我们Java代码,必须要按照这个规范来;
在我们的系统环境变量中配置如下配置:
<mirror>
<id>nexus-aliyunid>
<mirrorOf>*,!jeecg,!jeecg-snapshotsmirrorOf>
<name>Nexus aliyunname>
<url>http://maven.aliyun.com/nexus/content/groups/publicurl>
mirror>
在本地的仓库,远程仓库; 建立一个本地仓库:localRepository
在D:\java\Maven\apache-maven-3.8.7\ 新建一个空目录,maven-repo
<localRepository>D:\java\Maven\apache-maven-3.8.7\maven-repolocalRepository>
注意要设置两遍,设置地点如上图!
第一次创建项目,用生成器
第二次创建项目,不用生成器
如下所示,main-java 放置java源码,resources放置配置文件,test-java测试 (约定大于配置!)
重新用构造器构造一个maven项目,会出现如下的webapp包
右键可以标记为源码目录,也可以设置-项目结构-模块中设置
右上角当前文件,下拉选择配置文件,+一个Tomcan本地服务器
下方的路径设置尽量不要设置为 /
否则会删掉原来Tomcat中的ROOT目录
然后启动,就可以访问到 helloworld了
pom.xml是maven的核心配置文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>test2artifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<name>test2 Maven Webappname>
<url>http://maven.apache.orgurl>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>3.8.1version>
<scope>testscope>
dependency>
dependencies>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<build>
<finalName>test2finalName>
build>
project>
maven由于他的约定大于配置,我们之后可以能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:
IDEA操作:右上角的目录树,可以显示依赖的目录结构,Crtl+Alt+Shift+U
IDEA用Maven构造器,生成的web.xml中的版本默认是2.3,应该和Tomcat一致,所以要从Tomcat中的ROOT目录中把web.xml内容复制过来,目前是5.0
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
web-app>
把实现了Servlet接口的Java程序叫做,Servlet
Serlvet接口Sun公司有两个默认的实现类:HttpServlet,GenericServled
<modules>
<module>servlet-01module>
modules>
子项目会有
<parent>
<artifactId>javaweb-02-servletartifactId>
<groupId>com.kuanggroupId>
<version>1.0-SNAPSHOTversion>
parent>
父项目中的java, 子项目可以直接使用
son extends father
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
web-app>
<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.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>javaweb-02-servletartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>pompackaging>
<modules>
<module>servlet-01module>
<module>servlet-02module>
modules>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
dependencies>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
project>
package org.Martin.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter(); //响应流
writer.print("Hello,Serlvet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>com.kuang.servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello2url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello3url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello4url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello5url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello/*url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>*.qinjiangurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet>
<servlet-name>myErrorservlet-name>
<servlet-class>org.Martin.servlet.ErrorServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>myErrorservlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
我在这个Servlet中保存的数据,可以在另外一个servlet中拿到;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter() 初始化参数
//this.getServletConfig() Servlet配置
//this.getServletContext() Servlet上下文
ServletContext context = this.getServletContext();
String username = "秦疆"; //数据
context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username
}
}
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// 获取HelloServlet保存的
String username = (String) servletContext.getAttribute("username");
resp.getWriter().print(username);
}
}
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>com.Martin.servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet>
<servlet-name>getsservlet-name>
<servlet-class>com.Martin.servlet.GetServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>getsservlet-name>
<url-pattern>/getsurl-pattern>
servlet-mapping>
测试访问结果;先访问hello,再访问gets才会生效,否则hello没提交数据,gets访问不到
<context-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql://localhost:3306/mybatisparam-value>
context-param>
<servlet>
<servlet-name>gpservlet-name>
<servlet-class>com.Martin.servlet.GetParaServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>gpservlet-name>
<url-pattern>/gpurl-pattern>
servlet-mapping>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
把GP的资源转发到了自己的页面
@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);
}
发现:都被打包到了同一个路径下:target-classes,我们俗称这个路径为classpath:
思路:需要一个文件流
username=admin
password=root
public class GetPropertiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 在打包之后的target下的项目路径
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String username = prop.getProperty("username");
String password = prop.getProperty("password");
resp.getWriter().print(username+password);
}
}
访问测试即可ok;
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest
对象,代表响应的一个HttpServletResponse;
负责向浏览器发送数据的方法
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);
package org.Martin.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/ctfshow.png");
// String realPath = "E:\\Martin_Code\\java\\javaweb\\javaweb-02-servlet\\Response-01\\target\\Response-01\\WEB-INF\\classes\\ctfshow.png";
System.out.println("文件路径:"+realPath);
// 2. 下载的文件名是啥?
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3. 设置想办法让浏览器能够支持下载我们需要的东西
// "Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"))
resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream fis = new FileInputStream(realPath);
// 5. 创建缓冲区
int len=0;
byte[] buffer = new byte[1024];
// 6. 获取OutputStream对象
ServletOutputStream outputStream = resp.getOutputStream();
// 7. 将FileOutputStream流写入到bufer缓冲区
while ((len=fis.read(buffer))!=-1){
// 8. 使用OutputStream将缓冲区中的数据输出到客户端!
outputStream.write(buffer,0,len);
}
outputStream.close();
fis.close();
}
}
验证怎么来的?
package org.Martin.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 如何让浏览器每5秒刷新一次
resp.setHeader("refresh","3");
// 在内存中创建一个图片
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
// 得到图片
Graphics2D g = (Graphics2D) image.getGraphics(); //笔
// 设置图片背景颜色
g.setColor(Color.WHITE);
g.fillRect(0,0,80,20);
// 给图片写数据
g.setColor(Color.BLUE);
g.setFont(new Font("null",Font.BOLD,20));
g.drawString(makeNum(),0,20);
// 告诉浏览器这个请求用图片的方式打开
resp.setContentType("image/png");
// 网站存在缓冲,不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
// 把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
// 生成随机数
private String makeNum(){
Random random = new Random();
// 最大值,4位数
String num = random.nextInt(9999) + "";
StringBuffer sb = new StringBuffer();
// 不足四位数,补充0
for (int i = 0; i < 4-num.length(); i++) {
sb.append("0");
}
num = sb.toString() + num;
return num;
}
}
<servlet>
<servlet-name>ImageServletservlet-name>
<servlet-class>com.kuang.servlet.ImageServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>Imageservletservlet-name>
<url-pattern>/imgurl-pattern>
servlet-mapping>
void sendRedirect(String var1) throws IOException;
测试:
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 跳转到哪里
/*
resp.setHeader("Location","./image");
resp.setStatus(302);
*/
// resp.sendRedirect(req.getContextPath()+"/image");
resp.sendRedirect("./image");
}
}
<html>
<body>
<h2>Hel1o World!h2>
<%--这里超交的路径,需要寻找到项目的路径--%>
<%--${pageContext. request, contextPath}代表当前的项目--%>
<form action="${pageContext. request.contextPath}/login" method="get">
用户名: <input type="text" name="username"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit">
form>
body>
html>
RequestTest.java
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入请求");
// 处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+password);
// 重定向到成功,注意路径
resp.sendRedirect(req.getContextPath()+"/success.jsp");
// resp.sendRedirect("./success.jsp");
}
}
重定向页面success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<h1>successh1>
body>
html>
web.xml配置
<servlet>
<servlet-name>requsetservlet-name>
<servlet-class>com. kuang. servlet. RequestTestservlet-class>
servlet>
<servlet-mapping>
<servlet-name>requsetservlet-name>
<url-pattern>/loginurl-pattern>
servlet-mapping>
导入依赖的jar包
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
dependencies>
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req. setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username);
System.out.println(password);
for (String hobby : req.getParameterValues("hobby")) {
System.out.println(hobby);
}
// 请求转发 会保留项目地址 所以不用加这个 req.getContextPath()
req.getRequestDispatcher("/success.jsp").forward(req,resp);
System.out.println(req.getPathInfo()); // null
System.out.println(req.getContextPath()); // /Request_01_war 项目的根路径
System.out.println(req.getServletPath()); // /login 自己这个类的路径
}
}
// 重定向,需要根目录的地址
response.sendRedirect(req.getContextPath()+"/success.jsp");
// 请求转发, 会保留项目的根目录地址,不用加requset.getContextPath()来获取根目录地址
requset.getRequestDispatcher("/success.jsp").forward(req,resp);
// 前端获取项目的根地址
${pageContext.request.contextPath}
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话;
有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话;
你能怎么证明你是西开的学生?
你 西开
一个网站,怎么证明你来过?
客户端 服务端
cookie
session
常见常见:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
代码:
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决中文乱码,解决不了!!
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
// 写数据
PrintWriter writer = resp.getWriter();
// Cookie从服务器获取
Cookie[] cookies = req.getCookies(); // 可能存在多个,是一个数组
// 判断是否是第一次登录
boolean flag = false;
for (Cookie cookie : cookies) {
if (cookie.getName().equals("lastTime")){
flag=true;
// cookie.getValue();是一个字符串
// 字符串变整数时间戳
long lastTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastTime);
writer.write("Not first: ");
writer.write(date.toLocaleString());
}
}
if (!flag){
writer.write("The First");
}
// 服务器更新Cookie name value
// System.currentTimeMillis()一个时间戳
Cookie cookie = new Cookie("lastTime",String.valueOf(System.currentTimeMillis()));
cookie.setMaxAge(24*60*60); //有效期
resp.addCookie(cookie);
}
}
cookie:一般会保存在本地的 用户目录下 AppData;
一个网站cookie是否存在上限!聊聊细节问题
删除Cookie;
编码解码:
URLEncoder.encode("秦疆","utf-8");
URLDecoder.decode(cookie.getValue(),"UTF-8");
使用场景:
使用Session:
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
// 得到Session
HttpSession session = req.getSession();
// session.removeAttribute("name"); 删除session中的name
// session.invalidate(); 清除session,当浏览器再次访问,会生成新的session,应用于用户手动注销
// 给Session 存信息 可以存一个对象
session.setAttribute("name","Martin");
session.setAttribute("Person",new Person("person.name",3));
// 得到Session 的信息
System.out.println(session.getAttribute("name"));
System.out.println(session.getAttribute("Person"));
// 获取Session ID
String sessionId = session.getId();
// 判断是不是新的
if (session.isNew()){
resp.getWriter().write("new: "+sessionId);
}else {
resp.getWriter().write("old: "+sessionId);
}
//Session创建的时候做了什么?
//传递了一个Cookie, name="JSESSIONID" value=session.getId()
}
}
会话自动过期:web.xml配置
<session-config>
<session-timeout>15session-timeout>
session-config>
req.getCookies()
resp.addCookies(cookie)
cookie.getName();cookie.getValue();
req.getSession()
session.setAttribute(name,value)
session.getAttribute(name)
Cookie:只能保存键值对,效率低,引入了Session
Session: SessionID是一串键值对的哈希值,效率高,(服务器用SessionID相互匹配来验证区分用户)但是都存到服务器,服务器很难受,引入了Token
Token: 把加密的UserID保存到客户端,服务器解密得到UserID,服务器很轻松
Java Server Pages : Java服务器端页面,也和Servlet一样,用于动态Web技术!
最大的特点:
思路:JSP到底怎么执行的!
C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat
我电脑的地址:C:\Users\86136\AppData\Local\JetBrains\IntelliJIdea2022.3\tomcat\16a6cd02-6b09-4de3-a7fa-601b94a708b7\work\Catalina\localhost\Request_01_war\org\apache\jsp
发现页面转变成了Java程序!
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
JSP最终也会被转换成为一个Java类!
JSP 本质上就是一个封装好的Servlet
//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//JSPService
public void _jspService(.HttpServletRequest request,HttpServletResponse response){
}
final javax.servlet.jsp.PageContext pageContext; //页面上下文
javax.servlet.http.HttpSession session = null; //session
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //config
javax.servlet.jsp.JspWriter out = null; //out
final java.lang.Object page = this; //page:当前
HttpServletRequest request; //请求
HttpServletResponse response; //响应
response.setContentType("text/html"); //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
在JSP页面中;
只要是 JAVA代码就会原封不动的输出;
如果是HTML代码,就会被转换为: out.write("\r\n");
这样的格式,输出到前端!
任何语言都有自己的语法,JAVA中有,。 JSP 作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),Java所有语法都支持!
<%-- 注释 --%>
<%= 变量或者表达式%> //作用:用来将程序的输出,输出到客户端
<%= new java.util.Date()%>
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out.println("Sum="+sum+"
");
%>
脚本片段的再实现
<%
int x = 10;
out.println(x);
%>
这是一个JSP文档
<%
int y = 2;
out.println(y);
%>
<%--在代码嵌入HTML元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
Hello,World <%=i%>
<%
}
%>
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void kuang(){
System.out.println("进入了方法Kuang!");
}
%>
JSP声明:会被编译到JSP生成Java的类中!其他的,就会被生成到_jspService方法中!
在JSP,嵌入Java代码即可!
<%%> java代码片段
<%= %> 表达式的值
<%! %> jsp声明
<%--注释--%>
JSP的注释,不会在客户端显示,HTML就会!
<%@page args.... %>
<%@include file=""%>
<%--@include会将两个页面合二为一,参数不能冲突--%>
<%@include file="common/header.jsp"%>
网页主体
<%@include file="common/footer.jsp"%>
<%--jSP标签
jsp:include:拼接页面,本质还是三个,参数互不影响
--%>
网页主体
pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","秦疆4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
EL表达式: ${ }
JSP标签
<%--jsp:include--%>
<%--
http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
--%>
/jsptag2.jsp
<%=request.getParameter("name")%>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!,需要引入标签库
格式化标签
SQL标签
XML 标签
核心标签 (掌握部分)
JSTL标签库使用步骤
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
c:if
<head>
<title>Titletitle>
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> peoples = new ArrayList<>();
peoples.add(0,"张三");
peoples.add(1,"李四");
peoples.add(2,"王五");
peoples.add(3,"赵六");
peoples.add(4,"田六");
request.setAttribute("list",peoples);
%>
<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin, 哪里开始
end, 到哪里
step, 步长
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="${people}"/> <br>
</c:forEach>
实体类
JavaBean有特定的写法:
一般用来和数据库的字段做映射 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,"西安");
}
servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序猿调用
↑
JDBC (实现该接口)
↑
Mysql Oracle SqlServer ....(不同厂商)
View
Controller (Servlet)
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库
比如 Shiro安全框架技术就是用Filter来实现的
Filter:过滤器 ,用来过滤网站的数据;
(比如用来过滤网上骂人的话,我***我自己 0-0)
Filter开发步骤:
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.25version>
dependency>
dependencies>
package org.example.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//Chain : 链
/*
1. 过滤中的所有代码,在过滤特定请求的时候都会执行
2. 必须要让过滤器继续执行
chain.doFilter(request,response);
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前....");
chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
System.out.println("CharacterEncodingFilter执行后....");
}
//销毁:web服务器关闭的时候,过滤器会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>org.example.filter.CharacterEncodingFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/servlet/*url-pattern>
filter-mapping>
实现一个监听器的接口;(有n种监听器)
//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {
//创建session监听: 看你的一举一动
//一旦创建Session就会触发一次这个事件!
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
//销毁session监听
//一旦销毁Session就会触发一次这个事件!
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
/*
Session销毁:
1. 手动销毁 getSession().invalidate();
2. 自动销毁
*/
}
<listener>
<listener-class>com.kuang.listener.OnlineCountListenerlistener-class>
listener>
当前在线人数:<%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>
监听器: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() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
}
});
}
}
用户登录之后才能进入主页!用户注销后就不能进入主页了!
// error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<h1>没有权限或者密码错误h1>
<a href="./login.jsp"> 请登录a>
body>
html>
// login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$title>
head>
<body>
${pageContext.request.contextPath}
<form action="${pageContext.request.contextPath}/login" method="get">
请输入用户名:<input type="text" name="username">
<input type="submit">
form>
body>
html>
// success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<h1>登录成功h1>
<a href="${pageContext.request.contextPath}/logout">注销a>
body>
html>
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入LoginServlet->doGet");
System.out.println(req.getContextPath());
// 如果是管理员登录,跳转到成功页面
if (req.getParameter("username").equals("admin")){
// 设置Session
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
// 重定向需要获得根目录
resp.sendRedirect(req.getContextPath()+"/security/success.jsp");
}else{
resp.sendRedirect(req.getContextPath()+"/error.jsp");
}
}
}
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LogoutServlet->doGet");
// 销毁Session 或者 移除其中一个属性(建议后者,开销小
Object userSession = req.getSession().getAttribute("USER_SESSION");
if (userSession!=null){
req.getSession().removeAttribute("USER_SESSION");
resp.sendRedirect(req.getContextPath()+"/login.jsp");
}else {
resp.sendRedirect(req.getContextPath()+"/error.jsp");
}
}
}
public class LogoutFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
Object userSession = req.getSession().getAttribute("USER_SESSION");
if (userSession==null){
resp.sendRedirect(req.getContextPath()+"/error.jsp");
}
filterChain.doFilter(req,resp);
}
public void destroy() {
}
}
<servlet>
<servlet-name>loginservlet-name>
<servlet-class>org.example.servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>loginservlet-name>
<url-pattern>/loginurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>logoutservlet-name>
<servlet-class>org.example.servlet.LogoutServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>logoutservlet-name>
<url-pattern>/logouturl-pattern>
servlet-mapping>
<filter>
<filter-name>LogoutFilterfilter-name>
<filter-class>org.example.filter.LogoutFilterfilter-class>
filter>
<filter-mapping>
<filter-name>LogoutFilterfilter-name>
<url-pattern>/security/*url-pattern>
filter-mapping>
什么是JDBC : Java连接数据库!
需要jar包的支持:
实验环境搭建
CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','[email protected]','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','[email protected]','2000-01-01');
SELECT * FROM users;
导入数据库依赖
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.28version>
dependency>
package org.example;
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "root";
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from users";
//5.执行查询SQL,返回一个 ResultSet : 结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id="+rs.getObject("id"));
System.out.println("name="+rs.getObject("name"));
System.out.println("password="+rs.getObject("password"));
System.out.println("email="+rs.getObject("email"));
System.out.println("birthday="+rs.getObject("birthday"));
}
//6.关闭连接,释放资源(一定要做) 先开后关
rs.close();
statement.close();
connection.close();
}
}
预编译SQL
package org.example;
import java.sql.*;
public class TestJdbc2 {
public static void main(String[] args) throws Exception {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "root";
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.编写SQL
String sql = "insert into users(id, name, password, email, birthday) values (?,?,?,?,?);";
//4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 注意这里第一个是ID,有没有自增,或者用不用赋值
preparedStatement.setInt(1,4);//给第一个占位符? 的值赋值为1;
preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;
preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;
preparedStatement.setString(4,"[email protected]");//给第四个占位符? 的值赋值为1;
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());
//5.执行SQL
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功@");
}
//6.关闭连接,释放资源(一定要做) 先开后关
preparedStatement.close();
connection.close();
}
}
事务
要么都成功,要么都失败!
ACID原则:保证数据的安全。
开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务
转账:
A:1000
B:1000
A(900) --100--> B(1100)
Junit单元测试
依赖
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
dependency>
简单使用
@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!
利用注解来反射?
import org.junit.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);
package org.example;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestJdbc3 {
@Test
public void test() {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "root";
Connection connection = null;
//1.加载驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
connection = DriverManager.getConnection(url, username, password);
//3.通知数据库开启事务,false 开启
connection.setAutoCommit(false);
String sql = "update account set money = money-100 where name = 'A'";
connection.prepareStatement(sql).executeUpdate();
//制造错误
//int i = 1/0;
String sql2 = "update account set money = money+100 where name = 'B'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();//以上两条SQL都执行成功了,就提交事务!
System.out.println("success");
} catch (Exception e) {
try {
//如果出现异常,就通知数据库回滚事务
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
30~37集的SMBMS项目实验
在Web应用中,文件上传和下载功能是非常常用的功能,今天来实现一下JavaWeb中的文件上传和下载功能
对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的。
一般选择采用apache的开源工具common-fileupload这个文件上传组件。
common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
下载最新的jar包
https://mvnrepository.com/artifact/commons-io/commons-io
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
【文件上传的注意事项】
【需要用到的类详解】
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象, 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过==ServletFileUpload对象的构造方法或setFileItemFactory()==方法设置ServletFileUpload对象的fileItemFactory属性。
在HTML页面input 必须有 name
表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data
浏览器表单的类型如果为multipart/form-data , 在服务器端想获取数据就要通过流。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$title>
head>
<body>
<%--通过表单上传
get:上传文件大小有限制
post: 上传文件大小没有限制--%>
<form action = "" method = "post" enctype="multipart/form-data">
上传用户:<input type="text" name="username"><br/>
<p><input type="file" name="file1">p>
<p><input type="file" name="file2">p>
<p><input type="submit"> |<input type="reset">p>
form>
body>
html>
【常用方法介绍】
//isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormField();
//getFieldName方法用于返回表单标签name属性的值。
String getFieldName();
//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();
//getName方法用于获得文件上传字段中的文件名。
String getName();
//以流的形式返回上传文件的数据内容。
InputStream getInputStream();
//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
void delete();
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中 . 使用其parseRequest(HttpServletRequest) 方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。
UploadServlet
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//判断上传的文件是普通的表单还是带文件的表单
if (!ServletFileUpload.isMultipartContent(request)) {
return;//如果是普通文件,我们可以直接返回
} //如果通过了这个if,说明我们的表单是带文件上传的;
//创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件;
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {//如果目录不存在,创建这样一个目录;
uploadFile.mkdir();
}
//临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File file = new File(tmpPath);
if (!file.exists()) {//如果目录不存在,创建这样一个目录;
file.mkdir();
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
//但是我们都建议使用 Apache的文件上传组件来实现,common-fileupload,它需要依赖于 commons-io组件;
//1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
DiskFileItemFactory factory = getDiskFileItemFactory(file);
//2.获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3.处理上传的文件
String msg = uploadParseRequest(upload, request, uploadPath);
//servlet请求转发消息
request.setAttribute("msg",msg);
request.getRequestDispatcher("msg.jsp").forward(request,response);
} catch (FileUploadException e) {
e.printStackTrace();
}
}
public static DiskFileItemFactory getDiskFileItemFactory(File file) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
factory.setSizeThreshold(1024 * 1024); //缓存区大小为1M
factory.setRepository(file);//临时目录的保存目录,需要一个File
return factory;
}
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度;
upload.setProgressListener(new ProgressListener() {
@Override
//pBytesRead:已经读取到的文件大小
//pContentLength : 文件大小
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
}
});
//处理乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//设置总共能够上传文件的大小
//1024 = 1kb * 1024 = 1M * 10 = 10M
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadPath)
throws FileUploadException, IOException {
String msg = "";
//3.把前端请求解析,封装成一个FileItem对象
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()){ //判断上传的文件是普通的表单还是带文件的表单
//getFieldName指的是前端表单控件的name;
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8"); //处理乱码
System.out.println(name+":"+value);
}else { //判断它是上传的文件
//=======================处理文件===============================//
//拿到文件名字
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名:"+uploadFileName);
if (uploadFileName.trim().equals("")||uploadFileName==null){
continue;
}
//获得上传的文件名 /images/girl/paojie.png
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
//获得文件的后缀名
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
/*
如果文件后缀名 fileExtName 不是我们所需要的
就直接return,不处理,告诉用户文件类型不对。
*/
System.out.println("文件信息 [件名:"+fileName+"---文件类型"+fileExtName+"]");
//可以使用UUID(唯一识别的通用码),保证文件名唯一;
//UUID.randomUUID(),随机生一个唯一识别的通用码;
String uuidPath = UUID.randomUUID().toString();
//=======================处理文件完毕===============================//
//存到哪? uploadPath
//文件真实存在的路径 realPath
String realPath = uploadPath+"\\"+uuidPath;
//给每个文件创建一个对应的文件夹
File realPathFile = new File(realPath);
if (!realPathFile.exists()){
realPathFile.mkdir();
}
//=======================存放地址完毕===============================//
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
//realPath = 真实的文件夹;
//差了一个文件; 加上输出文件的名字+"/"+uuidFileName
FileOutputStream fos = new FileOutputStream(realPath+"\\"+fileName);
//创建一个缓冲区
byte[] buffer = new byte[1024*1024];
//判断是否读取完毕
int len = 0;
//如果大于0说明还存在数据;
while ((len=inputStream.read(buffer))>0){
fos.write(buffer,0,len);
}
//关闭流
fos.close();
inputStream.close();
msg = "文件上传成功!";
fileItem.delete(); //上传成功,清除临时文件
//=======================文件传输完毕===============================//
}
}
return msg;
}
}
upload.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传title>
head>
<body>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br/>
上传文件1:<input type="file" name="file1"><br/>
上传文件2:<input type="file" name="file2"><br/>
<input type="submit" value="提交">
form>
body>
html>
msg.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>消息提示title>
head>
<body>
${msg}
body>
html>
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>uploadservlet-name>
<servlet-class>com.kuang.servlet.UploadFileServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>uploadservlet-name>
<url-pattern>/upload.dourl-pattern>
servlet-mapping> web-app>
要在网络上实现邮件功能,必须要有专门的邮件服务器。
这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
SMTP服务器地址:一般是 smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。
电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能;
SMTP协议
发送邮件:
我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
接收邮件:
我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
邮件收发原理
【注意】有可能你收件人地址,发件人地址等信息都正确了,控制台也打印了正确的信息,但是在收件箱就是收不到信息。这是因为可能收件箱服务器拒收了你发的邮件(比如认为你的邮件是广告),这时候可能在垃圾箱里能找到,可能找不到。解决办法是重复的邮件内容不要多次发送,或者更换收件箱试试
我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如OA项目中利用邮件进行任务提醒等等。
使用Java发送 E-mail 十分简单,但是首先你应该准备 JavaMail API 和Java Activation Framework 。
得到两个jar包:
JavaMail 是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME等。我们在使用JavaMail API 编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail 开发包中相应的API类就可以了。
我们可以先尝试发送一封简单的邮件,确保电脑可以连接网络。
主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。
先在项目中导入jar包
QQ邮箱中获取对应的权限
QQ邮箱需要安全验证,我们需要获取他对应的权限;
QQ邮箱–>邮箱设置–>账户
编写测试代码
import com.sun.mail.util.MailSSLSocketFactory;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
public class SendEmail {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.qq.com"); 设置QQ邮件服务器
prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
//使用JavaMail发送邮件的5个步骤
//创建定义整个应用程序所需的环境信息的 Session 对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("[email protected]", "授权码");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com", "[email protected]", "授权码");
//4、创建邮件
//创建邮件对象
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("[email protected]"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
//邮件的标题
message.setSubject("只包含文本的简单邮件");
//邮件的文本内容
message.setContent("你好啊!", "text/html;charset=UTF-8");
//5、发送邮件
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
}
先认识两个类一个名词:
MIME(多用途互联网邮件扩展类型)
MimeBodyPart类
javax.mail.internet.MimeBodyPart类 表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
MimeMultipart类
javax.mail.internet.MimeMultipart是抽象类 Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。
创建包含内嵌图片的邮件
前面的例子中是单独的使用HTML或者是纯文本内容,但是有时候我们需要在纯文本中使用内嵌的方式显示一些图片,因此就要将纯文本和内嵌图片单独存放在MimeBodyPart中然后再将其存放在一个Mimemultipart对象中即可。
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;
public class SendImageEmail {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.setProperty("mail.host", "smtp.qq.com"); 设置QQ邮件服务器
prop.setProperty("mail.transport.protocol", "smtp"); // 邮件发送协议
prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
//使用JavaMail发送邮件的5个步骤
//1、创建定义整个应用程序所需的环境信息的 Session 对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("[email protected]", "授权码");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com", "[email protected]", "授权码");
//4、创建邮件
//创建邮件
MimeMessage message = new MimeMessage(session);
// 设置邮件的基本信息
//发件人
message.setFrom(new InternetAddress("[email protected]"));
//收件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
//邮件标题
message.setSubject("带图片的邮件");
// 准备邮件数据
// 准备图片数据
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("src/resources/bz.jpg"));
image.setDataHandler(dh);
image.setContentID("bz.jpg");
// 准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一封邮件正文带图片
的邮件", "text/html;charset=UTF-8");
// 描述数据关系
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
//设置到消息中,保存修改
message.setContent(mm);
message.saveChanges();
//5.发送邮件
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
}
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.security.GeneralSecurityException;
import java.util.Properties;
public class SendFileMail {
public static void main(String[] args) throws MessagingException, GeneralSecurityException {
//创建一个配置文件保存并读取信息
Properties properties = new Properties();
//设置qq邮件服务器
properties.setProperty("mail.host","smtp.qq.com");
//设置发送的协议
properties.setProperty("mail.transport.protocol","smtp");
//设置用户是否需要验证
properties.setProperty("mail.smtp.auth", "true");
//=================================只有QQ存在的一个特性,需要建立一个安全的链接
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
//=================================准备工作完毕
//1.创建一个session会话对象;
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("[email protected]", "授权码");
}
});
//可以通过session开启Dubug模式,查看所有的过程
session.setDebug(true);
//2.获取连接对象,通过session对象获得Transport,需要捕获或者抛出异常;
Transport tp = session.getTransport();
//3.连接服务器,需要抛出异常;
tp.connect("smtp.qq.com","[email protected]","授权码");
//4.连接上之后我们需要发送邮件;
MimeMessage mimeMessage = imageMail(session);
//5.发送邮件
tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());
//6.关闭连接
tp.close();
}
public static MimeMessage imageMail(Session session) throws MessagingException {
//消息的固定信息
MimeMessage mimeMessage = new MimeMessage(session);
//邮件发送人
mimeMessage.setFrom(new InternetAddress("[email protected]"));
//邮件接收人,可以同时发送给很多人,我们这里只发给自己;
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
mimeMessage.setSubject("我也不知道是个什么东西就发给你了"); //邮件主题
/*
编写邮件内容
1.图片
2.附件
3.文本
*/
//图片
MimeBodyPart body1 = new MimeBodyPart();
body1.setDataHandler(new DataHandler(new FileDataSource("src/resources/yhbxb.png")));
body1.setContentID("yhbxb.png"); //图片设置ID
//文本
MimeBodyPart body2 = new MimeBodyPart();
body2.setContent("请注意,我不是广告
","text/html;charset=utf-8");
//附件
MimeBodyPart body3 = new MimeBodyPart();
body3.setDataHandler(new DataHandler(new FileDataSource("src/resources/log4j.properties")));
body3.setFileName("log4j.properties"); //附件设置名字
MimeBodyPart body4 = new MimeBodyPart();
body4.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.txt")));
body4.setFileName(""); //附件设置名字
//拼装邮件正文内容
MimeMultipart multipart1 = new MimeMultipart();
multipart1.addBodyPart(body1);
multipart1.addBodyPart(body2);
multipart1.setSubType("related"); //1.文本和图片内嵌成功!
//new MimeBodyPart().setContent(multipart1); //将拼装好的正文内容设置为主体
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(multipart1);
//拼接附件
MimeMultipart allFile =new MimeMultipart();
allFile.addBodyPart(body3); //附件
allFile.addBodyPart(body4); //附件
allFile.addBodyPart(contentText);//正文
allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed;
//放到Message消息中
mimeMessage.setContent(allFile);
mimeMessage.saveChanges();//保存修改
return mimeMessage;
}
}
现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件。邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息。今天我们也来实现一个这样的功能,用户注册成功之后,就将用户的注册信息以Email的形式发送到用户的注册邮箱当中,实现发送邮件功能就得借助于JavaMail了。
代码实现:
package com.kuang.pojo;
public class User {
private String username;
private String password;
private String email;
public User() {
}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
注册
package com.kuang.utils;
import com.kuang.pojo.User;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
public class Sendmail extends Thread {
//用于给用户发送邮件的邮箱
private String from = "[email protected]";
//邮箱的用户名
private String username = "[email protected]";
//邮箱的密码
private String password = "授权码";
//发送邮件的服务器地址
private String host = "smtp.qq.com";
private User user;
public Sendmail(User user){
this.user = user;
}
//重写run方法的实现,在run方法中发送邮件给指定的用户
@Override
public void run() {
try{
Properties prop = new Properties();
prop.setProperty("mail.host", host);
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
//1、创建定义整个应用程序所需的环境信息的 Session 对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("[email protected]", "授权码");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect(host, username, password);
//4、创建邮件
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from)); //发件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail())); //收件人
message.setSubject("用户注册邮件"); //邮件的标题
String info = "恭喜您注册成功,您的用户名:" + user.getUsername() + ",您的密码:" + user.getPassword() + ",请妥善保管,如有问题请联系网站客服!!";
message.setContent(info, "text/html;charset=UTF-8");
message.saveChanges();
//发送邮件
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package com.kuang.servlet;
import com.kuang.pojo.User;
import com.kuang.utils.Sendmail;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//接收用户请求,封装成对象
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
User user = new User(username,password,email);
//用户注册成功之后,给用户发送一封邮件
//我们使用线程来专门发送邮件,防止出现耗时,和网站注册人数过多的情况;
Sendmail send = new Sendmail(user);
//启动线程,线程启动之后就会执行run方法来发送邮件
send.start();
//注册用户
request.setAttribute("message", "注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!!");
request.getRequestDispatcher("info.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "注册失败!!");
request.getRequestDispatcher("info.jsp").forward(request, response);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>registerservlet-name>
<servlet-class>com.kuang.servlet.RegisterServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>registerservlet-name>
<url-pattern>/RegisterServlet.dourl-pattern>
servlet-mapping>
web-app>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>提示信息title>
head>
<body>
${message}
body>
html>
运行Tomcat测试!
邮件发送成功,OK!