JavaWeb
1. 基本概念
1.1 前言
静态web
- html,css
动态web
- 技术栈: Servlet/JSP ASP PHP
1.2 web应用程序
web应用程序:可以提供浏览器访问的程序;
- 一个统一的web资源会被放在同一个文件夹下,web应用程序—>tomcat:服务器
- 一个web应用由多部份组成(静态web,动态web)
- html,css,js
- jsp,servlet
- java程序
- jar包
- 配置文件(Properties)
web应用程序编写完毕后,若想提供给外界访问,需要 一个服务器统一管理
1.3 静态web
- .htm,.html 都是网页的后缀,如果服务器中存在这些,都可以进行读取


- 静态web存在的缺点
- web页面无法动态更新,所有用户看到的都是同一个页面
轮播图,点击特效:伪动态
js - 无法和数据库交互(数据无法持久化,用户无法交互)
- web页面无法动态更新,所有用户看到的都是同一个页面
1.4 动态web


缺点:
- 加入服务器的动态web资源出现错误,我们需要重新编写我们的后台程序,并重新发布
- 停机维护
优点:
- web页面可以动态更新,所有用户看到的不是同一个页面
- 可以和数据库交互(数据可以持久化:注册,商品信息….,用户可以交互)


2. Web服务器
2.1 技术讲解
ASP:
微软的
php:
- PHP开发速度快,功能强大,代码短,跨平台
- 无法承载大访问量的情况(局限性)
JSP/Servlet:
- 基于java语言的(所有大公司,一些开源软件基本都是java写的)
- 可以承载三高问题带来的影响(高性能,高并发,高可用)
- 语法像ASP
2.2 web服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;
IIS
window里自带的服务器
tomcat
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目, 最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。
3. tomcat服务器
在idea中防止乱码方法:
在tomcat/conf/logging.properties
里面修改java.util.logging.ConsoleHandler.encoding = GBK与idea中一样即可
1.配置环境变量
JAVA_HOME: jdk路径
CATALINA: tomcat路径
Path : tomcat下的bin路径
conf下的service.xml配置文件
可以配置启动的端口号
- tomcat默认端口号:8080
- MySQL:3306
- http:80
- https:443
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
可以配置主机的名称
- 默认的主机名为:localhost—-127.0.0.1
- 默认网站应用存放的位置为:webapps
<Host name="localhost" appBase="webapps"unpackWARs="true" autoDeploy="true">
2.高难度面试题:
谈谈网站是如何进行访问的?
1.输入一个域名;回车2.检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射1.有,则直接返回对应ip地址,在这个地址中,有我们需要访问的web程序,可以直接访问
127.0.0.1 自定义域名
2.没有,则去DNS服务器找,找到则返回,没找到则不返回<br /><br />
3.发布一个web网站


HTTP协议: 面试
Maven: 构建工具
- Maven安装包
Servlet 入门
- HelloWorld
- Servlet配置
- 原理
4. Http
4.1 什么是Http
HTTP(超文本传输协议) 使一个简单的请求-响应协议,通常运行在TCP上
http: 80
https: 443
4.2 Http请求
- 客户端—-发请求—-服务器
百度:
请求 URL: https://www.baidu.com/请求方法: GET get/post状态代码: 200 OK远程地址: 14.215.177.39:443引用站点策略: no-referrer-when-downgrade
1.请求行
- 请求行中的请求方式:get
- 请求方式:Get Post
- get:请求能够携带的参数比较少,大小有限,不安全,但高效
- Post:请求能够携带的参数没有限制,安全,但不高效
2.消息头
Accept:告诉浏览器所支持的数据类型
4.3 Http响应
- 服务器 —- 响应 — 客户端
百度:
Cache-Control: private 缓存控制Connection: keep-alive 连接Content-Encoding: gzip 编码Content-Type: text/html;charset=utf-8 类型Set-Cookie: H_PS_PSSID=34068_31254_35064_34517_34917_34578_34813_26350;Strict-Transport-Security: max-age=172800
1.响应体
与消息头基本一样
refrush:告诉客户端,多久刷新一次
location:让网页重新定位
2.响应状态码(重点)
200:请求响应成功
3xx:请求重定向
- 重定向:你重新到我给你的新位置
4xx:找不到资源 404
- 资源不存在
5xx:服务器代码错误 500 502网关错误
常见面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?1.域名解析2.发起TCP的三次握手(client-->service-->client-->service)3.建立起TCP连接后发起http请求4.服务器响应http请求,浏览器得到html代码5.浏览器解析html代码,并请求html代码中的资源(css JavaScript 图片)6.浏览器对页面进行渲染呈现
5. Maven
为什么要学习这个技术?
Maven 是一个构建项目的管理工具,提供jar包
- 在javaweb开发中,需要使用大量的jar包,我们手动去导入
如何能够让一个东西自动帮我导入和配置这个jar包
由此,Maven诞生了
Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。
Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发文时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。
5.1 Maven项目架构管理工具
我们目前用来就是方便导入jar包
Maven的核心思想: 约定大于配置
- Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构
- 有约束,不要去违反
Maven会规定好你如何区编写我们的Java代码,必须要按照这个规范来
5.2 环境变量配置
配置:
- M2_HOME Maven下的bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置 %MAVEN_HOME%
5.4 阿里云镜像(重要)
- 镜像: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
<localRepository>D:\java\apache-maven-3.6.3\maven-repo</localRepository>
5.6 在IDEA中使用Maven
1.打开IDEA
2.创建一个Maven web项目
3.创建完成即可
把web.xml中的配置内容换成最新的
5.7创建一个普通的maven项目


5.8 标记文件夹




5.9 pom文件
pom.xml是maven的核心配置文件




maven由于他的约定大于配置,之后可以会遇到自己写的配置文件,无法被导出或者生效的问题
解决方案:在build下加个resources
在MyBatis 中会遇到
<!--在build中配置resources,来防止我们资源导出失败的问题 --><build><resources><resource><directory>src/main/resources</directory><excludes><exclude>**/*.properties</exclude><exclude>**/*.xml</exclude></excludes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources></build>
5.10 IDEA操作
5.11解决问题
1.maven默认web项目中的web.xml版本问题
生产目录树

2.替换web.xml 4.0版本和tomcat一致
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"></web-app>
5.12 .maven仓库的使用
搜索jar包 httpservlet




