JavaWeb
1、基本概念
1.1、前言
web开发:
web,网页的意思,例如:www.baidu.com
静态web
html,css 提供给所有人看的数据始终不会发生变化!
动态web
几乎是所有的网站;比如淘宝。 提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同! 技术栈:Servlet/JSP,ASP,PHP
1.2、web应用程序
可以提供浏览器访问的程序;
a.html、b.html.….多个web资源,这些web资源可以被外界访问,对外界提供服务; 我们能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。 URL
这个统一的web资源会被放在同一个文件夹下,web应用程序>Tomcat:服务器 一个web应用由多部分组成(静态web,动态web)
- html,css,js
- jsp,servlet
- Java程序
- jar包
- 配置文件(Properties)
Web应用程序编写完毕后,若想提供给外界访问;需费一个服务器来统一管理
1.3、静态web
*.htm, *.html这些都是网页的后缀、如果服务器上一直存在这些东西,我们就可以直接进行读取、需要网络;
静态web存在的缺点
- Web页面无法动态更新,所有用户看到都是同一个页面
- 轮播图,点击特效:伪动态
- JavaScript[实际开发中,它用的最多]
- VBScript
- 它无法和数据库交互(数据无法持久化,用户无法交互)
1.4、 动态web
页面会动态展示,“web页面的展示效果因人而异”
缺点:
加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布; 停机维护优点: Web页面可以动态更新,所有用户看到都不是同一个页面 它可以与数据库交互(数据持久化:注册,商品信息,用户信息………)
2、web服务器
2.1、技术讲解
ASP:
微软:国内最早流行的就是ASP;
- 在HTML中嵌入了VB的脚本,ASP+COM;
- 在ASP开发中,基本一个页面都有几千行的业务代码,页面极其换乱
- 维护成本高!
C# IIS php:
PHP开发速度很快,功能很强大,跨平台,代码很简单(70%,WP) 无法承载大访问量的情况(局限性)
jSP/Servlet:
B/S;浏览和服务器 C/S:客户端和服务器
sun公司主推的B/S架构 基于Java语言的(所有的大公司,或者一些开源的组件,都是用Java写的) 可以承载三高问题带来的影响; 语法像ASP,ASP->JSP,加强市场强度;
2.2、web服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;
lIS
微软的;ASP.,Windows中自带的
3、Tomcat
面向百度编程: Tomcat是Apache 软件基金会(Apache Software Foundation)的jakarta项目中的一个核心项目,最新的Servlet 和 JSP 规范总是能在Tomcat中得到体现,因为Tomcat 技术先进、性能稳定,而且免费,因而深受lava爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个Java初学web的人来说,它是最佳的选择
Tomcat 实际上运行JSP页面和Servlet。
工作3-5年之后,可以尝试手写Tomcat服务器;
3.1、tomcat:
- 安装or解压
- 了解配置文件及目录结构
- 这个东西的作用
3.2、Tomcat启动和配置
文件夹作用:
启动,关闭Tomcat
测试访问:http://localhost:8080/
可能遇到的问题:
- Java环境变量没有配置
- 闪退问题:需要配置兼容性
- 乱码问题:配置文件中设置
3.3、配置
可以配置启动的端口号
- tomcat的默认端口号:8080
- mysql:3306
- http:80
- https:443
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
可以配置主机的名称
- 默认的主机名为:localhost->127.0.0.1
- 默认网站应用存放的位置:webapps
<Host name="www.hh.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题:
谈谈网站是如何进行访问的?
-
输入一个域名,回车 -
检查本机的C:\Windows\System32\drivers\etc\hosts 配置文件下有没有这个域名映射
3.4、发布一个web网站
先模仿
- 将自己写的网站,放到服务器(Tomcat)中指定的文件夹(webapps),就可以访问
网站应有的结构
-- webapps:Tomcat服务器的web 目录
-ROOT
-kuangstudy:网站的目录名
- WEB-INF
-classes:java程序
- lib:web应用所依赖的jar包
- web.xml:网站配置文件
-index.html:默认的首页
- static
- css
-style.css
-js
-img
-...
HTTP协议:面试 Maven:构建工具(导jar包)
Servlet入门
4、Http
4.1、什么是HTTP
HTTP(超文本传输协议)是一个简单的请求-响应协议,它通常运行在 TCP 之上。
- 文本:html,字符串,…
- 超文本:图片,音乐,视频,定位
- 端口:80
Https:是安全的(端口:443)
4.2、两个时代
- http1.0
- HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
- http2.0
- HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源。
4.3、Http请求
客户端–-发请求(Request)–服务器 百度:
Request URL:https://www.baidu.com/ 请求地址
Request Method:GET get方法/post方法
Status Code:200 OK 状态码:200
Remote(远程)
Address:14.215.177.39:443
Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9 语言
Cache-Control:max-age=0
Connection:keep-alive
1、请求行
-
请求行中的请求方式:GET -
请求方式:Get,Post,HEAD,DELETE,PUT,TRACT.…
2、消息头
4.4、Http响应
百度:
Cache-Control:private 缓存控制
Connection:Keep-Alive 连接
Content-Encoding:gzip 编码
Content-Type:text/html 类型
1.响应体
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保-持连接
HOST:主机..../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;
2、响应状态码(重点)
- 200:请求响应成功 200
- 3xx:请求重定向
- 4xx:找不到资源404
- 5xx:服务器代码错误 500 502:网关错误
常见面试题: 当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?
5、Maven
我为什么要学习这个技术?
- 在Javaweb开发中,需要使用大量的jar包,我们手动去导入;
- 如何能够让一个东西自动帮我导入和配置这个jar包。
由此,Maven诞生了!
5.1 Maven项目架构管理工具
我们目前就是用来方便导入jar包的!
Maven的核心思想:约定大于配置
- 有约束,不要去违反。
Maven会规定好你该如何去编写我们Java代码,必须要按照这个规范来;
5.2下载安装Maven
官网:https://maven.apache.org/
3.6.1版本下载:
https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/
下载完成后,解压bin文件夹;
5.3配置环境变量
在我们的系统环境变量中配置如下配置:
测试Maven是否安装成功:mav -version
5.4阿里云镜像
-
镜像:mirrors -
作用:加速我们的下载 -
国内建议使用阿里云的镜像 -
在配置文件里配置
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
------------------------------------------
<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\Maven\apache-maven-3.8.5\maven-repo</localRepository>
5.6、在IDEA中使用Maven
- 创建一个maven项目
- 等待项目初始化完毕
-
观察仓库中多了什么东西 -
IDEA中的Maven设置 IDEA项目创建成功后,看一眼Maven的配置
5.7、创建一个普通的Maven项目
- 这是只有在web应用下才会有
5.8、标记文件夹功能
方法一
方法二
5.9、IDEA中配置Tomcat
解决警告问题:
为什么会有个这个问题?我们访问一个网站,需要指定一个文件夹名字(必须要的配置)
5.10、pom文件
由于maven他的约定大于配置,我们之后可能遇到我们写的配置文件(java文件)无法导出或者生效的问题,解决方案
由于maven他的约定大于配置,我们之后可能遇到我们写的配置文件(java文件)无法导出或者生效的问题,解决方案
<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>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
</resources>
</build>
5.11、IDEA操作
5.13、解决遇到的问题
1.Maven其他版本
解决方案:使用3.6.1版本
2、Tomcat闪退
3、IDEA中每次都要重复配置Maven
在IDEA中的全局默认配置中去配置
-
maven项目中的Tomcat无法配置 -
maven默认web项目中的web.xml版本问题
替换为webapp4.0版本和tomcat一致
-
maven仓库的使用 地址:https://mvnrepository.com/
6、Servlet
6.1、Servlet简介
- Servlet就是sun公司开发动态web的一门技术
- Sun 在这些APi中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口
- 把开发好java类部署(注册)到web服务器中。
把实现了Servlet接口的Java程序叫做,Servlet
6.2、HelloServlet
Serlvet接口有两个默认的实现类:HttpServlet,GenericServlet
- 构建一个普通的Maven项目,删掉src目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就是Maven主工程;
- 关于Maven父子工程的理解;
父项目中会有
<modules>
<module>servlet-01</module>
</modules>
子项目会有
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.hh</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的java 子项目可以直接使用
son extends father
-
Maven环境优化
- 修改web.xml为最新的(和Tomcat保持一致)
- 将maven的结构搭建完整(java resources)
-
编写一个Servlet程序
- 编写一个普通类
- 实现Servlet接口,这里我们直接继承HttpServlet
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("Hello,Serlvet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 编写Servlet的映射
为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.hh.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>hello</url-pattern>
</servlet-mapping>
- 配置Tomcat(容易忽略这步)
注意:配置项目发布的路径就可以了 - 启动测试
6.3、Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
6.4、Mapping问题
-
一个Servlet可以指定一个映射路径(注意一定要有 /) <servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
-
一个Servlet可以指定多个映射路径 <servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
-
一个Servlet 可以指定通用映射路径 <servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>hello/*</url-pattern>
</servlet-mapping>
-
默认请求路径(少用,直接把首页干掉了) <servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
-
指定一些后缀或者前缀等等 可以自定义后缀实现请求映射
注意点:*前面不能加项目映射的路径
hello/adhasjkh.qinjiang
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.qinjiang</url-pattern>
</servlet-mapping>
-
优先级问题 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
6.5、ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
6.5.1、共享数据
我在这个Servlet中保存的数据,可以在另外一个servlet中拿到;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sg8Tvsu1-1653534854866)(C:\Users\小曾\AppData\Roaming\Typora\typora-user-images\image-20220518164151318.png)]
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = "秦疆";
context.setAttribute("username",username);
}
}
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().print("名字"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.kuang.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
测试访问结果;
6.5.2、获取初始化参数
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.hh.servlet.GetInitParameter</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
6.5.3、请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
context.getRequestDispatcher("/gp").forward(req,resp);
}
<servlet>
<servlet-name>rd</servlet-name>
<servlet-class>com.hh.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>rd</servlet-name>
<url-pattern>/rd</url-pattern>
</servlet-mapping>
6.5.4、读取资源文件
Properties
- 在java目录下新建properties
- 在resources目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath:
但是现在有一个问题,Java目录下的配置资源文件没有打包进来,这时看5.10、pom文件解决问题
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</exclude>
<include>**/*.xml</exclude>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</exclude>
<include>**/*.xml</exclude>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
接着解决另一个问题,思路:需要一个文件流
username=root12312
password=zxczxczxc
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/aa.properties");
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
访问测试即可ok;
6.6、HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest
对象,代表响应的一个HttpServletResponse对象;
6.6.1、简单分类(看源码)
负责向浏览器发送数据的方法
servletOutputstream getOutputstream() throws IOException;
Printwriter getwriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String varl,long var2)
void addDateHeader(String var1,long var2)
void setHeader(String var1,String var2);
void addHeader(String var1,String var2);
void setIntHeader(String var1,int var2);
void addIntHeader(String varl,int var2);
6.6.2、常见应用
- 向浏览器输出消息
- 下载文件
- 要获取下载文件的路径
- 下载的文件名是啥?
- 设置想办法让浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区中的数据输出到客户端!
package com.hh.servlet;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String realPath="D:\\JAVA\\IDEA\\Project\\javaweb-02-servlet\\response\\src\\main\\resourse\\1.JPG";
System.out.println("文件的路径为:"+realPath);
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];
ServletOutputStream out = resp.getOutputStream();
while((len =in.read(buffer))>0){
out.write(buffer,0,len);
}
}
in.close();
out.close();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.6.3、验证码功能
验证怎么来的?
- 前端实现
- 后端实现,需要用到 Java的图片类,生成一个图片
package com.kuang.servlet;
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.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
resp.setContentType("image/jpeg");
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
ImageIO.write(image,"jpg", resp.getOutputStream());
}
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-num.length() ; i++) {
sb.append("0");
}
num = sb.toString() + num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.6.4、实现重定向(重点)
B一个web资源收到客户端A请求后,B会通知A客户端去访问另外一个web资源C,这个过程叫做重定向。
常见场景:
void sendRedirect(String var1) throws IOException;
测试:
@override
protected void doGet(HttpservletRequest req, HttpservletResponse resp) throws ServletException, IOException {
resp. sendRedirect("/r/img");
面试题:聊聊重定向和转发的区别?(重点)
相同点:
不同点:
- 请求转发的时候,url不会发生变化
- 重定向时候,url地址栏会发生变化
index.jsp
<html>
<body>
<h2>Hel1o World!</h2>
<%--这里提交的路径,需要寻找到项目的路径--%>
<%--${pageContext. request, contextPath}代表当前的项目,需要导入jsp的jar包--%>
<form action="${pageContext. request.contextPath}/login" method="get">
用户名: <input type="text" name="username"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit">
</form>
</body>
</html>
RequestTest.java
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username + ":" + password);
resp.sendRedirect("/r/success.jsp");
}
}
重定向页面success.jsp
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>success</h1>
</body>
</html>
导入依赖的jar包(百度 jsp maven)
<dependencies>
<dependency>
<groupld>javax.servlet</grouptd>
<artifactId>javax. servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupld>
<artifactId>javax. servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
</project>
6.7、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;
获取参数,请求转发(跑的时候有问题)
public class RequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf8");
req.setCharacterEncoding("utf8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobbys");
System.out.println("==========");
System. out.println(username);
System. out.println(password);
System. out.println(Arrays.toString(hobbys));
System. out.println("============");
System. out.println(req.getContextPath());
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login</title>
</head>
<body>
<h2>登录</h2>
<div>
<form action="$(pageContext.request.contextPath)/login" method="post">
用户名:<input type="text" name="username">
密码:<input type="text" name="password">
爱好:<input type="checkbox" name="hobbys" value="女孩">女孩
<input type="checkbox" name="hobbys" value="代码">代码
<input type="checkbox" name="hobbys" value="跑步">跑步
<input type="checkbox" name="hobbys" value="滑板">滑板
<input type="submit" name="提交">
</form>
</div>
</body>
</html>
7、Cookie、Session
7.1、会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话;
有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话;
你能怎么证明你是西开的学生?
- 发票 西开给你发票
- 学校登记 西开标记你来过了
一个网站,怎么证明你来过?
客户端 服务端
- 服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie
- 服务器登记你来过了,下次你来的时候我来匹配你; seesion
7.2、保存会话的两种技术
cookie
seesion
- 服务器技术,利用这个技术,可以保存用户的会话信息? 我们可以把信息或者数据放在Session中!
常见应用:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!
7.3、Cookie(有问题)
- 从请求中拿到cookie信息
- 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies();
cookie.getName();
cookie.getValue();
new Cookie("lastLoginTime", System.currentTimeMillis()+"");
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
**cookie:**一般会保存在本地的 用户目录下 appdata;
一个网站cookie是否存在上限!聊聊细节问题
- 一个Cookie只能保存一个信息;
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
- Cookie大小有限制4kb;
- 300个cookie浏览器上限
删除Cookie;
- 不设置有效期,关闭浏览器,自动失效;
- 设置有效期时间为 0 ;
编码解码:
URLEncoder.encode("秦疆","utf-8")
URLDecoder.decode(cookie.getValue(),"UTF-8")
7.4、Session(重点)
什么是Session:
- 服务器会给每一个用户(浏览器)创建一个Seesion对象;
- 一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
- 用户登录之后,整个网站它都可以访问!–> 保存用户的信息;保存购物车的信息……
Session和cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
- Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器创建;
使用场景:
- 保存一个登录用户的信息;
- 购物车信息;
- 在整个网站中经常会使用的数据,我们将它保存在Session中;
使用Session:
package com.hh.servlet;
import com.hh.pojo.Person;
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");
HttpSession session = req.getSession();
session.setAttribute("name",new Person("秦疆",1));
String sessionId = session.getId();
if (session.isNew()){
resp.getWriter().write("session创建成功,ID:"+sessionId);
}else {
resp.getWriter().write("session以及在服务器中存在了,ID:"+sessionId);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
HttpSession session = req.getSession();
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
HttpSession session = req.getSession();
session.removeAttribute("name");
session.invalidate();
会话自动过期:web.xml配置
<!--设置Session默认的失效时间-->
<session-config>
<!--15分钟后Session自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
8、JSP
8.1、什么是JSP
Java Server Pages : Java服务器端页面,也和Servlet一样,用于动态Web技术!
最大的特点:
- 写JSP就像在HTML
- 区别:
- HTML只给用户提供静态的数据
- JSP页面中可以嵌入JAVA代码,为用户提供动态数据;
8.2、JSP原理
思路:JSP到底怎么执行的!
我电脑的地址:
C:\Users\Administrator.IntelliJIdea2018.1\system\tomcat\Unnamed_javaweb-session-cookie\work\Catalina\localhost\ROOT\org\apache\jsp
发现页面转变成了Java程序!
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
JSP 最终也会被转换成为一个Java类!
JSP 本质上就是一个Servlet
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(HttpServletRequest request,HttpServletResponse response)
-
判断请求 -
内置一些对象 final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
HttpServletRequest request
HttpServletResponse response
-
输出页面前增加的代码 response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
-
以上的这些个对象我们可以在JSP页面中直接使用!
在JSP页面中;
只要是 Java代码就会原封不动的输出;
如果是HTML代码,就会被转换为:
out.write("<html>\r\n");
这样的格式,输出到前端!
8.3、JSP基础语法
任何语言都有自己的语法,JAVA中有,。 JSP 作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),Java所有语法都支持!
JSP表达式
<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>
jsp脚本片段
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out.println("<h1>Sum="+sum+"</h1>");
%>
脚本片段的再实现
<%
int x = 10;
out.println(x);
%>
<p>这是一个JSP文档</p>
<%
int y = 2;
out.println(y);
%>
<hr>
<%--在代码嵌入HTML元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1>Hello,World <%=i%> </h1>
<%
}
%>
JSP声明
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void kuang(){
System.out.println("进入了方法Kuang!");
}
%>
JSP声明:会被编译到 JSP 生成Java的类中(扩大了作用域)!其他的,就会被生成到 _jspService方法中!
在JSP,嵌入Java代码即可!
<% %> 片段
<%= %> 表达式输出一个值
<%! %> 定义全局的方法(扩大了作用域)
<%--注释--%>
JSP的注释,不会在客户端显示,HTML就会!
8.4、JSP指令(有问题)
<%@page args.... %>
<%@include file=""%>
<%--@include会将两个页面合二为一--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>
<hr>
<%--jSP标签
jsp:include:拼接页面,本质还是三个
--%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>
8.5、9大内置对象
- PageContext 存东西
- Request 存东西
- Response
- Session 存东西
- Application 【SerlvetContext】 存东西
- config 【SerlvetConfig】
- out
- page ,不用了解
- exception
pageContext.setAttribute("name1","hh1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","hh2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","hh3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","hh4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;
8.6、JSP标签、JSTL标签、EL表达式
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表达式: ${ }
JSP标签
<%--jsp:include--%>
<%--
http://localhost:8080/jsptag.jsp?name=hh&age=12
--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="kuangshen"></jsp:param>
<jsp:param name="age" value="12"></jsp:param>
</jsp:forward>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!
格式化标签
SQL标签
XML 标签
核心标签 (掌握部分)
JSTL标签库使用步骤
- 引入对应的 taglib
- 使用其中的方法
- 在Tomcat 也需要引入 jstl的包,否则会报错:JSTL解析错误
c:if
<head>
<title>Title</title>
</head>
<body>
<h4>if测试</h4>
<hr>
<form action="coreif.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断如果提交的用户名是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎您!"/>
</c:if>
<%--自闭合标签--%>
<c:out value="${isAdmin}"/>
</body>
c:choose c:when
<body>
<%--定义一个变量score,值为85--%>
<c:set var="score" value="55"/>
<c:choose>
<c:when test="${score>=90}">
你的成绩为优秀
</c:when>
<c:when test="${score>=80}">
你的成绩为一般
</c:when>
<c:when test="${score>=70}">
你的成绩为良好
</c:when>
<c:when test="${score<=60}">
你的成绩为不及格
</c:when>
</c:choose>
</body>
c:forEach
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"赵六");
people.add(4,"田六");
request.setAttribute("list",people);
%>
<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin, 哪里开始
end, 到哪里
step, 步长
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="${people}"/> <br>
</c:forEach>
9、JavaBean
实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法;
一般用来和数据库的字段做映射 ORM;
ORM :对象关系映射
people表
id | name | age | address |
---|
1 | 1号 | 3 | 西安 | 2 | 2号 | 18 | 西安 | 3 | 3号 | 100 | 西安 |
class People{
private int id;
private String name;
private int age;
private String address;
}
class A{
new People(1,"1号",3,"西安");
new People(2,"2号",3,"西安");
new People(3,"3号",3,"西安");
}
- 过滤器
- 文件上传
- 邮件发送
- JDBC 复习 : 如何使用JDBC , JDBC crud, jdbc 事务
10、MVC三层架构
- 什么是MVC: Model view Controller 模型、视图、控制器
10.1、以前的架构
用户直接访问控制层,控制层就可以直接访问数据库
servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中,请求处理,响应,视图跳转,处理JDBC,处理业务代码,处理逻辑代码
架构:没有什么是加一层解决不了的
程序员调用
|
JDBC
|
Mysql Oracle SqlServer
10.2、三层架构
Model
- 业务处理 :业务逻辑(Service)
- 数据持久层:CRUD (Dao - 数据持久化对象)
View
- 展示数据
- 提供链接发起Servlet请求 (a,form,img…)
Controller (Servlet)
11、Filter (重点)
比如 Shiro安全框架技术就是用Filter来实现的
Filter:过滤器 ,用来过滤网站的数据;
(比如用来过滤网上骂人的话)
Filter开发步骤:
- 导包
- 编写过滤器
- 导包不要错 (注意)(javax.servlet)
实现Filter接口,重写对应的方法即可
public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前....");
chain.doFilter(request,response);
System.out.println("CharacterEncodingFilter执行后....");
}
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
-
在web.xml中配置 Filter <filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
12.监听器
实现一个监听器的接口;(有n种监听器)
-
编写一个监听器 实现监听器的接口…
public class OnlineCountListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
}
- web.xml中注册监听器
<listener>
<listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
-
index.jsp <html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>当前有 <sqan><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></sqan> 人在线</h1>
</body>
</html>
-
看情况是否使用!
13、过滤器、监听器常见应用
监听器:GUI编程中经常使用;
public class TestPanel {
public static void main(String[] args) {
Frame frame = new Frame("中秋节快乐");
Panel panel = new Panel(null);
frame.setLayout(null);
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(0,0,255));
panel.setBounds(50,50,300,300);
panel.setBackground(new Color(0,255,0));
frame.add(panel);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
}
});
}
}
功能:用户登录之后才能进入主页!用户注销后就不能进入主页了!
- 用户登录之后,向Sesison中放入用户的数据
- 进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
response.sendRedirect("/error.jsp");
}
chain.doFilter(request,response);
}
public void destroy() {
}
}
14、JDBC
什么是JDBC : Java连接数据库!
需要jar包的支持:
- java.sql
- javax.sql
- mysql-conneter-java… 连接驱动(必须要导入)
实验环境搭建
CREATE DATABASE jdbc CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbc
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');
SELECT * FROM users;
导入数据库依赖
<!--mysql的驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
IDEA中连接数据库:
JDBC 固定步骤:
- 加载驱动
- 连接数据库,代表数据库
- 向数据库发送SQL的对象Statement : CRUD
- 编写SQL (根据业务,不同的SQL)
- 执行SQL
- 关闭连接(先开的后关)
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from users";
//5.执行查询SQL,返回一个 ResultSet : 结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id="+rs.getObject("id"));
System.out.println("name="+rs.getObject("name"));
System.out.println("password="+rs.getObject("password"));
System.out.println("email="+rs.getObject("email"));
System.out.println("birthday="+rs.getObject("birthday"));
}
//6.关闭连接,释放资源(一定要做) 先开后关
rs.close();
statement.close();
connection.close();
}
}
预编译SQL
public class TestJdbc2 {
public static void main(String[] args) throws Exception {
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "insert into users(id, name, password, email, birthday) values (?,?,?,?,?);";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,4);
preparedStatement.setString(2,"狂神说Java");
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"24736743@qq.com");
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功@");
}
preparedStatement.close();
connection.close();
}
}
事务
要么都成功,要么都失败!
ACID原则:保证数据的安全。
开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务
转账:
A:1000
B:1000
A(900) --100--> B(1100)
Junit单元测试
依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
简单使用
@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!
@Test
public void test(){
System.out.println("Hello");
}
搭建一个环境
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(40),
money FLOAT
);
INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
public class TestJdbc3 {
@Test
public void test() {
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, username, password);
connection.setAutoCommit(false);
String sql = "update account set money = money-100 where name = 'A'";
connection.prepareStatement(sql).executeUpdate();
String sql2 = "update account set money = money+100 where name = 'B'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();
System.out.println("success");
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
15、SMBMS项目
使用技术
Maven:管理依赖打包项目 Mysql:存储数据 Servlet:后台服务资源完成相关业务 Tomcat:web项目部署的服务器 Filter:统一会话管理所有登录情况
数据库拆分:
基本框架搭建
dao层(数据持久层),pojo层( ORM映射),service(业务层),servlet(控制层),util(工具层),filter(过滤层)
dao层主要进行数据库操作,Service(业务层)调用dao层,并将获得的数据传给servlet层,
servlet层负责前后端交互,从前端获取数据,传到后端,并将后端获取的数据响应给前端
service层捕获异常,进行事务处理
事务处理:调用不同dao的多个方法,必须使用同一个connection(connection作为参数传递)事务完成之后,需要在service层进行connection的关闭,然后dao层关闭(PreparedStatement和ResultSet对象)
pojo层主要是与数据库对应的一些对象(表—类映射)
过滤器层要写编码过滤层,防止前后端编码不一致乱码情况
1、项目搭建准备工作
1.搭建一个Maven web项目
2.配置Tomcat
3.测试项目是否能够跑起来
4.导入项目中会依赖的jar包
servlet,jsp,jstl,mysql,standard
5.创建项目包结构
6.编写实体类pojo
ORM映射:表—类映射
7.编写基础公共类(dao)
-
数据库配置文件db.properties driver=com.mysql.jdbc.Driver;
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=true;
username=root;
password=123456;
-
编写操作数据库的公共类BaseDao
public class BaseDao {
private static String driver;
private static String url;
private static String username;
private static String password;
static{
Properties properties = new Properties();
InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
try {
properties.load(is);
} catch (Exception e) {
e.printStackTrace();
}
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
}
public static Connection getConnection(){
Connection connection=null;
try {
Class.forName(driver);
connection= DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
public static ResultSet executeQuery(Connection connection, String sql, Object[] params, ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException {
PreparedStatement prepareStatement = connection.prepareStatement("sql");
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject(i + 1, params[i]);
}
resultSet = prepareStatement.executeQuery();
return resultSet;
}
public static int executeUpdate(Connection connection, String sql, Object[] params, ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException {
PreparedStatement prepareStatement = connection.prepareStatement("sql");
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject(i + 1, params[i]);
}
int updateRows = prepareStatement.executeUpdate();
return updateRows;
}
public static boolean closeResource(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet){
boolean flag = true;
if(resultSet!=null){
try {
resultSet.close();
resultSet=null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
preparedStatement=null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if(connection!=null){
try {
connection.close();
connection=null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
return flag;
}
}
-
编写字符编码过滤器CharacterEncodingFilter public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig filterConfig){
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf8");
response.setCharacterEncoding("utf8");
chain.doFilter(request, response);
}
public void destroy() {
}
}
8.导入静态资源
2、登录功能实现
-
编写前端
-
设置首页 frame.jsp -
编写dao层,得到用户登陆的接口 public interface UserDao {
public User getLoginUser(Connection connection, String useCode) throws SQLException;
}
-
编写dao接口的实现类 public class UserDaoImpl implements UserDao{
public User getLoginUser(Connection connection, String useCode) throws SQLException {
PreparedStatement pstm =null;
ResultSet rs = null;
User user = null;
if(connection != null){
String sql="select * from sumbs_user where userCode=?";
Object[] params = {userCode};
rs= BaseDao.executeQuery(connection, sql, params,rs,pstm);
if(rs.next()){
user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("useruserCode"));
user.setUserName(rs.getString("userName"));
user.setUserPassword(rs.getString("userPassword"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setAddress(rs.getString("address"));
user.setUserRole(rs.getInt("userRole"));
user.setCreatedBy(rs.getInt("createdBy"));
user.setCreationDate(rs.getTimestamp("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getTimestamp("modifyDate"));
}
BaseDao.closeResource(null,pstm,rs);
}
return user;
}
}
-
业务层接口 public interface UserService {
public User login(String useCode, String password);
-
业务层实现类 public class UserServiceImpl implements UserService {
public User login(String useCode, String password) {
private UserDao userDao;
public UserServiceImpl() {
userDao = new UserDaoImpl();
}
public User login(String useCode, String password){
Connection connection = null;
User user = null;
try {
connection = BaseDao.getConnection();
userDao.getLoginUser(connection, useCode);
} catch (SQLException e) {
e.printStackTrace();
} finally {
BaseDao.closeResource(connection, null, null)
}
return user;
}
}
}
-
编写控制层 Servlet public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LoginServite--start......");
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("UserPassword");
UserServiceImpl userService = new UserServiceImpl(userCode, userPassword);
User user = userService.login(userCode, userPassword);
if(user!=null){
req.getSession().setAttribute(Constants.USER_SESSION,user);
resp.sendRedirect("jsp/frame.jsp");
}else{
req.setAttribute("error","用户名或者密码不正确");
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
-
注册Servlet <servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.ping.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
-
测试访问
3、登录功能优化
注销功能:
思路:移除session,返回登录页面
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().removeAttribute(Constants.USER_SESSION);
resp.sendRedirect(req.getContextPath()+"/login.jsp");
}
注册xml
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.ping.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
登录拦截优化
正常情况下退出系统后是登录不了的,但是目前直接输入地址还是能够登录。所以要进行优化
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
if (user != null) {
response.sendRedirect("/smbms/error.jsp");
}else{
chain.doFilter(req,resp);
}
}
public void destroy() {
}
}
配置xml
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.ping.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>
测试,登录,注销,权限,都要成功
密码修改
思路
1.导入pwdmodify.jsp文件
2.写项目从底层往上写
- Dao层,持久层,用于与数据库交互
- Service层,业务层,业务逻辑代码,Service层一般调用Dao层
- Servlet层,控制层,一般用于接收网页请求,并处理逻辑代码后返回响应,Servlet层一般调用Service层
- 编写完Servlet层记得到web.xml中注册
3.Dao层接口
public interface UserDao {
public User getLoginUser(Connection connection, String useCode) throws SQLException;
public int updatePwd(Connection connection,int id,String password) throws SQLException;
}
4.Dao层实现类
public class UserDaoImpl implements UserDao{
public String updatePwd(Connection connection, int id, String password) throws SQLException {
PreparedStatement pstm=null;
int execute=0;
if(connection!=null){
String sql="update smbms_user set userPassword=?where id=?";
Object params[]={password,id};
execute=BaseDao.executeQuery(connection,pstm,sql,params);
BaseDao.closeResource(null,pstm,null);
}
return execute;
}
}
5.service层接口
public interface UserService {
public User login(String useCode, String password);
public boolean updatePwd(int id,String pwd);
}
6.service层实现类
public boolean updatePwd(int id, String pwd) {
Connection connection = null;
boolean flag = false;
try {
connection = BaseDao.getConnection();
if (userDao.updatePwd(connection, id, pwd) > 0) {
flag = true;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
BaseDao.closeResource(connection, null, null);
}
return flag;
}
7.UserServlet层
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if (method.equals("savepwd") && method != null) {
this.updatePwd(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
public void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String newpassword = req.getParameter("newpassword");
System.out.println("UserServlet" + newpassword);
boolean flag = false;
System.out.println(o != null);
System.out.println(StringUtils.isNullOrEmpty(newpassword));
if (o != null && newpassword != null) {
UserServiceImpl userService = new UserServiceImpl();
flag = userService.updatePwd(((User) o).getId(), newpassword);
if (flag) {
req.setAttribute("message", "修改密码成功,请退出");
req.getSession().removeAttribute(Constants.USER_SESSION);
} else {
req.setAttribute("message", "密码修改失败");
}
} else {
req.setAttribute("message", "新密码有问题");
}
try {
req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
8.配置xml文件
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.ping.servlet.user.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/jsp/user.do</url-pattern>
</servlet-mapping>
9.测试
优化密码修改使用Ajax
-
AJAX = 异步 JavaScript 和 XML。 -
AJAX 是一种用于创建快速动态网页的技术。 -
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 -
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
1.阿里巴巴的fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.2</version>
</dependency>
2.UserServlet
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if (method.equals("savepwd") && method != null) {
this.updatePwd(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
public void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String newpassword = req.getParameter("newpassword");
System.out.println("UserServlet" + newpassword);
boolean flag = false;
System.out.println(o != null);
System.out.println(StringUtils.isNullOrEmpty(newpassword));
if (o != null && newpassword != null) {
UserServiceImpl userService = new UserServiceImpl();
flag = userService.updatePwd(((User) o).getId(), newpassword);
if (flag) {
req.setAttribute("message", "修改密码成功,请退出");
req.getSession().removeAttribute(Constants.USER_SESSION);
} else {
req.setAttribute("message", "密码修改失败");
}
} else {
req.setAttribute("message", "新密码有问题");
}
try {
req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void pwdModify(HttpServletRequest req, HttpServletResponse resp) {
Object object = req.getSession().getAttribute(Constants.USER_SESSION);
String oldpassword = req.getParameter("oldpassword");
HashMap<String, String> resultMap = new HashMap<String,String>();
if (object == null) {
resultMap.put("result", "sessionerror");
} else if (StringUtils.isNullOrEmpty(oldpassword)) {
resultMap.put("result", "error");
} else {
String userPassword = ((User) object).getUserPassword();
if (oldpassword.equals(userPassword)) {
resultMap.put("result", "true");
} else {
resultMap.put("result", "false");
}
}
try {
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
writer.write(JSONArray.toJSONString(resultMap));
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、用户管理实现
思路
- 导入分页的工具类
- 用户列表页面导入
4.1获取用户数量
1、UserDao
public int getUserCount(Connection connection,String username ,int userRole)throws SQLException;
2、UserDaoImpl
public int getUserCount(Connection connection, String username, int userRole) throws SQLException {
PreparedStatement pstm = null;
ResultSet rs = null;
int count = 0;
if (connection!=null){
StringBuffer sql = new StringBuffer();
sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id");
ArrayList<Object> list = new ArrayList<Object>();
if (!StringUtils.isNullOrEmpty(username)){
sql.append(" and u.userName like ?");
list.add("%"+username+"%");
}
if (userRole>0){
sql.append(" and u.userRole = ?");
list.add(userRole);
}
Object[] params = list.toArray();
System.out.println("UserDaoImpl->getUserCount:"+sql.toString());
rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
if (rs.next()){
count = rs.getInt("count");
}
BaseDao.closeResource(null,pstm,rs);
}
return count;
}
3、UserService
public int getUserCount(String username,int userRole);
4、UserServiceImpl
public int getUserCount(String username, int userRole) {
Connection connection = null;
int count = 0;
try {
connection = BaseDao.getConnection();
count = userDao.getUserCount(connection, username, userRole);
} catch (SQLException e) {
e.printStackTrace();
} finally {
BaseDao.closeResource(connection,null,null);
}
return count;
}
4.2获取用户列表
1、userdao
public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize)throws Exception;
2、userdaoImpl
public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws Exception {
PreparedStatement pstm = null;
ResultSet rs = null;
List<User> userList = new ArrayList<User>();
if(connection != null){
StringBuffer sql = new StringBuffer();
sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id");
List<Object> list = new ArrayList<Object>();
if(!StringUtils.isNullOrEmpty(userName)){
sql.append(" and u.userName like ?");
list.add("%"+userName+"%");
}
if(userRole > 0){
sql.append(" and u.userRole = ?");
list.add(userRole);
}
sql.append(" order by creationDate DESC limit ?,?");
currentPageNo = (currentPageNo-1)*pageSize;
list.add(currentPageNo);
list.add(pageSize);
Object[] params = list.toArray();
System.out.println("sql ----> " + sql.toString());
rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
while(rs.next()){
User _user = new User();
_user.setId(rs.getInt("id"));
_user.setUserCode(rs.getString("userCode"));
_user.setUserName(rs.getString("userName"));
_user.setGender(rs.getInt("gender"));
_user.setBirthday(rs.getDate("birthday"));
_user.setPhone(rs.getString("phone"));
_user.setUserRole(rs.getInt("userRole"));
_user.setUserRoleName(rs.getString("userRoleName"));
userList.add(_user);
}
BaseDao.closeResource(null, pstm, rs);
}
return userList;
}
3、userservice
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);
4、userserviceImpl
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) {
Connection connection = null;
List<User> userList = null;
System.out.println("queryUserName ---- > " + queryUserName);
System.out.println("queryUserRole ---- > " + queryUserRole);
System.out.println("currentPageNo ---- > " + currentPageNo);
System.out.println("pageSize ---- > " + pageSize);
try {
connection = BaseDao.getConnection();
userList = userDao.getUserList(connection, queryUserName,queryUserRole,currentPageNo,pageSize);
} catch (Exception e) {
e.printStackTrace();
}finally{
BaseDao.closeResource(connection, null, null);
}
return userList;
}
4.3获取角色操作
为了我们职责统一,可以把角色的操作单独放在一个包中,和POJO类对应
1、roledao
public interface RoleDao {
public List<Role> getRoleList(Connection connection) throws SQLException;
}
2、roledaoImpl
public class RoleDaoImpl implements RoleDao {
public List<Role> getRoleList(Connection connection) throws SQLException {
PreparedStatement pstm = null;
ResultSet resultSet = null;
ArrayList<Role> roleList = new ArrayList<Role>();
if (connection!=null){
String sql = "select * from smbms_role";
Object[] params = {};
resultSet = BaseDao.execute(connection, pstm, resultSet, sql, params);
while (resultSet.next()){
Role _role = new Role();
_role.setId(resultSet.getInt("id"));
_role.setRoleCode(resultSet.getString("roleCode"));
_role.setRoleName(resultSet.getString("roleName"));
roleList.add(_role);
}
BaseDao.closeResource(null,pstm,resultSet);
}
return roleList;
}
}
3、roleservice
public interface RoleService {
public List<Role> getRoleList();
}
4、roleserviceImpl
public class RoleServiceImpl implements RoleService {
private RoleDao roleDao;
public RoleServiceImpl() {
roleDao = new RoleDaoImpl();
}
public List<Role> getRoleList() {
Connection connection = null;
List<Role> roleList = null;
try {
connection = BaseDao.getConnection();
roleList = roleDao.getRoleList(connection);
} catch (SQLException e) {
e.printStackTrace();
} finally {
BaseDao.closeResource(connection,null,null);
}
return roleList;
}
}
5.用户显示的Servlet
- 获取用户前端的数据(查询)
- 判断请求是否需要执行
- 为了实现分页,需要计算出当前页面和总页面,页面大小
- 用户列表展示
- 返回前端
public void query(HttpServletRequest req, HttpServletResponse resp){
String queryUserName = req.getParameter("queryname");
String temp = req.getParameter("queryUserRole");
String pageIndex = req.getParameter("pageIndex");
int queryUserRole = 0;
UserServiceImpl userService = new UserServiceImpl();
List<User> userList = null;
int pageSize = 5;
int currentPageNo = 1;
if (queryUserName ==null){
queryUserName = "";
}
if (temp!=null && !temp.equals("")){
queryUserRole = Integer.parseInt(temp);
}
if (pageIndex!=null){
currentPageNo = Integer.parseInt(pageIndex);
}
int totalCount = userService.getUserCount(queryUserName, queryUserRole);
PageSupport pageSupport = new PageSupport();
pageSupport.setCurrentPageNo(currentPageNo);
pageSupport.setPageSize(pageSize);
pageSupport.setTotalCount(totalCount);
int totalPageCount = ((int)(totalCount/pageSize))+1;
if (currentPageNo<1){
currentPageNo = 1;
}else if (currentPageNo>totalPageCount){
currentPageNo = totalPageCount;
}
userList = userService.getUserList(queryUserName, queryUserRole, currentPageNo, pageSize);
req.setAttribute("userList",userList);
RoleServiceImpl roleService = new RoleServiceImpl();
List<Role> roleList = roleService.getRoleList();
req.setAttribute("roleList",roleList);
req.setAttribute("totalCount",totalCount);
req.setAttribute("currentPageNo",currentPageNo);
req.setAttribute("totalPageCount",totalPageCount);
req.setAttribute("queryUserName",queryUserName);
req.setAttribute("queryUserRole",queryUserRole);
try {
req.getRequestDispatcher("userlist.jsp").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
5.smbms架构分析及方法
反编译
IDEA:直接把class文件 放到相应的文件夹下就行(直接拷贝不行,得show explorer找到项目本地路径,然后复制class文件,然后idea打开)
16.文件传输原理及介绍
对于?件上传,浏览器在上传的过程中是将?件以流的形式提交到服务器端的。
?般采?Apache的开源?具common-fileupload这个?件上传组件。
导入jar包
common-io以及common-fileupload包
文件上传的注意事项:调优
1.为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放在WEB-INF目录下
2.为防止文件覆盖的现象发生,要为上传文件设置一个唯一的文件名
3.要限制文件上传的最大值
4.可以限制文件上传的类型,在收到上传文件名时,判断后缀名是否合法
需要用到的类
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或ServletFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。
FileItem类
在HTML页面input必须有name < input type=“file” name=“filename” >
表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-date
<form action="" method="post" enctype="multipart/form-data">
上传用户: <input type="text" name="username"><br>
<p><input type="file" name="file1"></p>
<p><input type="file" name="file2"></p>
<p><input type="submit"> | <input type="reset"></p>
</form>
浏览器表单的类型如果为multipart/form-data,在服务器端想获取数据就要通过流。
【常用方法介绍】
boolean isFormField();
String getFieldName();
String getString();
String getName();
InputStream getInputStream();
void delete();
ServletFileUploda类 ServletFileUploda负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中,使用其**parseRequest(HttpservletRequest)**方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简答易用。
17.文件上传
创建项目
配置Tomcat
导包
commons-fileupload-1.4.jar
commons-io-2.11.0.jar
网址:https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
https://mvnrepository.com/artifact/commons-io/commons-io/2.11.0
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br/>
<p><input type="file" name="file1"></p>
<p><input type="file" name="file2"></p>
<p><input type="submit"> | <input type="reset"></p>
</form>
</body>
</html>
web.xml
<servlet>
<servlet-name>FileServlet</servlet-name>
<servlet-class>com.hh.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>
UploadFileServlet
package com.hh.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
public class FileServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (!ServletFileUpload.isMultipartContent(request)) {
return;
}
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
uploadFile.mkdir();
}
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tempFile = new File(tempPath);
if (!tempFile.exists()) {
tempFile.mkdir();
}
DiskFileItemFactory factory = createDiskFileItemFactory(tempFile);
ServletFileUpload upload = creatServletFileUpload(factory);
String msg = uploadFile(request, uploadPath, upload);
request.setAttribute("msg", msg);
request.getRequestDispatcher("/info.jsp").forward(request, response);
}
private String uploadFile(HttpServletRequest request, String uploadPath, ServletFileUpload upload) throws IOException {
String msg = "";
try {
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {
String fieldName = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
System.out.println(fieldName + ":" + value);
} else {
String uploadFileName = fileItem.getName();
System.out.println("uploadFileName:" + uploadFileName);
if (uploadFileName == null || "".equals(uploadFileName.trim())) {
continue;
}
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
String uuidPath = UUID.randomUUID().toString();
String realPath = uploadPath + "/" + uuidPath;
File realPathFile = new File(realPath);
if (!realPathFile.exists()) {
realPathFile.mkdir();
}
InputStream inputStream = fileItem.getInputStream();
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
byte[] buffer = new byte[1024 * 1024];
int len = 0;
while ((len = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
inputStream.close();
msg = "上传成功~";
}
}
} catch (FileUploadException e) {
e.printStackTrace();
msg = "上传失败~";
}
return msg;
}
private ServletFileUpload creatServletFileUpload(DiskFileItemFactory factory) {
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setProgressListener(new ProgressListener() {
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("总大小:" + pContentLength + "已经上传:" + pBytesRead);
}
});
upload.setHeaderEncoding("UTF-8");
upload.setFileSizeMax(1020 * 1024 * 10);
upload.setSizeMax(1020 * 1024 * 10);
return upload;
}
private DiskFileItemFactory createDiskFileItemFactory(File tempFile) {
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024 * 1024);
factory.setRepository(tempFile);
return factory;
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
编写info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
Tomcat部署项目时报错方案解决:
在Tomcat的lib目录下导入jar包
上传文件存储位置
18.邮件发送原理及实现
- 张三通过smtp协议连接到Smtp服务器,然后发送一封邮件给网易的邮件服务器
- 网易分析发现需要去QQ的邮件服务器,通过Smtp协议将邮件转投给QQ的Smtp服务器
- QQ将接收到的邮件存储在456789@qq.com这个邮件账号的空间中
- 李四通过Pop3协议连接到Pop3服务器收取邮件
从456789@qq.com这个邮件账号的空间中取出邮件 - Pop3服务器将取出来的邮件送到李四手中
电子邮件
要在网络上实现邮件功能,必须要有专门的**邮件服务器,**这些邮件服务器相当于邮局,它负责接收投递过来的邮件,并把邮件投递到邮件接受者的电子邮箱中。
SMTP服务器地址:一般是smtp.xxx.com,比如QQ邮箱 smpt.qq.com
传输协议
SMTP协议
发送邮件:我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)
POP3协议
接收邮件:我们通常把处理用户pop3请求(邮件接受请求)的服务器称之为POP3服务器(邮件接收服务器)
步骤:
1.创建session对象
2.创建Transport对象
3.使用邮箱的用户名和授权码连上邮件服务器
4.创建一个Message对象(需要传递session)
5.发送邮件
6.关闭连接
需要导包
activation-1.1.1.jar
mail-1.4.7.jar
网址:
activation.jar ==> https://mvnrepository.com/artifact/javax.activation/activation
mail.jar ==> https://mvnrepository.com/artifact/javax.mail/mail
编写代码
public class MailDemo01 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.setProperty("mail.host", "smtp.qq.com");
properties.setProperty("mail.transport.protocol", "smtp");
properties.setProperty("mail.smtp.auth", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("2550705615@qq.com", "授权码");
}
});
session.setDebug(true);
Transport ts = session.getTransport();
ts.connect("smtp.qq.com", "2550705615@qq.com", "授权码");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("2550705615@qq.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("2550705615@qq.com"));
message.setSubject("hello");
message.setContent("<h1 style='color: red'>你好啊</h1>", "text/html;charset=UTF-8");
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
}
复杂文件内容的发送
文件构成解析
1、图片类型
package com.hh;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;
public class MailDemo02 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.setProperty("mail.host", "smtp.qq.com");
properties.setProperty("mail.transport.protocol", "smtp");
properties.setProperty("mail.smtp.auth", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("2066176114@qq.com", "ehbokkqknbzpcfgh");
}
});
session.setDebug(true);
Transport ts = session.getTransport();
ts.connect("smtp.qq.com", "2066176114@qq.com", "ehbokkqknbzpcfgh");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("2066176114@qq.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("2896325252@qq.com"));
message.setSubject("带图片的邮件");
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("D:\\JAVA\\IDEA\\Project\\文件传输\\email\\src\\resources/bz.jpg"));
image.setDataHandler(dh);
image.setContentID("bz.jpg");
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一封邮件带图片<img src='cid:bz.jpg'/>的邮件","text/html;charset=UTF-8");
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
message.setContent(mm);
message.saveChanges();
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}
}
2、包含文件的发送
package com.hh;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.security.GeneralSecurityException;
import java.util.Properties;
public class MailDemo03 {
public static void main(String[] args) throws MessagingException, GeneralSecurityException {
Properties properties = new Properties();
properties.setProperty("mail.host","smtp.qq.com");
properties.setProperty("mail.transport.protocol","smtp");
properties.setProperty("mail.smtp.auth", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("2066176114@qq.com", "ehbokkqknbzpcfgh");
}
});
session.setDebug(true);
Transport tp = session.getTransport();
tp.connect("smtp.qq.com","2066176114@qq.com","ehbokkqknbzpcfgh");
MimeMessage mimeMessage = imageMail(session);
tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());
tp.close();
}
public static MimeMessage imageMail(Session session) throws MessagingException {
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setFrom(new InternetAddress("2066176114@qq.com"));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("2896325252@qq.com"));
mimeMessage.setSubject("我也不知道是个什么东西就发给你了");
MimeBodyPart body1 = new MimeBodyPart();
body1.setDataHandler(new DataHandler(new FileDataSource("D:\\JAVA\\IDEA\\Project\\文件传输\\email\\src\\resources/bz.jpg")));
body1.setContentID("bz.jpg");
MimeBodyPart body2 = new MimeBodyPart();
body2.setContent("请注意,我不是广告<img src='cid:bz.jpg'>","text/html;charset=utf-8");
MimeBodyPart body3 = new MimeBodyPart();
body3.setDataHandler(new DataHandler(new FileDataSource("D:\\JAVA\\IDEA\\Project\\文件传输\\email\\src\\resources/JavaWeb.md")));
body3.setFileName("JavaWeb.md");
MimeBodyPart body4 = new MimeBodyPart();
body4.setDataHandler(new DataHandler(new FileDataSource("D:\\JAVA\\IDEA\\Project\\文件传输\\email\\src\\resources/1.txt")));
body4.setFileName("1.txt");
MimeMultipart multipart1 = new MimeMultipart();
multipart1.addBodyPart(body1);
multipart1.addBodyPart(body2);
multipart1.setSubType("related");
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(multipart1);
MimeMultipart allFile =new MimeMultipart();
allFile.addBodyPart(body3);
allFile.addBodyPart(body4);
allFile.addBodyPart(contentText);
allFile.setSubType("mixed");
mimeMessage.setContent(allFile);
mimeMessage.saveChanges();
return mimeMessage;
}
}
19.Javaweb发送邮件
现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件。邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息。今天我们也来实现一个这样的功能,用户注册成功之后,就将用户的注册信息以Email的形式发送到用户的注册邮箱当中,实现发送邮件功能就得借助于JavaMail了。
1.新建一个JavaWeb项目,配置tomcat,添加jar包
2.编写对应的用户实体类
public class User implements Serializable {
private String username;
private String password;
private String email;
public User() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
3.前端注册页面 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/registerServlet.do" method="post">
用户名:<input type="text" name="userName"/><br/>
密码:<input type="password" name="password"/><br/>
邮箱:<input type="text" name="email"/><br/>
<input type="submit" value="注册"/>
</form>
</body>
</html>
4.邮件发送工具类
public class Sendmail extends Thread{
private String from = "24736743@qq.com";
private String username = "24736743@qq.com";
private String password = "授权码";
private String host = "smtp.qq.com";
private User user;
public Sendmail(User user){
this.user = user;
}
@Override
public void run() {
try{
Properties prop = new Properties();
prop.setProperty("mail.host", host);
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.auth", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("24736743@qq.com", "授权码");
}
});
session.setDebug(true);
Transport ts = session.getTransport();
ts.connect(host, username, password);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));
message.setSubject("用户注册邮件");
String info = "恭喜您注册成功,您的用户名:" + user.getUsername() + ",您的密码:" + user.getPassword() + ",请妥善保管,如有问题请联系网站客服!!";
message.setContent(info, "text/html;charset=UTF-8");
message.saveChanges();
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
5.编写对应的servlet处理类
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
User user = new User(username,password,email);
Sendmail send = new Sendmail(user);
send.start();
request.setAttribute("message", "注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!!");
request.getRequestDispatcher("info.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "注册失败!!");
request.getRequestDispatcher("info.jsp").forward(request, response);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
7.发送成功或失败的反馈页面 info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${message}
</body>
</html>
6.配置web.xml
<servlet-mapping>
<servlet-name>registerServlet</servlet-name>
<url-pattern>/registerServlet.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>registerServlet</servlet-name>
<servlet-class>com.zyy.servlet.RegisterServlet</servlet-class>
</servlet>
8.运行Tomcat测试。
SSM框架学习
|