1、JAVAweb开发原理
2、web服务器
2.1、技术服务
ASP(微软 国内最早流行;在HTML中嵌入了VB的脚本,ASP+Com;在ASp开发中,基本一个页面都有几千行的业务代码,页面及其混乱;维护成本高!)
PHP(PHP开发速度很快,功能强大,跨平台,代码很简单;但是无法承载大访问量情况)
JSP(Servlet,sun公司主推的B/S架构:浏览器和服务器
C/S:客户端和服务器
;基于java语言的;可以承载高并发、高可用、高性能,语法像ASP)
2.2、web服务器(服务器是一种被动的操作,用来处理用户的一些强求和给用户一些响应信息)
**IIS:**微软公司;ASP…Windows中自带
**Tomcat:**技术先进、性能稳定;对于初学者来说是最佳首选是一个servlet和jsp的容器,最新版本9.0…
工作3-5年后,可以尝试手写tomcat服务器;
下载tomcat:
1、了解配置文件及目录结构
2、了解作用
3、Tomcat
3.1、安装tomcat
3.2、 Tomcat启动和配置
3.2、启动和关闭
访问路径:localhost:8080
可能遇到的问题:
1、java环境没有配置
2、闪退问题,需要配置兼容性
3、乱码问题:启动文件中修改(不建议使用)
3.3、配置
可以配置端口号、主机名字
默认端口号8080 默认主机名称为:localhost—>127.0.0.1
默认网站应用存放的位置为:webapps
<Host name="www.huang.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题:
请你谈一谈网站是如何进行访问的!
1、输入一个域名:回车
2、检查本机hosts配置文件下有没有这个域名的映射
3、有直接返回对应的ip地址;如果没有就去DNS服务器(全世界的域名都在dns)
3.4、发布一个web网站
将自己写的网站,放到服务器(tomcat)中指定的web应用的文件夹(webapps)下就可以访问了
网站该有的结构:
4、HTTP
4.1、什么是http
什么是HTTP(超文本传输协议):http是一个简单的请求响应协议,他通常运行在TCP之上(图片、定位、视频、英语…)。
https:安全的
4.2、两个时代
http1.0:
http/1.0
:客户端可以与外部服务器连接,只能获取一个web资源,断开连接。
http2.0
http/1.1:
客户端可以与外部服务器连接,可以获得多个web资源。
4.3、Http请求
http请求
请求行:
**get:**请求能够携带的参数比较少,大小有限制,会在浏览器的url地址显示数据内容,不安全但 高效
**post:**请求能够携带的参数没有限制,大小有限制,不会在浏览器的url地址显示数据内容,安全 不高效
消息头:
http响应
响应体:
响应状态码:
200:请求响应成功
3xX:请求重定向
4XX:找不到资源 404
5XX:服务器代码错误 500 502:网关错误
常见面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间,到页面展示经历了什么?
1、域名解析—>2、发起TCP的三次握手---->3、建立TCP连接后发起http请求---->4、服务器响应http请求,浏览器的到html代码—>5、浏览器解析html代码,并请求html代码中的资源—>6、浏览器对页面进行渲染呈现给用户
5、Maven
我们为什么要学这个技术?
1、在javaWeb的开发中需要使用大量的架包,我们手动去导入。
2、maven可以自动导入配置这个jar包
5.1、Maven架构管理工具
我们目前就是用来方便导入架包的。Maven的核心思想:约定大于配置
maven会规定好你该如何去编写我们的java代码,必须要按照这个规范来;
5.2、Maven下载
https://maven.apache.org/
5.3、配置环境变量
5.4、修改阿里云镜像
放在conf下的setting中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>
5.5、建立仓库
有本地和远程仓库:
本地:
<localRepository>
C:\Users\HRL\Maven\apache-maven-3.8.4-bin\apache-maven-3.8.4\maven-repo</localRepository>
5.6在idea中使用Maven
idea创建成功后查看maven配置
pom.xml核心配置文件
<?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>org.huang</groupId>
<artifactId>MavenTest</artifactId>
<version>1.0-SNAPSHOT</version>
<!--项目打包的方式-->
<packaging>war</packaging>
<name>MavenTest Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<!--配置-->
<properties>
<!-- 项目配置编码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 编译版本-->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<!--项目依赖-->
<dependencies>
<!-- 具体架包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--项目构建用的东西-->
<build>
</build>
</project>
Maven由于他的约定大于配置,我们之后可能会遇到写的配置文件,无法被导出
配置resouce节点
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
maven版本问题:降级
tomact闪退:看bin目录下的卡特玲娜.文件 加入puase看错误信息
maven项目中tomcat无法配置:
去defaultSetting中修改maven配置
导包去https://mvnrepository.com/仓库下载
6、Servlet
6.1、Servlet简介
servlet是sun公司开发动态web的一门技术
sun在这些api提供一个借口叫做:servlet,如果你想开发一个Servlet程序,只需2个小步骤:
1、编写一个类,实现Servlet接口
2、把开发好的java类部署到web服务器中。
把实现了Servlet接口的java程序叫做,servlet
6.2、HelloServlet
Servlet接口sun公司有两个默认实现类:HttpServlet和GenericServlet
1、构建一个普通的Maven项目,删掉里面的的src目录,以后我们的学习就在这个项目里面建立moudel;这个空大的工程就是maven主工程。
2、关于Maven父子工程大的理解:
父项目中会有一个module,子项目中会有一个parent;父项目中的项目可以用子项目,子项目无法用项目中的配置。
Maven环境优化
1、修改web.xml为最新的
2、将Maven的结构搭建完整
编写一个Servlet
1、编写一个类
2、实现Servlet接口,这里我们直接继承HttpServlelt
package com.huang.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 {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>你好</h1>");
out.println("</body>");
out.println("</html>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
配置Webxml中的映射
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.huang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/Hello</url-pattern>
</servlet-mapping>
最后启动tomcat即可
6.3、运行原理
6.4Mapping问题
1、一个Servlet可以指定一个映射路径
2、一个Servlet可以指定多个映射路径
3、一个Servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
4、指定一些后缀或者前缀等等。。。。
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
5、优先级问题
指定了固有的mapper映射路径优先级最高,找不到就会找默认的处理请求。
6.5、ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的一个servletContext对象,它代表当前的web应用;
1、共享数据:
我在这个Servlet中保存的数据,可以在另一个Servlet中拿到。
获取:
ServletContext servletContext=this.getServletContext();
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
String username = (String) servletContext.getAttribute("username");
resp.getWriter().print("名字:"+username);
设置:
ServletContext servletContext=this.getServletContext();
servletContext.setAttribute("username","黄");
System.out.println("hello!");
2、获取初始化参数
设置初始参数:
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
获取参数:
ServletContext servletContext=this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
3、请求转发
ServletContext servletContext=this.getServletContext();
servletContext.getRequestDispatcher("/url").forward(req,resp);
4、读取资源文件
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties=new Properties();
properties.load(is);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
resp.getWriter().print(username+password);
6.6、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 var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
响应的状态码
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2、常见应用
1、向浏览器输出消息(上述代码)
2、下载文件:
获取下载文件的路径
下载文件名是什么?
设置想办法浏览器支持我们下载的东西
获取文件下载的输入流
创建缓冲区
获取OutputStream对象
将FileOutputStream流写入到缓冲区
将缓冲区中的数据输出到客户端!
// 获取下载文件的路径
String realPath="C:\\项目\\ServletTest\\ResponseSerclet\\src\\main\\resources\\表格.PNG";
// 下载文件名是什么?
String fileName=realPath.substring(realPath.lastIndexOf("\\")+1);
// 设置想办法浏览器支持我们下载的东西
resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode(fileName,"UTF-8"));
// 获取文件下载的输入流
FileInputStream in =new FileInputStream(realPath);
// 创建缓冲区
int len=0;
byte [] buffer=new byte[1024];
// 获取OutputStream对象
ServletOutputStream out =resp.getOutputStream();
// 将FileOutputStream流写入到缓冲区,将缓冲区中的数据输出到客户端!获取下载文件的路径
while ((len=in.read(buffer))>0)
{
out.write(buffer,0,len);
}
in.close();
out.close();
3、验证码功能
一种是前端实现
一种是后端实现
package com.huang.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 {
//浏览器三秒刷新一次
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.black);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(RandomNum(),0,20);
//告诉浏览器,这个请求由图片方式打开
resp.setContentType("image/jpeg");
//让浏览器不缓存图片
resp.setDateHeader("expires",-1);
//http 1.1 缓存问题
resp.setHeader("Cache-Control","no-cache");
//http 1.0 缓存问题
resp.setHeader("pragma","no-cache");
//把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
//生成随机数
private String RandomNum(){
Random random=new Random();
String num=random.nextInt(99999)+"";
StringBuffer sb=new StringBuffer();
for (int i = 0; i <5-num.length() ; i++) {
sb.append("0");
}
num=sb.toString()+num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
4、response请求重定向
重定向和转发的区别:
相同点:
页面都会实现跳转
不同点:
请求转发的时候url不会变化 307
重定向的时候url会发生变化 302
代码实现:
package com.huang.Servlet;
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 重定向 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
实现原理
resp.setHeader("Location","/img");
resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
*/
resp.sendRedirect("/img");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
6.7、HttpServletRequest(代表客户端的请求)
用户通过http协议访问服务器,http请求中的所有信息会被封装带HttpServletRequet中,通过HttpServletRequet可以获取客户端的所有信息。
1、获取前端传递的参数
package com.huang.Servlet;
import javax.servlet.ServletContext;
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.util.Arrays;
public class ServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
System.out.println("进去请求");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] types = req.getParameterValues("types");
System.out.println(Arrays.toString(types));
System.out.println(username+"-----"+password);
req.getRequestDispatcher("/success.jsp").forward(req,resp);
// ServletContext context=this.getServletContext();
// context.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7、Cookie 和Session
7.1、会话(session)
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话。
有状态会话:
一个网站 怎么证明你来过?
客户端 服务器
1、服务器给客户端一个信件,客户端下次访问服务器带上信件就可以了:cookie
2、服务器登记你来过了,下次你来的时候来匹配你:Session
7.2、保存会话的两种技术
cookie**(客户端技术 利用响应和请求)**
session**(服务器技术,可以保存用户的会话信息)**
常见场景:网站登录后,你下次不用再登录了,第二次访问直接上去
7.3、Cookie
1、冲请求中拿到cookie信息
2、服务器响应给客户端cookie
package com.huang.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;
public class CookieServelt extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setHeader("Content-type","text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();
if (cookies != null) {
out.write("你上此访问的时间是:");
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equals("LoginTime")) {
long l = Long.parseLong(cookies[i].getValue());
Date date = new Date(l);
out.write(date.toLocaleString());
}
}
} else {
out.write("欢迎你第一次进入本网站!!");
}
Cookie cookie = new Cookie("LoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(60 * 60 * 60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
Cookie:一般会保存再本地用户目录下 appData;
一个网站cookie是否存在上线!
1、一个cookie只能保存一个信息
2、一个web站点可以给服务器发送多个cookie,最多存放20个cookie
3、cookie大小有限制4kb
4、300个cookie浏览器上限
删除cookie(再创建一个cookie与之前cookie同名设置存活周期为0):
1、不设置有效期,关闭浏览器
2、设置有效期时间为0
Cookie编码问题:
Cookie cookie1=new Cookie("name2", URLEncoder.encode("科比","utf-8"));
URLDecoder.decode(cookies[i].getValue(),"utf-8");
7.4、Session
什么是session:
服务器会给每一个用户(浏览器)创建一个Session对象
一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
用户登录后,整个网站他都可以访问–>保存用户的信息;保存购物车的信息…
Session和Cookie的区别:
Cookie是把用户的数据写给用户的浏览器保存(可以保存多个)
Session是把用户的数据写到用户独占的Session中,服务器端保存(保存重要的信息,减少服务 器资源的浪费)
Session对象是由服务器创建
使用场景:
保存一个登录用户的信息;
购物车信息
在整个网站中经常会使用的数据,我们将它保存在Session中
使用Session:
HttpSession session=req.getSession();
session.setAttribute("name","Hello!");
session.isNew();
session.removeAttribute("name");
//释放Session 手动释放
session.invalidate();
session.getAttribute("name");
定时
<session-config>
<!-- 分钟计时-->
<session-timeout>1044</session-timeout>
</session-config>
8、JSP
8.1、什么是jsp
java Server pages:java服务器端页面,也和Servlet一样用于开发动态Web
最大的特点:
写jsp就像在写html
区别:
html只能给用户提供静态的数据
jsp页面中可以嵌入java代码,为用户提供动态数据
8.2、JSP原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imXbsAjy-1647770118038)(JAVAweb入门基础.assets/捕获1.PNG)]
思路:JSP到底怎么执行!
代码层面没有任何问题
tomcat中有一个work目录;
idea中使用tomcat的会在idea的tomcat中生产一个work目录**(发现页面转变成了java程序!)**
浏览器向服务器发送请求,不管访问是什么资源,其实都是在访问Servlet!
JSP最终也会转化为java类
JSP本质上就是一个Servlet
public void _jspInit() {
}
public void _jspDestroy() {
}
public 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//响应
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; //
4、以上的这些个对象可以在jsp页面中直接使用!
在jsp页面中,只要是java代码就会原封不动的输出;
html代码都换转化为 out.write(“dsadasd\r\n”);
8.3、jsp基础语法和指令
任何语言都有自己的语法,java中有。jsp作为java技术的一种应用,他拥有一些自己扩充的语法。
jsp表达式
<%= new java.util.Date()%>
jsp脚本片段
<%
int a=0;
for (int i = 0; i <=100 ; i++) {
a+=i;
}
out.print("<h1>"+a+"</h1>");
%>
脚本片段的在实现
<%int x=10;%>
<%
out.print(x);
for (int i = 0; i <=5 ; i++) {
%>
<h1> Hello <%=i%></h1>
<%
}
%>
JSP声明
<%! %> //例如定义全局变量
jsp声明:会被编译到jsp生成的Java类中!其他的,就会被生成到_jspService方法中!
在jsp中嵌入java代码即可!
jsp注释和代码不会在浏览器审查元素中显示(安全性)
8.3、jsp指令
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J4xRkv01-1647770118038)(JAVAweb入门基础.assets/捕获2-1639297135633.PNG)]
8.4、9大内置对象
1、pageContent 存东西
2、Requet 存东西
3、Response
4、Session 存东西
5、Application(extend ServletContext)存东西
6、config(ServletConfig)
7、out
8、page
9、exception
PageContext.setAttribute() //作用于一次页面 (新闻)
request.setAttribute() //作用于一次请求,请求转发湿也会携带
session.setAttribute() //作用于一次浏览器开启到关闭(购物车)
appliction.setAttribute() //作用于服务器,服务器关闭才消失(聊天数据)
PageContext.setAttribute("","",PageContext.Scope)//可以修改作用域
pageContext.forward();pageContext.forward();//跳转页面
8.5、JSP标签、JSTL、EL表达式(express language)
EL表达式:
1、获取数据
2、执行运算
3、获取web开发的常用对象
4、调用java方法
<%
1、pageContent 存东西
2、Requet 存东西
3、Response
4、Session 存东西
5、Application(extend ServletContext)存东西
6、config(ServletConfig)
7、out
8、page
9、exception
%>
JSP标签
<jsp:forward page="">
<jsp:param name="name" value="dad"/>
</jsp:forward>
JSTL标签(弥补html的不足;标签的功能和java代码一样)
1、核心标签(掌握部分)
(需要在tomcat服务器lib中添加JSTL和Standarjia包否则服务器会报错)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2、Sql标签
3、格式化标签
4、xml标签
9、JavaBean
实体类
JavaBean有特定的写法:
1、必须有一个无参构造
2、属性必须私有化
3、必须有对象的get/set方法;
一般用来和数据库字段作映射
10、三层架构
什么是MVC:model(实体类、字段)、 view(jsp页面) 、controller(Servlet)
10.1、早些年
用户直接访问控制层,控制层就可以直接操作数据库;
servlet-CRUD->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理、逻辑代码
架构:没有什么是加一层解决不了的
10.2、三层架构机制
11、Filter
shiro
Filter:过滤器,用来过滤网站的数据;
1、处理乱码
2、登录验证…
Filter开发步骤:
1、导包
2、编写过滤器
1、导包不要错
2、实现Filter
3、重写方法
package com.huang.Filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("在服务器启动的时候就开启,随时等待过滤!");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前");
filterChain.doFilter(request,response);//递归
System.out.println("CharacterEncodingFilter执行后");
}
public void destroy() {
System.out.println("在服务器关闭的时候结束!");
}
}
映射:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.huang.Filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
12、监听器(GUI中大量应用)
实现一个监听器的接口;(n种)
1、实现监听器的接口(重写里面的方法)
package com.huang.Listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class HttpListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent se) {
ServletContext servletContext = se.getSession().getServletContext();
Integer count= (Integer) servletContext.getAttribute("OnLineCount");
if (count==null){
count=new Integer(1);
}else {
int realCount=count.intValue();
count=new Integer(realCount+1);
}
servletContext.setAttribute("OnLineCount",count);
}
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
//销毁Session
httpSessionEvent.getSession().invalidate();
Integer count= (Integer) servletContext.getAttribute("OnLineCount");
if (count==null){
count=new Integer(0);
}else {
int realCount=count.intValue();
count=new Integer(realCount-1);
}
servletContext.setAttribute("OnLineCount",count);
}
}
2、配置监听器
<listener>
<listener-class>com.huang.Listener.HttpListener</listener-class>
</listener>
13、监听器、拦截器运用用户登录后才能进去网站、注销后无法进入
public class LoginFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest rep, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) rep;
HttpServletResponse response = (HttpServletResponse) resp;
if (request.getSession().getAttribute("username")==null){
response.sendRedirect("/error.jsp");
}
}
public void destroy() {
}
}
///
package com.huang.Utile;
public class Constant {
public final static String Username="UserName";
}
/
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.huang.Filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
14、JDBC复习(Java Database Connect)
1、
public class JDBCTest {
public static void main(String[] args) throws Exception{
//解决中文乱码
String url="jdbc:mysql://localhost:3306/db_game?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
///1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、连接数据库 connection代表数据库
Connection connection=DriverManager.getConnection(url,username,password);
//3、向数据库发送SQl的对象Statement : CRUD
Statement statement = connection.createStatement();
//4、编写SQl
String sql="select * from user";
//5、执行sql 返回一个结果集
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.print("id="+resultSet.getObject("u_id")+" ");
System.out.print("u_name="+resultSet.getObject("u_name")+"\n");
}
resultSet.close();
statement.close();
connection.close();
}
}
2、
public class JDBCTest02 {
public static void main(String[] args) throws Exception{
//解决中文乱码
String url="jdbc:mysql://localhost:3306/db_game?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
///1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、连接数据库 connection代表数据库
Connection connection=DriverManager.getConnection(url,username,password);
//3、编写SQl
String sql="insert into user (u_id,u_name,u_password,u_score) values (?,?,?,?)";
//4、预编译sql
PreparedStatement statement=connection.prepareStatement(sql);
statement.setInt(1,5);
statement.setString(2,"你好");
statement.setString(3,"qqqqq");
statement.setInt(4,1234);
//5、执行sql
int i = statement.executeUpdate();
if (i>0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败");
}
statement.close();
connection.close();
}
}
JDBC事务
jdbc封装
package com.huang.Utile;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class DataAffair {
private static String url;
private static String driver;
private static String user;
private static String password;
static {
Properties properties=new Properties();
InputStream is = DataAffair.class.getClassLoader().getResourceAsStream("db.properties");
try{
properties.load(is);
}catch (Exception e){
e.printStackTrace();
}
driver=properties.getProperty("driver");
url=properties.getProperty("url");
user=properties.getProperty("user");
password=properties.getProperty("password");
}
public static Connection getConnection(){
Connection connection=null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
public ResultSet execute(Connection connection,String sql,ResultSet resultSet,Object [] params,PreparedStatement statement) throws Exception {
statement = connection.prepareStatement(sql);
for (int i = 0; i <params.length ; i++) {
statement.setObject(i+1,params[i]);
}
resultSet=statement.executeQuery(sql);
return resultSet;
}
public int executeupdate(Connection connection,String sql,Object [] params,PreparedStatement statement) throws Exception {
statement = connection.prepareStatement(sql);
for (int i = 0; i <params.length ; i++) {
statement.setObject(i+1,params[i]);
}
int result=statement.executeUpdate(sql);
return result;
}
public static boolean closeResource(Connection connection ,PreparedStatement preparedStatement,ResultSet resultSet){
boolean flag =true;
if (connection!=null){
try {
connection.close();
//GC线程回收机制,避免关闭失败
connection=null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
if (preparedStatement!=null){
try {
preparedStatement.close();
//GC线程回收机制,避免关闭失败
preparedStatement=null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
if (resultSet!=null){
try {
resultSet.close();
//GC线程回收机制,避免关闭失败
resultSet=null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
return flag;
}
}
字符编码过滤器
package com.huang.Filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("在服务器启动的时候就开启,随时等待过滤!");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
filterChain.doFilter(request,response);//递归
}
public void destroy() {
System.out.println("在服务器关闭的时候结束!");
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.huang.Filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
前段部分代码
<action method="post/get" action="{pageContext.request.ContestPath}/接口名"
web.xml中设置用户进入首页
<!-- 设置欢迎界面-->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
SSL报错
driver中添加useSSL=true
java代码重定向路径错误时
resp.sendRedirect(req.getContextPath+"/login.jsp");
文件传输原理
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//判断上传的表单是普通表单还是带文件的表单,是返回true,否返回false;
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,它需要依赖于common-io组件;
try {
//1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小
DiskFileItemFactory factory = gteDiskFileItemFactory(file);
//2、获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3、处理上传文件
String msg = uploadParseRequest(upload,request,uploadpath);
//Servlet请求转发消息
request.setAttribute("msg",msg);
request.getRequestDispatcher("/info.jsp").forward(request,response);
}catch (FileUploadException e){
e.printStackTrace();
}
}
public static DiskFileItemFactory gteDiskFileItemFactory(File file){
//1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;
factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M
factory.setRepository(file);
return factory;
}
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
//2、获取ServletFileUpload
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener() {
public void update(long pBytesRead, long lpContentLenght, int i) {
//pBytesRead:已读取到的文件大小
//pContentLenght:文件大小
System.out.println("总大小:"+lpContentLenght+"已上传:"+pBytesRead);
}
});
//处理乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//设置总共能够上传文件的大小
//1024 = 1kb * 1024 = 1M * 10 = 10M
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadpath) throws IOException, FileUploadException {
String msg = "";
//3、处理上传文件
//把前端的请求解析,封装成一个FileItem对象
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()){ //判断是普通表单还是带文件的表单
//getFieldName指的是前端表单控件的name
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");//处理乱码
System.out.println(name+":"+value);
}else {//判断它是带文件的表单
//======================处理文件=======================//
//拿到文件的名字
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名:"+uploadFileName);
if (uploadFileName.trim().equals("") || uploadFileName == null){
continue;
}
//获得上传的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的后面的都不需要
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//获得文件的后缀名
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
/*
如果文件后缀名fileExtName不是我们所需要的
就直接return,不处理,告诉用户文件类型不对
*/
//可以使用UUID(唯一识别的通用码),保证文件名唯一
//UUID.randomUUID,随机生一个唯一识别的通用码
//网络传输中的东西,都需要序列化
//pojo,实体类,如果想要在多个电脑运行,传输--->需要吧对象都序列化了
//JNI=java Native Interface
//implements Serializable :标记接口,JVM--->java栈 本地方法栈 native-->c++
String uuidPath= UUID.randomUUID().toString();
System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"】");
//可以使用UUID(唯一通用识别码)来保证文件名的统一
String uuidFileName = UUID.randomUUID().toString();
//=======================传输文件=========================//
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+ fileExtName);
//创建一个缓冲区
byte[] buffer = new byte[1024 * 1024];
//判断是否读取完毕
int len = 0;
//如果大于0,说明还存在数据
while ((len=inputStream.read(buffer))>0){
fos.write(buffer,0,len);
}
//关闭流
fos.close();
inputStream.close();
msg = "文件上传成功!";
fileItem.delete();//上传成功,清除临时文件
}
}
return msg;
}
--------------------------------------------------------------------------------------
pom.xml配置
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
邮件发送案例
简单
package com.huang;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.net.InetAddress;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.Properties;
import static javax.mail.Message.*;
public class Test {
//简单邮件:没有附件,纯文本
//要发送文件需要获得协议和支持,开启服务pop3和smpt
//授权码:ctikfylpzoqriiff
public static void main(String[] args) throws Exception {
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.ssl.socketFactory",sf);
//创建整个服务器需要的环境信息的Session对象
Session session=Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("huangronshj@qq.com","ctikfylpzoqriiff");
}
});
// 通过Session获得transport对象
session.setDebug(true);
Transport ts=session.getTransport();
// 使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","huangronshj@qq.com","ctikfylpzoqriiff");
// 创建邮箱
MimeMessage message=new MimeMessage(session);
message.setFrom(new InternetAddress("huangronshj@qq.com"));
//收件人
InternetAddress address1=new InternetAddress("huangronshj@qq.com");
InternetAddress address[]={address1};
message.setRecipients(RecipientType.TO, address);
//邮件
message.setSubject("只包含文本的简单邮件");//邮件主题
message.setContent("<h1>你好啊</h1>","text/html;charset=UTF-8");
// 发送邮箱
ts.sendMessage(message,message.getAllRecipients());
ts.close();
System.out.println("结束");
}
}
复杂
package com.huang;
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.net.InetAddress;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.Properties;
import static javax.mail.Message.*;
public class 复杂邮件上传 {
//简单邮件:没有附件,纯文本
//要发送文件需要获得协议和支持,开启服务pop3和smpt
//授权码:ctikfylpzoqriiff
public static void main(String[] args) throws Exception {
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.ssl.socketFactory",sf);
//创建整个服务器需要的环境信息的Session对象
Session session=Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("huangronshj@qq.com","ctikfylpzoqriiff");
}
});
// 通过Session获得transport对象
session.setDebug(true);
Transport ts=session.getTransport();
// 使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","huangronshj@qq.com","ctikfylpzoqriiff");
// 创建邮箱
MimeMessage message=new MimeMessage(session);
message.setFrom(new InternetAddress("huangronshj@qq.com"));
//收件人
InternetAddress address1=new InternetAddress("huangronshj@qq.com");
InternetAddress address[]={address1};
message.setRecipients(RecipientType.TO, address);
//邮件
message.setSubject("复杂邮件");//邮件主题
//准备图片数据
MimeBodyPart img=new MimeBodyPart();
DataHandler dh=new DataHandler(new FileDataSource("C:\\项目\\文件上传\\Mail\\src\\resource\\bz.jpg"));
img.setDataHandler(dh);
img.setContentID("bz.jpg");
//准备正文数据
MimeBodyPart text=new MimeBodyPart();
text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件","text/html;charset=UTF-8");
//.rar
MimeBodyPart rar=new MimeBodyPart();
DataHandler handler=new DataHandler(new FileDataSource("C:\\项目\\javaweb-jsp.rar"));
rar.setDataHandler(handler);
rar.setFileName("javaweb-jsp.rar.rar");
//描述数据关系
MimeMultipart multipart1=new MimeMultipart();
multipart1.addBodyPart(text);
multipart1.addBodyPart(img);
multipart1.setSubType("related");
MimeBodyPart body1=new MimeBodyPart();
body1.setContent(multipart1);
MimeMultipart multipart=new MimeMultipart();
multipart.addBodyPart(body1);
multipart.addBodyPart(rar);
multipart.setSubType("mixed");
//设置到消息中,保存修改
message.setContent(multipart);
message.saveChanges();
// 发送邮箱
ts.sendMessage(message,message.getAllRecipients());
ts.close();
System.out.println("结束");
}
}
码连上邮件服务器
ts.connect(“smtp.qq.com”,“huangronshj@qq.com”,“ctikfylpzoqriiff”);
// 创建邮箱
MimeMessage message=new MimeMessage(session);
message.setFrom(new InternetAddress(“huangronshj@qq.com”));
//收件人
InternetAddress address1=new InternetAddress(“huangronshj@qq.com”);
InternetAddress address[]={address1};
message.setRecipients(RecipientType.TO, address);
//邮件
message.setSubject(“复杂邮件”);//邮件主题
//准备图片数据
MimeBodyPart img=new MimeBodyPart();
DataHandler dh=new DataHandler(new FileDataSource("C:\\项目\\文件上传\\Mail\\src\\resource\\bz.jpg"));
img.setDataHandler(dh);
img.setContentID("bz.jpg");
//准备正文数据
MimeBodyPart text=new MimeBodyPart();
text.setContent("这是一封邮件正文带图片<img src='cid:bz.jpg'>的邮件","text/html;charset=UTF-8");
//.rar
MimeBodyPart rar=new MimeBodyPart();
DataHandler handler=new DataHandler(new FileDataSource("C:\\项目\\javaweb-jsp.rar"));
rar.setDataHandler(handler);
rar.setFileName("javaweb-jsp.rar.rar");
//描述数据关系
MimeMultipart multipart1=new MimeMultipart();
multipart1.addBodyPart(text);
multipart1.addBodyPart(img);
multipart1.setSubType("related");
MimeBodyPart body1=new MimeBodyPart();
body1.setContent(multipart1);
MimeMultipart multipart=new MimeMultipart();
multipart.addBodyPart(body1);
multipart.addBodyPart(rar);
multipart.setSubType("mixed");
//设置到消息中,保存修改
message.setContent(multipart);
message.saveChanges();
// 发送邮箱
ts.sendMessage(message,message.getAllRecipients());
ts.close();
System.out.println("结束");
}
}