在创建一个类时,若没有该类相应的jar包,则添加maven依赖,在依赖中搜索,有则下载,没有则按照下面方法
上诉网站中搜索所需的jar包,把依赖代码复制到pom.xml文件里面.即可下载所需jar包
6. Servlet
创建Servlet类之后,立马到web.xml中注册映射
6.1什么是Servlet
- Servlet是sun公司开发动态web的一门技术
- sun公司在这些API中提供一个接口叫:Servlet想要开发一个Servlet程序,只需完成两个小步骤
- 编写一个类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
把实现Servlet接口的java程序叫做Servlet
==
Servlet(Server Applet)是[Java](https://baike.baidu.com/item/Java/85979) Servlet的简称,称为**小服务程序或服务连接器**,用Java编写的[服务器](https://baike.baidu.com/item/%E6%9C%8D%E5%8A%A1%E5%99%A8/100571)端程序,具有独立于平台和[协议](https://baike.baidu.com/item/%E5%8D%8F%E8%AE%AE/13020269)的特性,主要功能在于交互式地浏览和生成数据,生成动态[Web](https://baike.baidu.com/item/Web/150564)内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于[HTTP协议](https://baike.baidu.com/item/HTTP%E5%8D%8F%E8%AE%AE/1276942)的Web服务器。
==
6.2 HelloServlet*
java书写Servlet项目流程
Servlet接口Sun公司有两个默认的实现类:HttpServlet,,GenericServlet

1.构建一个普通的Maven项目,删掉里面的src目录,学习就在这个项目里建立muddles,空的就是主工程
2.关于Maven父子工程理解:
父项目:
<modules><module>Servlet01</module></modules>
子项目:
<parent><artifactId>Servlet</artifactId><groupId>com.yy</groupId><version>1.0-SNAPSHOT</version></parent>
父项目中的java子项目可以直接使用
3.Maven环境优化
- 修改web.xml为最新的
- 将Maven的结构搭建完整
4.编写一个Servlet程序*
- 编写一个普通类
- 实现Servlet接口,这里直接继承HttpServlet
重写方法 doGet和doPost方法
- 由于get或者post只是请求实现的不同的方式,可以互相调用,业务逻辑都一样
public class HelloServlet extends HttpServlet { //由于get或者post只是请求实现的不同的方式,可以互相调用,业务逻辑都一样 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ServletInputStream inputStream = req.getInputStream(); // ServletOutputStream outputStream = resp.getOutputStream(); PrintWriter writer = resp.getWriter(); //响应流 writer.println("hello,servlet"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { }}
- 由于get或者post只是请求实现的不同的方式,可以互相调用,业务逻辑都一样
编写Servlet的映射(注册)
在web.xml中配置Servlet映射,才能访问java程序
为什么要映射:我们写的Java程序,但是要通过浏览器访问,而浏览器要连接web服务器,所以要在web服务中注册我们写的Servlet,还需要给他一个浏览器访问的路径;<!-- 注册Servlet--> <servlet><!-- 映射名--> <servlet-name>hello</servlet-name><!-- Java类的路径--> <servlet-class>com.yy.servlet.HelloServlet</servlet-class> </servlet><!-- Servlet映射 Servlet的请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name><!-- Servlet的请求路径 , 自定义 --> <url-pattern>/yy</url-pattern> </servlet-mapping>
配置tomcat
注意: 配置项目发布的路径
给tomcat部署工件,即该项目的war包
在以下位置修改默认访问index.jsp的路径名称即可(可选择性)

- 启动tomcat
默认访问地址为上述的访问index.jsp的路径
在其后面输入web.xml中映射的java类,即可访问该类中的内容
6.3 Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:

6.4 Mapping问题
一个Servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/yy</url-pattern> </servlet-mapping>
一个Servlet可以指定多个映射路径
<servlet-name>hello</servlet-name> <url-pattern>/yy</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/yy1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/yy2</url-pattern> </servlet-mapping>
**一个Servlet可以指定通用映射路径 (通配符)
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/yy/*</url-pattern> </servlet-mapping>在/yy路径后面添加任意的/路径都能访问/yy下的servlet文件
默认请求路径 *
<!-- 默认请求路径注意点:优先级较高,替代了index.jsp文件--><servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
指定一些后缀或者前缀等等
<!-- 可以自定义后缀实现请求映射 注意点:*前面不能加项目映射的路径 例: /yy/*.yy 可以在地址栏后面以/xxx.yy结尾也可以访问--><servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.yy</url-pattern> </servlet-mapping>
优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.yy.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/yy</url-pattern> </servlet-mapping> <servlet> <servlet-name>Error</servlet-name> <servlet-class>com.yy.servlet.ErrorServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Error</servlet-name><!-- /*优先级较高,覆盖了index.jsp文件,直接在默认路径下显示该映射的java Servlet程序 但是可以在其后面输入其余有效路径进行访问对应的Java Servlet程序--> <url-pattern>/*</url-pattern> </servlet-mapping>
结果:




6.5 ServletContext
(先存后读)
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,他代表当前的web应用;数据会存入到ServletContext对象中,读取数据也从ServletContext对象中读取
1. 共享数据
(Session或者request的一些方法代替)
我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到


SetServlet.java
public class SetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //this.getServletConfig() Servlet 配置 //this.getInitParameter() 初始化参数 //this.getServletContext() Servlet 上下文 ServletContext context = this.getServletContext(); String username="小y"; context.setAttribute("username",username); //将一个数据保存在ServletContext中,key value: username username resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); PrintWriter writer = resp.getWriter(); writer.println("输入成功!"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }}
GetSrevlet.java
public class GetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String username = (String)context.getAttribute("username"); resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); resp.getWriter().println(username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }}
web.xml
<!--SetServlet 要先往ServletContext里存入值--> <servlet> <servlet-name>setC</servlet-name> <servlet-class>com.yy.SetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>setC</servlet-name> <url-pattern>/setC</url-pattern> </servlet-mapping> <!--GetServlet才能在ServletContext里取出值--> <servlet> <servlet-name>getC</servlet-name> <servlet-class>com.yy.GetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>getC</servlet-name> <url-pattern>/getC</url-pattern> </servlet-mapping>
2. 初始化配置
(几乎不用)
<!-- 配置一些web应用的初始化参数--> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/Mybatis</param-value> </context-param>
获取
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String url = context.getInitParameter("url"); resp.getWriter().println(url); }
3. 请求转发
(requset顶替)
A B C
A想拿去C中的资源,但是不能直接拿到,则需要通过B去拿C中的资源,在通过B返回A
B则为ServletContext对象


getRequestDispatcher
<servlet> <servlet-name>forward</servlet-name> <servlet-class>com.yy.ServletForward</servlet-class> </servlet> <servlet-mapping> <servlet-name>forward</servlet-name> <url-pattern>/fd</url-pattern> </servlet-mapping>
ServletForward.java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//获取请求转发的路径//requestDispatcher.forward(req,resp);//调用forward实现请求转发context.getRequestDispatcher("/gp").forward(req,resp);resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");PrintWriter writer = resp.getWriter();writer.println("输入成功!");}
4. 读取资源文件
类加载(反射代替)
properties
- 在Java目录下新建properties
- 在resources目录下新建properties
发现: 都被打包到了同一个路径下:classes,俗称该路径为classpath(类路径)
思路: 需要一个文件:properties,通过getResourceAsStream()获取该文件路径
,再通过Properties类获取配置即可
username=mybatispassword=123456
@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");//通过ServletContext对象获取properties配置文件Properties prop = new Properties();prop.load(is); //通过load读取文件String username = prop.getProperty("username");String password = prop.getProperty("password");resp.getWriter().println(username+"\n"+password);}
6.6 HttpServletResponse **
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse
- 如果要获取客户端请求过来的参数: 找HttpServletRequest
- 如果给客户端响应一些信息: 找HttpServletResponse
1. 常见应用
1.像浏览器输出消息
2.下载文件
**setHeader:**
它的作用就是设置响应的头部
Content-Disposition:指明响应的配置信息
attachment:指明包含附件
- 要获取下载文件路径
- 下载的文件名
- 设置想办法让浏览器能够支持下载我们需要的的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用Output Stream将缓冲区中的数据输出到客户端
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 要获取下载文件路径 String realPath = "D:\\Study\\IDEA\\JavaWeb\\Servlet\\Response\\src\\main\\resources\\1.jpg"; System.out.println("文件路径:"+realPath);// 2. 下载的文件名 String filename = realPath.substring(realPath.lastIndexOf("\\" + 1)); //巧妙的获取文件名// 3. 设置想办法让浏览器能够Content-Disposition支持下载我们需要的的东西,attachment;(附件)// URLEncoder.encode(文件名,编码) resp.setHeader("Content-Disposition","attachment;filename"+ URLEncoder.encode(filename,"UTF-8"));// 4. 获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath);// 5. 创建缓冲区 int ret=0; byte[] buffer = new byte[1024];// 6. 获取OutputStream对象 ServletOutputStream out = resp.getOutputStream();// 7. 将FileOutputStream流写入到buffer缓冲区,使用Output Stream将缓冲区中的数据输出到客户端 while((ret=in.read(buffer))!=-1){ out.write(buffer,0,ret); } out.close(); in.close(); }
2. 验证码


//随机数生成private String random(){Random random =new Random();String num = random.nextInt(99999999) + ""; //验证码位数StringBuffer sb=new StringBuffer();for (int i = 0; i <7-num.length() ; i++) {sb.append("0");}num=sb.toString()+num;return num;}
3. 重定向(重要**)


B一个web资源收到客户端A请求后,B会通知A客户端去访问另一个web资源C,这个过程叫做重定向
常见场景
- 用户登录
public void sendRedirect(String location) throws IOException
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// resp.setHeader("location","/r/down");// resp.setStatus(302); resp.sendRedirect("/r/down"); //重定向 }
面试题: 请聊聊重定向和转发的区别?
相同点:
- 页面都会跳转
不同点:
- 请求转发时,URL不会变化
- 重定向时,URL会发生变化
测试:
${pageContext.request.contextPath}/red
${pageContext.request.contextPath}为获取web项目的路径
/red 为servlet的请求映射路径
index.jsp
<html><body><h2>Hello World!</h2><form action="${pageContext.request.contextPath}/red" method="post">用户名:<input type="text" name="username"><br>密 码: <input type="password" name="password"><br><input type="submit"></form></body></html>
重定向java代码
@Overrideprotected 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("/r/success.jsp");}
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title> <style> div{ width: 200px; height:200px; background-color: aqua; } </style></head><body> <div></div></body></html>
配置映射代码
<servlet> <servlet-name>RedirectServlet</servlet-name> <servlet-class>com.yy.RedirectServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RedirectServlet</servlet-name> <url-pattern>/red</url-pattern> </servlet-mapping>
6.7 HttpServeltRequest **
HttpServeltRequest代表客户端的请求,用户通过http访问服务器,http请求中的所有信息会被封装到HttpServletRepuest,通过这个HttpServletRequest的方法,获得客户端的所有信息
1. 获取前端传递的参数 请求转发 **
req.getParameter() //获取name属性 获取一个req.getParameterValues() //获取多个
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");String username = req.getParameter("username");String password = req.getParameter("password");String[] hobbies = req.getParameterValues("hobbies");System.out.println("===========================================");System.out.println(username);System.out.println(password);System.out.println(Arrays.toString(hobbies));System.out.println("===========================================");//获取当前web项目路径System.out.println(req.getContextPath());//这里的/代表当前的web项目req.getRequestDispatcher("/success.jsp").forward(req,resp);}
2. 请求转发和重定向的区别
面试题: 请聊聊重定向和请求转发的区别?
相同点:
- 页面都会跳转
不同点:
- 请求转发时,URL不会变化 307
- 重定向时,URL会发生变化 302
请求转发下 getRequestDispatcher(“/success.jsp”).forward(req,resp);
//URL不会变化,所以在加/就代表多重路径了,而且/就代表该web项目路径
重定向 sendRedirect(“/r/success.jsp”);
7. Cookie Session
Cookie: 有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
Session 对象最常见的一个用法就是存储用户的首选项
7.1 会话
会话: 用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,该过程称为会话
一个网站,怎么证明访问过?
客户端 服务端
- 服务端给客户端一个 信件 , 客户端下次访问服务端的时候带上信件即可; Cookie
- 服务器登记你来过,下次来的时候匹配你; Session
7.2 保存会话的两种技术
cookie
- 客户端技术(响应,请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息,我们可以把信息或者数据放在Session中
7.3 cookie(了解即可)
服务端要先从客户端的请求中获取cookie:
判断是否有cookie
若没有cookie(第一次请求)则服务器端把客户端请求的信息添加到一个cookie(信件)中响应给客户端然后获取cookie中的属性
req.getCookies();//服务器获取客户端请求的cookiescookie.getName();//获取cookie中name属性cookie.getValue();//获取cookie中的值long lastLoginTime = Long.parseLong(cookie.getValue());//把字符串变成一个时间戳//第一次请求没有cookie,则服务器给客户端添加一个cookieCookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");cookie.setMaxAge(24*60*60);//设置cookie有效期resp.addCookie(cookie);//添加cookie //响应cookie会客户端
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//服务器,告诉你,你来的时间,把这个时间封装成一个 信件,你下次来,就知道你来了//解决请求响应的乱码req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");//服务器获取客户端请求的cookiesCookie[] cookies = req.getCookies();//cookie可能有多个,返回数组PrintWriter out = resp.getWriter();//判断cookie是否存在if(cookies!=null){out.write("你上次访问的时间:");for (Cookie cookie : cookies) {if(cookie.getName().equals("lastLoginTime")){long lastLoginTime = Long.parseLong(cookie.getValue());//把字符串变成一个时间戳Date date = new Date(lastLoginTime);//把时间戳变成date类型out.write(date.toLocaleString());}}}else{out.write("你是第一次访问 ");}//第一次请求没有cookie,则服务器给客户端添加一个cookieCookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");cookie.setMaxAge(24*60*60);resp.addCookie(cookie);//响应cookie会客户端}
一个网站cookie是否存在上限!
- 一个cookie只能保存一个信息
- 一个web站点,可以给服务器发送多个cookie,最多存放20个cookie
- cookie大小限制4KB
- 浏览器300个cookie
删除cookie
- 不设置有效期,关闭浏览器,自动失效
- 设置有效期时间为0
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+""); //这里要跟被删除cookie的key:value一致 cookie.setMaxAge(0); resp.addCookie(cookie);//响应cookie会客户端 }
中文数据传递 解决中文乱码问题
URLEncoder.encode("小y","utf-8");//编码URLDecoder.decode(cookie.getValue(),"utf-8");//解码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //服务器,告诉你,你来的时间,把这个时间封装成一个 信件,你下次来,就知道你来了 //解决请求响应的乱码 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); //服务器获取客户端请求的cookies Cookie[] cookies = req.getCookies();//cookie可能有多个,返回数组 PrintWriter out = resp.getWriter(); //判断cookie是否存在 if(cookies!=null){ out.write("姓名:"); for (Cookie cookie : cookies) { if(cookie.getName().equals("name")){ out.write( URLDecoder.decode(cookie.getValue(),"utf-8")); } } }else{ out.write("你是第一次访问 !"); } //第一次请求没有cookie,则服务器给客户端添加一个cookie Cookie cookie = new Cookie("name", URLEncoder.encode("小y","utf-8")); cookie.setMaxAge(24*60*60); resp.addCookie(cookie); }
7.4 Session (重点)
Session可以用来共享数据和存储一些用户信息
什么是Session:
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
- 用户登录之后,整个网站都可以访问—->保存用户信息,保存购物车的信息
setAttribute() //创建节点元素getId() //获取IDgetCreationTime() //获取Session创建时间invalidate() //清除SessionisNew() //创建新的SessiongetAttribute() getServletContext()
使用场景:
- 保存一个登录用户的信息
- 购物车信息
- 在整个网站中经常使用的数据,我们把它保存到Session中
使用Session:
package com.yy;import javax.servlet.ServletException;import javax.servlet.http.*;import java.io.IOException;//设置信息public class SessionDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码问题 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); //获取Session HttpSession session = req.getSession(); //给Session存入东西 (可以是字符串,也可以是对象 例如Person对象) //session.setAttribute("name",new Person("小y",18)); session.setAttribute("name","小y"); //获取session 的ID String sessionId = session.getId(); //判断session是不是新创建的 if(session.isNew()){ resp.getWriter().write("Session是新创建的,ID:"+sessionId); }else { resp.getWriter().write("Session不是新创建的,ID:"+sessionId); } //Session创建的时候做了什么// Cookie cookie = new Cookie("JSESSIONID", sessionId);// resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }}
得到Session:
package com.yy;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;//获取信息public class SessionDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码问题 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); HttpSession session = req.getSession(); //Person person=(Person) session.getAttribute("name"); String name = (String) session.getAttribute("name"); resp.getWriter().write(name); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }}
Session注销:
package com.yy;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;//注销Sessionpublic class SessionDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码问题 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); HttpSession session = req.getSession(); session.removeAttribute("name");//清除name属性的信息 //手动注销 session.invalidate();//注销Session,会新生成一个SessionID } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }}
会话自动过期 (失效), web.xml配置
<!-- 会话自动过期 设置Session自动失效时间 --> <session-config><!-- 1 代表一分钟--> <session-timeout>1</session-timeout> </session-config>
7.5 Session和cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存

- Session是把用户的数据写到用户独占Session中,服务器保存(保存重要的信息,减少服务器资源的浪费)


访问统一资源


8. JSP
8.1 JSP原理
HTML和JSP的区别:
- HTML只给用户提供静态的数据
- JSP页面中可以嵌入Java代码,为用户提供动态数据
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
JSP最终也会被转换成为一个Servlet类
JSP其实就是Servlet
//JSP继承了HttpJspBase类 HttpJspBase继承了HttpServlet
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;//sessionfinal javax.servlet.ServletContext application; //applicationcontextfinal javax.servlet.ServletConfig config;javax.servlet.jsp.JspWriter out = null;final java.lang.Object page = this; //page : 当前页HttpServletRequest requestHttpServletResponse response
3.输出页面前增加的代码
response.setContentType("text/html;charset=UTF-8"); //设置响应的页面类型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页面中直接使用
<%//书写Java代码%><%String name="yy";%>name:<%=name%><%//取值%>
在JSP页面中:
只要是Java代码就会原封不动的输出,
如果是HTML,就会转换为这样的格式:
out.write("<html>\n");
输出到前端!
JSP原理

8.2 JSP基础语法
JSP中,Java语法都支持!
EL表达式
${}
JSP表达式
<%-- JSP表达式 作用:用来将程序的输出,输出到客户端 <%= 变量或者表达式%> --%> <%= new java.util.Date()%>
JSP脚本片段
<%-- JSP脚本片段--%> <% //java代码 int sum=0; for (int i = 0; i < 100; i++) { sum+=i; } out.println("<h2> sum="+sum+"</h2>"); %>
脚本片段的再实现
<%for (int i = 0; i <5 ; i++) {%> <h2>你好</h2> <%=i%> <%}%>
JSP声明
<%!%> //提高作用域到全局
<%! private String name="yy"; public void login(){ System.out.println(name); } static { System.out.println("嗯嗯"); } %>
JSP声明:会被编译到JSP生成Java的类中,其他的就会被生成到jspService中
在jsp中,嵌入Java代码
<%%> jsp脚本片段 java代码<%=%> jsp表达式<%!%> jsp全局作用域<%----%>
8.3 JSP指令
<%@ page args… %> 页面指令
自定义500错误页面
原页面<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@page errorPage="/error/500.jsp" %><html><head><title>Title</title></head><body><%int i=1/0;%></body></html>错误页面<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><img src="../img/500.png" alt="500"></body></html>
web.xml中配置404和500错误页面
<error-page><error-code>500</error-code><location>/error/500.jsp</location></error-page><error-page><error-code>404</error-code><location>/error/404.jsp</location></error-page>
<%@ include file=”” %>包含指令
<%-- @include会将两个页面合二为一--%> <%@include file="/common/header.jsp"%> <h2>主体</h2> <% int i=0;// 若在header.jsp中定义了一个int i=0; 此处则会报错,因为jsp本质是Servlet,相当于定义了两个i %> <%@include file="/common/footer.jsp"%><%-- jsp标签--%> <jsp:include page="/common/header.jsp"/> <h2>主体</h2> <jsp:include page="/common/footer.jsp"/>
8.4 9大内置对象
- PageContext 存东西
- Request 存东西
- Respone
- Session 存东西
- Application [ServletContext] 存东西
- config [ServletConfig]
- out
- page
- exception
作用域scoe
session.setAttribute();<br /> application.setAttribute();保存在服务器中
<% //作用域由低到高 pageContext.setAttribute("name1","y1"); // 保存的数据只在一个页面中有效 request.setAttribute("name2","y2"); // 保存的数据只在一次请求中有效,请求转发会携带整个数据 session.setAttribute("name3","y3"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器 application.setAttribute("name4","y4"); //保存的数据在服务器中有效,从打开服务器到关闭服务器%>
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完就没用了
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可以使用,比如:聊天
1.在pageContextDemo01.jsp页面下能获取到全部数据
<%--内置对象--%><% //作用域由低到高 pageContext.setAttribute("name1","y1"); // 保存的数据只在一个页面中有效 request.setAttribute("name2","y2"); // 保存的数据只在一次请求中有效,请求转发会携带整个数据 session.setAttribute("name3","y3"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器 application.setAttribute("name4","y4"); //保存的数据在服务器中有效,从打开服务器到关闭服务器%><%--脚本片段中的代码,会被原封不动生成到_JSP.java中要求,这里面的代码:必须保证Java语法的正确性--%><% //从pageContext取出,我们通过寻找的方式来 //作用域 从底层到高层 String name1 = (String) pageContext.findAttribute("name1"); String name2 = (String) pageContext.findAttribute("name2"); String name3 = (String) pageContext.findAttribute("name3"); String name4 = (String) pageContext.findAttribute("name4"); String name5 = (String) pageContext.findAttribute("name5"); //不存在 //在该脚本片段中加入请求转发(PageContext.forward())到pageContextDemo02.jsp页面,就可以在pageContextDemo02.jsp页面中获取request的数据 //pageContext.forward("/pageContextDemo02.jsp");%><%--使用EL表达式 ${} --%><h1>值:</h1><h1>${name1}</h1><h1>${name2}</h1><h1>${name3}</h1><h1>${name4}</h1><h1>${name5}</h1><%--<h1>${name5}</h1> 不存在 则不会输出到页面中--%><h1><%=name5%></h1><%--<h1><%=name5%></h1> 没有值 会显示null--%>
2.在pageContextDemo02.jsp页面下只能获取到session和application的数据
(request未请求,没有携带数据,所以不能获取该数据)
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title></head><body><% //从pageContext取出,我们通过寻找的方式来 //作用域 从底层到高层 String name1 = (String) pageContext.findAttribute("name1"); String name2 = (String) pageContext.findAttribute("name2"); String name3 = (String) pageContext.findAttribute("name3"); String name4 = (String) pageContext.findAttribute("name4"); String name5 = (String) pageContext.findAttribute("name5"); //不存在%><%--使用EL表达式 ${} --%><h1>值:</h1><h1>${name1}</h1><h1>${name2}</h1><h1>${name3}</h1><h1>${name4}</h1><h1>${name5}</h1><%--<h1>${name5}</h1> 不存在 则不会输出到页面中--%><h1><%=name5%></h1><%--<h1><%=name5%></h1> 没有值 会显示null--%></body></html>
提高作用域(不建议使用)
pageContext.setAttribute("name1","y1",pageContext.SESSION_SCOPE);等价于session.setAttribute("name1","y1");
在该脚本片段中加入请求转发(PageContext.forward())到pageContextDemo02.jsp页面,就可以在pageContextDemo02.jsp页面中获取request的数据
跟getRequestDispatcher一样,url不会改变
<%pageContext.forward("/pageContextDemo02.jsp"); request.getRequestDispatcher("/pageContextDemo02.jsp").forward(request,response);%>
8.5 JSP标签, JSTL标签, EL表达式 (重点)
导包:
<!--JSP依赖项 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <!--JSTL表达式的依赖项 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--standard标签库--> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
1. EL表达式: ${}
- 获取数据
- 执行运算
- 获取web开发常用对象 EL表达式获取表单中的数据 ${param.属性值}**
- 调用java方法(一般不用)
2. JSP标签
<%--<jsp:include page=""></jsp:include>--%><jsp:forward page="/jsptag2.jsp"> <%--跟pageContext.forward一样--%> <jsp:param name="name" value="yy"></jsp:param> <jsp:param name="age" value="18"></jsp:param></jsp:forward><%--localhost:8080/jsptag2.jsp?name=yy&age=18--%>
3. JSTL表达式
JSTL标签库的使用是为了弥补HTML标签的不足,他自定义许多标签,可供我们使用,标签的功能和Java一样
格式化标签(了解即可)
SQL标签(了解即可)
XML标签(了解即可)
核心标签(掌握) 若是tomcat服务器中没有jstl包,则需要手动导入
<c:out> 用于在JSP中显示数据,就像<%= ... ><c:set> 用于保存数据<c:remove> 用于删除数据<c:if> 与我们在一般程序中用的if一样<c:choose> 本身只当做<c:when>和<c:otherwise>的父标签<c:when> <c:choose>的子标签,用来判断条件是否成立<c:import> 检索一个绝对或相对 URL,然后将其内容暴露给页面<c:forEach> 基础迭代标签,接受多种集合类型<c:param> 用来给包含或重定向的页面传递参数<c:redirect> 重定向至一个新的URL.<c:url> 使用可选的查询参数来创造一个URL
EL表达式获取表单中的数据
${param.属性值}
coreif测试
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html><head><title>Title</title></head><body><h2>cif测试</h2><br><form action="coreif.jsp" method="post"><%--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></html>
coreset corechoose corewhen
<c:set var="score" value="85"></c:set><c:choose> <c:when test="${score>=90}"> </c:when></c:choose>
coreforeach
<% ArrayList<String> people = new ArrayList<>(); people.add(0,"张三"); people.add(1,"大三"); people.add(2,"阿三"); people.add(3,"达三"); request.setAttribute("list",people);%><%--var="people" 定义一个变量items="${list}" 要遍历的对象begin="1"end="3"step="1" 步长--%><c:forEach var="people" items="${list}" begin="1" end="3" step="1"> <c:out value="${people}"/></c:forEach>
9. JavaBean 实体类
实体类:pojo,entity,dto
有特定的写法:
- 必须有一个无参的构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM(注解与反射);
ORM : 对象关系映射
- 数据库中的表——>对应java的类
- 字段——>属性
- 行记录——>对象
package com.yy.pojo;//实体类 我们一般都是和数据库中的表结构一一对应public class People { private int id; private String name; private int age; private String address; public People() { } public People(int id, String name, int age, String address) { this.id = id; this.name = name; this.age = age; this.address = address; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "People{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; }}
<%@ page import="com.yy.pojo.People" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title></head><body><%// People people = new People();// people.setAddress();%><jsp:useBean id="people" class="com.yy.pojo.People" scope="page"/><jsp:setProperty name="people" property="address" value="重庆"/><%--<%=people.getAddress()%>--%>地址:<jsp:getProperty name="people" property="address"/></body></html>
10. MVC三层架构
Model-View-Controller 模型-视图-控制器 呈三角形结构


Model
- 业务处理:业务逻辑 (Service)
- 数据持久层:CRUD (Dao)
View
- 展示数据
- 提供链接发起Servlet请求
Controller (此处为Servlet)
- 就收用户的请求: (req:请求参数,Session信息…)
- 交给业务层处理对应的代码
- 控制视图的跳转
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)--->交给业务层处理登录业务(判断用户名和密码是否正确:事务)--->Dao层查询用户名和密码是否正确--->数据库
11. Filter 过滤器(重点)
作用:用来过滤网站的数据;
- 处理中文乱码
- 登录验证…


Filter 开发步骤:
- 导包 Servlet等包
编写过滤器
- 导包 javax.Servlet下的Filter包
Character EncodingFilter.java
web.xml
```xmlpublic class CharacterEncodingFilter implements Filter { //初始化:web服务器启动,就已经初始化了,随时监听等待过滤对象出现 public void init(FilterConfig filterConfig) throws ServletException { System.out.println("初始化"); } //chain: 链 /* 1.过滤中的所有代码,在过滤特定请求的时候都会被执行(也就是要在xml中配置) 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("执行前"); chain.doFilter(request,response);//让我们的请求继续执行,不过不写,程序到这里就会被拦截 System.out.println("执行后"); } //销毁:在web服务器关闭时就会随着服务器销毁 public void destroy() { System.out.println("销毁"); }}
ShowServlet com.yy.servlet.ShowServlet ShowServlet /servlet/show
<filter-name>CharacterEncodingFilter</filter-name><filter-class>com.yy.filter.CharacterEncodingFilter</filter-class>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
- 导包 javax.Servlet下的Filter包
</filter-mapping>
<a name="ea67e9ea"></a># 12. 监听器实现监听器的接口统计在线人数 通过Session```java//统计网站在线人数:统计Sessionpublic class OnlineCountListener implements HttpSessionListener {//创建session监听//一旦创建session就会触发一次这个事件public void sessionCreated(HttpSessionEvent httpSessionEvent) {ServletContext context = httpSessionEvent.getSession().getServletContext(); //提高作用域Integer onlineCount = (Integer) context.getAttribute("OnlineCount");if(onlineCount==null){onlineCount=new Integer(1);}else {int count=onlineCount.intValue();onlineCount=new Integer(count+1);}context.setAttribute("OnlineCount",onlineCount);}//销毁session监听//一旦销毁session就会触发一次这个事件public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {ServletContext context = httpSessionEvent.getSession().getServletContext(); //提高作用域Integer onlineCount = (Integer) context.getAttribute("OnlineCount");if(onlineCount==null){onlineCount=new Integer(0);}else {int count=onlineCount.intValue();onlineCount=new Integer(count-1);}context.setAttribute("OnlineCount",onlineCount);}//销毁session// 手动销毁 getSession().invalidate();// 自动销毁 xml中配置
注册监听器web.xml
<servlet><servlet-name>ShowServlet</servlet-name><servlet-class>com.yy.servlet.ShowServlet</servlet-class></servlet><servlet-mapping><servlet-name>ShowServlet</servlet-name><!-- 因为加入过滤器,此处最好加个前目录分类--><url-pattern>/servlet/show</url-pattern><url-pattern>/show</url-pattern></servlet-mapping><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>com.yy.filter.CharacterEncodingFilter</filter-class></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><!-- 只要是满足 /servlet 目录下的任何请求,都会经过这个过滤器--><url-pattern>/servlet/*</url-pattern><!-- <url-pattern>/*</url-pattern>一般不会写/* 因为会把web目录下的所有请求都会过滤--></filter-mapping><listener><listener-class>com.yy.listener.OnlineCountListener</listener-class></listener><session-config><session-timeout>1</session-timeout></session-config>
13. 过滤器 监听器的应用
filter过滤拦截登录
LoginServlet.java
package com.yy.servlet;import com.yy.constant.Constant;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 LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username= req.getParameter("username");String password = req.getParameter("password");if(username.equals("admin") && password.equals("123456")){req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());resp.sendRedirect("/sys/success.jsp");}else {resp.sendRedirect("/error.jsp");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}}
LogoutServlet.java
package com.yy.servlet;import com.yy.constant.Constant;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 LogoutServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {if(req.getSession().getAttribute(Constant.USER_SESSION)!=null){req.getSession().removeAttribute(Constant.USER_SESSION);}resp.sendRedirect("/login.jsp");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}}
LoginFilter.java
package com.yy.filter;import com.yy.constant.Constant;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class LoginFilter implements Filter {public void init(FilterConfig filterConfig) throws ServletException {}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;if(req.getSession().getAttribute(Constant.USER_SESSION)==null){resp.sendRedirect("/login.jsp");}chain.doFilter(request,response);}public void destroy() {}}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><h1>登录</h1><form action="/servlet/login" method="post">用户名:<input type="text" name="username"><br>密 码:<input type="password" name="password"><br><input type="submit" value="登录"></form></body></html>
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Error</title></head><body><h1>登录失败</h1><h2>权限不够,用户名错误</h2><h2><a href="/servlet/logout">返回登录界面</a></h2></body></html>
succes.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title></head><body><h1>登录成功</h1><h2><a href="/servlet/logout">注销</a></h2></body></html>
注册
<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.yy.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/servlet/login</url-pattern> </servlet-mapping> <servlet> <servlet-name>LogoutServlet</servlet-name> <servlet-class>com.yy.servlet.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogoutServlet</servlet-name> <url-pattern>/servlet/logout</url-pattern> </servlet-mapping> <filter> <filter-name>LoginFilter</filter-name> <filter-class>com.yy.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/sys/*</url-pattern> </filter-mapping>
14. 文件上传
UUID 唯一识别的通用码
//可以使用UUID(唯一识别的通用码),保证文件名唯一(安全性) //UUID.randomUUID,随机生一个唯一识别的通用码 //网络传输中的东西,都需要序列化 //pojo,实体类,如果想要在多个电脑运行,传输--->需要吧对象都序列化了 //JNI=java Native Interface //implements Serializable :标记接口,JVM--->java栈 本地方法栈 native-->c++ String uuidPath= UUID.randomUUID().toString(); System.out.println("文件信息【文件名:"+fileName+"文件型:"+fileExtName+"】");
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(); } }
1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小
public static DiskFileItemFactory gteDiskFileItemFactory(File file){//1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小DiskFileItemFactory factory = new DiskFileItemFactory();//通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1Mfactory.setRepository(file);return factory;}
2、获取ServletFileUpload
```javapublic static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){//2、获取ServletFileUploadServletFileUpload 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 = 10Mupload.setSizeMax(1024 * 1024 * 10);return upload;}
3、处理上传文件```javapublic 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指的是前端表单控件的nameString 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++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;}
15. 邮件发送
SendMail
(邮件发送原始模板,其中01为简单发送,02位带图片发送,03为带图片带附件发送)
注意使用本地安装的tomcat需要把Mail.jar和组合封装的activation.jar导出tomcat 的lib下不然找不到报500错误
1、后端(邮件发送,文本)
package com.yy.mail;import com.sun.mail.util.MailSSLSocketFactory;import javax.mail.*;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import java.util.Properties;public class MailDemo1 {public static void main(String[] args) throws Exception {Properties prop=new Properties();prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session=Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication("2941660384@qq.com","ingjaeezhdppdehf");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器ts.connect("smtp.qq.com","2941660384@qq.com","ingjaeezhdppdehf");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人message.setFrom(new InternetAddress("2941660384@qq.com"));//指明邮件的收件人message.setRecipient(Message.RecipientType.TO,new InternetAddress("2941660384@qq.com"));//邮件标题//message.setSubject("标题");message.setSubject("Hello");//邮件的文本内容//message.setContent("文本内容","text/html;charset=UTF-8");message.setContent("你不化妆是天生丽质,化了妆是仙女下凡----》你长得像我家一个亲戚,我妈的儿媳妇~》这世上一切美好的事情,你的脸就占了99%" +"♠ ♣ ♥ ♦ ♤ ♡❤ ❥ ♡ ♥ ❣❥♥❤♡ღ ♥","text/html;charset=UTF-8");//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}}
2、后端(邮件发送,文本+图片)
package com.yy.mail;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;// 复杂邮件发送 文本 图片 不带附件// 每一个文本、图片、附件可以分为一个MimeBodyPart,由MimeMultipart完成组装public class MailDemo2 {public static void main(String[] args) throws Exception {Properties prop=new Properties();prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session=Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication("2941660384@qq.com","ingjaeezhdppdehf");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器ts.connect("smtp.qq.com","2941660384@qq.com","ingjaeezhdppdehf");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人message.setFrom(new InternetAddress("294660384@qq.com"));//指明邮件的收件人message.setRecipient(Message.RecipientType.TO,new InternetAddress("2941660384@qq.com"));//邮件标题message.setSubject("java发出");//邮件的文本内容//=================================准备图片数据=======================================MimeBodyPart image=new MimeBodyPart();//图片需要经过数据化的处理DataHandler dh=new DataHandler(new FileDataSource("图片路径"));//在part中放入这个处理过图片的数据image.setDataHandler(dh);//给这个part设置一个ID名字image.setContentID("bz.jpg");//准备正文的数据MimeBodyPart text=new MimeBodyPart();text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");//描述数据关系MimeMultipart mm=new MimeMultipart();mm.addBodyPart(text);mm.addBodyPart(image);// alternative 只能发送 文本// related 可以发送文本 + 图片// mixed 可以发送文本 + 图片 + 附件mm.setSubType("related");//设置到消息中,保存修改message.setContent(mm);message.saveChanges();//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}}
3、后端(邮件发送,文本+图片+附件)
package com.yy.mail;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 MailDemo3 {public static void main(String[] args) throws Exception {Properties prop=new Properties();prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session=Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication("2941660384@qq.com","ingjaeezhdppdehf");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器//ts.connect("smtp.qq.com","1270079739@qq.com","flsttjhjfzurggii");ts.connect("smtp.qq.com","2941660384@qq.com","ingjaeezhdppdehf");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人//message.setFrom(new InternetAddress("1270079739@qq.com"));message.setFrom(new InternetAddress("2941660384@qq.com"));//指明邮件的收件人//message.setRecipient(Message.RecipientType.TO,new InternetAddress("1411630997@qq.com"));message.setRecipient(Message.RecipientType.TO,new InternetAddress("2941660384@qq.com"));//邮件标题message.setSubject("qq邮件文本+图片+附件");//邮件的文本内容//=================================准备图片数据=======================================MimeBodyPart image=new MimeBodyPart();//图片需要经过数据化的处理DataHandler dh=new DataHandler(new FileDataSource("图片路径"));//在part中放入这个处理过图片的数据image.setDataHandler(dh);//给这个part设置一个ID名字image.setContentID("bz.jpg");//准备正文的数据MimeBodyPart text=new MimeBodyPart();text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");//=================================准备附件数据=======================================MimeBodyPart body1= new MimeBodyPart();body1.setDataHandler(new DataHandler(new FileDataSource("文档路径")));body1.setFileName("1.txt");//描述数据关系MimeMultipart mm=new MimeMultipart();mm.addBodyPart(body1);mm.addBodyPart(text);mm.addBodyPart(image);mm.setSubType("mixed"); //最大的范围//设置到消息中,保存修改message.setContent(mm);message.saveChanges();//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}}
4.registerUserSendMail(注册用户发送的邮件)
1、controller层(Servlet)
package com.yy.servlet;import com.yy.pojo.User;import com.yy.utils.Sendmail;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;//脚手架public class RegisterServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username=req.getParameter("username");String password=req.getParameter("pwd");String email=req.getParameter("email");User user=new User(username,password,email);Sendmail send=new Sendmail(user);send.start();System.out.println("success");req.setAttribute("message","注册成功!已发送邮件,请注意查收");req.getRequestDispatcher("info.jsp").forward(req,resp);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}}
2.实体类
package com.yy.pojo;import lombok.AllArgsConstructor;import lombok.Data;import java.io.Serializable;@Data //导入lombok包@AllArgsConstructorpublic class User implements Serializable {private static final long serialVersionUID = -4644951229999911627L;// 127邮件授权码 : flsttjhjfzurggii// 1411邮件授权码: pgdwmlqszdgsfjcfprivate String username;private String password;private String email;}
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version></dependency>
3.工具类
package com.yy.utils;import com.sun.mail.util.MailSSLSocketFactory;import com.yy.pojo.User;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="2941660384@qq.com";private String host="smtp.qq.com";private User user;public Sendmail(User user){this.user=user;}@Overridepublic void run() {try {Properties prop=new Properties();prop.setProperty("mail.host",host);///设置QQ邮件服务器prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户密码//QQ邮箱需要设置SSL加密MailSSLSocketFactory sf=new MailSSLSocketFactory();sf.setTrustAllHosts(true);prop.put("mail.smtp.ssl.enable","true");prop.put("mail.smtp.ssl.socketFactory",sf);//使用javaMail发送邮件的5个步骤//1.创建定义整个应用程序所需要的环境信息的session对象Session session= Session.getDefaultInstance(prop, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(from,"eyblepjiwzagdeed");}});//开启session的debug模式,这样可以查看到程序发送Email的运行状态session.setDebug(true);//2.通过session得到transport对象Transport ts=session.getTransport();//3.使用邮箱的用户名和授权码连上邮件服务器ts.connect(host,from,"eyblepjiwzagdeed");//4.创建邮件:写文件//注意需要传递sessionMimeMessage message=new MimeMessage(session);//指明邮件的发件人message.setFrom(new InternetAddress(from));//指明邮件的收件人message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail()));//邮件标题message.setSubject("注册通知");//邮件的文本内容message.setContent("恭喜你("+user.getUsername()+")成功注册!"+"密码:"+user.getPassword(),"text/html;charset=UTF-8");//5.发送邮件ts.sendMessage(message,message.getAllRecipients());//6.关闭连接ts.close();}catch (Exception e){System.out.println(e);}}}
4、web.xml注册服务
<servlet><servlet-name>RegisterServlet</servlet-name><servlet-class>com.yy.servlet.RegisterServlet</servlet-class></servlet><servlet-mapping><servlet-name>RegisterServlet</servlet-name><url-pattern>/RegisterServlet.do</url-pattern></servlet-mapping>
5、前端jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>注册</title></head><body><html><body><h2>Hello World!</h2><form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">用户名:<input type="text" name="username">密码:<input type="text" name="pwd">邮箱:<input type="text" name="email"><input type="submit" value="注册"></form></body></html></body></html>
6、响应页面(利用多线程) 浏览器3秒原则
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>详情页</title></head><body>${message}</body></html>
5.springboot实现邮件发送**
1.测试类
package com.yy.springboot;import org.junit.jupiter.api.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.mail.SimpleMailMessage;import org.springframework.mail.javamail.JavaMailSenderImpl;import org.springframework.mail.javamail.MimeMessageHelper;import org.springframework.test.context.junit4.SpringRunner;import javax.mail.internet.MimeMessage;import java.io.File;@RunWith(SpringRunner.class)@SpringBootTestpublic class DemoApplicationTests {// 注入Java邮件发送包@AutowiredJavaMailSenderImpl javaMailSender;@Testvoid contextLoads() {// 发送邮件// 邮件接收人// 内容// 创建邮件消息SimpleMailMessage message = new SimpleMailMessage();// 设置主题message.setSubject("SpringBoot 发送邮件");// 设置文本内容message.setText("你好呀");// 发送者message.setFrom("2941660384@qq.com");// 接受者message.setTo("2941660384@qq.com");// 发送javaMailSender.send(message);}// 带附件的发送 邮件@Testvoid testSendMailBandAttachment() throws Exception {// 带附件带图片 需要创建发送消息MimeMessage mimeMessage = javaMailSender.createMimeMessage();// 创建处理类 处理 mimeMessage true 为更改编码MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);helper.setSubject("晚上吃大餐");// 设置true 为表示 可以设置html标签 等价于 text/html;charset=UTF-8格式helper.setText("<a href = 'https://www.baidu.com/'>点击打开,点击打开,爱你呦!!!</a>",true);// ***new File() 指向文件的路径 + 文件名字helper.addAttachment("文件名.txt",new File("文件路径"));helper.addAttachment("图片名.png",new File("突破路径"));helper.setFrom("2941660384@qq.com");helper.setTo("2941660384@qq.com");javaMailSender.send(mimeMessage);}}
2、编写springboot配置文件
# 使用邮箱的用户名和spring.mail.username=2941660384@qq.com# 使用的授权码spring.mail.password=eyblepjiwzagdeed# 连上邮件服务器spring.mail.host=smtp.qq.com# 需要验证用户密码 设置为安全的spring.mail.properties.mail.smtyp.ssl.enable=true
3、springboot需要的jar包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>
PS:依赖及其配置文件
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app><parent><artifactId>Servlet</artifactId><groupId>com.yy</groupId><version>1.0-SNAPSHOT</version></parent><!--依赖项--><dependencies><!--Servlet依赖项 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--JSP依赖项 --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.1</version><scope>provided</scope></dependency><!--JSP依赖项 --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency><!--JSTL表达式的依赖项 --><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!--standard标签库--><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency><!--链接数据库的包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.0.8</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
PS:单元测试
不需要写main方法了,只需在方法前加@test就可以了,test只在方法上有效
导入junit包 @test
PS:小黄鸭调试法
PS:native(了解)
Java平台有个用户和本地C代码进行互操作的API,称为Java Native Interface (Java本地接口)。
首先让大家注意的是native方法,那个加载库的到后面也起作用。native 关键字告诉编译器(其实是JVM)调用的是该方法在外部定义,这里指的是C。
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。
这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。
1。native 是用做java 和其他语言(如c++)进行协作时用的
也就是native 后的函数的实现不是用java写的
