一. 引言
1.1 C/S架构和B/S架构
C/S 和B/S是软件发展过程中出现的两种软件架构方式
1.2 C/S架构(Client/Server 客户端/服务器)
特点: 必须在客户端安装特定软件
优点: 图形效果显示较好(如: 3D游戏)
缺点: 服务器的软件和功能进行升级, 客户端也必须升级
常见的C/S程序: QQ, 微信等
1.3 B/S架构(Browser/Server 浏览器/服务器)
特点: 无需安装客户端, 任何浏览器都可直接访问
优点: 设涉及到功能的升级, 只需要升级服务器端
缺点: 图形显示效果不如C/S架构
需要通过HTTP协议访问
二. 服务器
2.1 概念
2.1.1 什么是Web
Web(World wide web)称为万维网, 简单理解就是网站, 它用来表示Internet主机上提供外界访问的资源
Internet上供外界访问的资源分为两大类
静态资源: 指Web页面中供人们浏览的数据始终是不变的 (HTML, CSS)
动态资源: 指Web页面中供人们浏览的数据是由程序产生的, 不同时间点, 甚至不同设备访问Web页面看到的内容各不相同 (JSP/Servlet)
在Java中, 动态Web资源开发技术我们统称为Java Web
2.1.2 什么是Web服务器
Web服务器是运行及发布Web应用的容器, 只有将开发的Web项目放置到该容器中, 才能使网络中所有用户通过浏览器进行访问
2.2 常见服务器
开源: OpenSource (1. 开放源代码 2. 免费)
Tomcat(主流Web服务器之一, 适合初学者)
jetty (淘宝, 运行效率比Tomcat高)
resin (新浪, 所有开源服务器软件中, 运行效率最高的)
三者的用法从代码角度完全相同, 只有在开启, 关闭服务器软件时对应的命令稍有区别, 掌握一个即掌握所有
收费
WebLogic (Oracle)
WebSphere (IBM)
提供相应的服务与支持, 软件大, 耗资源
2.3 Tomcat服务器
Tomcat是Apache软件基金会 (Apache Software Foundation) 的Jakarta 项目中的一个核心项目, 免费开源, 并支持Servlet 和 JSP 规范. 目前Tomcat最新版本为9.0
Tomcat技术先进, 性能稳定, 深受Java爱好者喜爱并得到了部分软件开发商的认可, 成为目前比较流行的Web应用服务器
2.4 Tomcat安装
2.4.1 下载
2.4.2 解压安装
将Tomcat解压到一个没有特殊字符的目录中 (一般纯英文即可)
注意:
不建议将服务器软件放在磁盘层次很多的文件夹
不建议防在中文路径下
2.4.3 Tomcat目录说明
bin
该目录下存放的是二进制可执行文件
startup.bat 启动Tomcat, shutdown.bat 停止Tomcat
conf
这是一个非常重要的目录, 这个目录下有两个最为重要的文件server.xml和web.xml
server.xml: 配置整个服务器信息, 例如修改端口号, 编码格式等
web.xml: 项目部署描述符文件, 这个文件中注册了很多MIME类型, 即文档类型
lib
Tomcat的类库, 里面存放Tomcat运行所需要的jar文件
logs
存放日志文件, 记录了Tomcat启动和关闭的信息, 如果启动Tomcat时有错误, 异常也会记录在日志文件中
temp
Tomcat的临时文件, 这个目录下的文件在停止Tomcat后删除
webapps
存放web项目的目录, 其中每一个文件都是一个项目;
其中ROOT是一个特殊的项目, 在地址栏中没有给出项目目录时, 对应的就是ROOT项目
work
运行时生成的文件, 最终运行的文件都在这里
当客户端用户访问一个JSP文件时, Tomcat会通过JSP生成Java文件, 然后再编译Java文件生成class文件, 生成的Java和class文件都会存放到这个目录下
2.5 Tomcat启动和停止
2.5.1 启动
进入Tomcat安装目录bin下, 双击startup.bat启动程序
2.5.2 验证
打开浏览器, 输入http://localhost:8080
如果进入到Apache Tomcat版本信息页面证明启动成功
2.5.3 停止
双击shutdown.bat即可关闭Tomcat启动窗口
2.5.4 修改端口号
Tomcat默认端口号为8080, 可以通过conf/server.xml文件修改
<Connector port ="8080" protocol ="HTTP/1.1"
connectionTimeout ="20000"
redirectPort ="8443" />
注意: 修改端口号需要重新启动Tomcat才能生效
2.6 项目部署及访问静态资源
Tomcat是Web服务器, 我们的项目应用是部署在webapps下, 然后通过特定的URL 访问
2.6.1 创建项目
在webapps中建立文件夹(项目应用), 比如: myweb
创建WEB-INF文件夹, 用于存放项目的核心内容
创建classes, 用来存放.class文件
创建lib, 用于存放jar文件
创建web.xml, 项目配置文件 (到ROOT项目下的WEB-INF复制即可)
把网页hello.html复制到myweb文件夹中, 与WEB-INF在同级目录
2.6.2 URL访问资源
2.6.3 Tomcat响应流程
Client(Browser)
http://localhost:8080 /myweb/hello.html
|requests (请求) |
| |
| |
| |response (响应)
Tomcat
webapps (存放所有项目)
MyWeb (项目)
WEB-INF (核心内容)
classes (.class文件)
lib (网站需要的jar包)
hello.html
2.7 常见错误
2.7.1 Tomcat控制台闪退
闪退问题是由于JAVA_HOME配置导致的, 检查JAVA_HOME配置是否正确
2.7.2 404
访问资源不存在, 出现404错误, 检查下输入的网址是否有有误, 有没有少加斜杠/
三. Servlet [重点]
3.1概念
Servlet: Server Applet的简称, 是服务器端的程序 (代码, 功能实现), 可交互式的处理客户端发送到服务器的请求, 并完成操作响应
动态网页技术
JavaWeb程序开发的基础, JavaEE规范 (一套接口) 的一个组成部分
用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
编写一个Java类,实现servlet接口或者继承实现servlet接口的类
把开发好的Java类部署到web服务器中
按照一种约定俗成的称呼习惯,通常我们把实现servlet接口或继承实现servlet接口的类的java程序,称之为Servlet
3.1.1 Servlet作用
接收客户端请求, 完成操作
动态生成网页 (页面数据可变)
将包含操作结果的动态网页响应给客户端
3.2 Servlet开发步骤
3.2.1 搭建开发环境
将Servlet相关jar包 (lib\servlet-api.jar) 配置到classpath中
3.2.2 编写Servlet
实现javax.servlet.Servlet
重写5个主要方法
在核心的service() 方法中编写输出语句, 打印访问结果
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
public class MyServlet implements Servlet {
public void init (ServletConfig servletConfig) throws ServletException {
}
public void service (ServletRequest request, ServletResponse response) throws ServletException, IOException {
System.out.println("My First Servlet" );
}
public void destroy () {
}
public ServletConfig getServletConfig () {
return null ;
}
public String getServletInfo () {
return null ;
}
}
3.2.3 部署Servlet
编译MyServlet后, 将生成的.class文件放在WEB-INF/classes文件中
3.2.4 配置Servlet
编写WEB-INF下项目配置文件web.xml
Servlet-class: 如果有包名的话要写完整
例: com.dz.servlet.MyServlet
<servlet >
<servlet-name > MyServlet</servlet-name >
<servlet-class > MyServlet</servlet-class >
</servlet >
<servlet-mapping >
<servlet-name > MyServlet</servlet-name >
<url-pattern > /myservlet</url-pattern >
</servlet-mapping >
注意: url-pattern配置的内容就是浏览器地址栏输入的URL中项目名称后资源的内容
3.3 运行测试
3.4 常见错误
3.4.1 500错误
四. IDEA创建Web项目
4.1 IDEA创建Web项目
创建项目窗口点击Java Enterprise, 选择JavaEE7版本, 并勾选Web Application
输入项目名称和保存位置, 点击Finish, 完成项目创建
web项目目录介绍
.idea: IDEA工程配置文件
src: 存放Java代码
web: 存放项目资源
WEB-INF: 存放项目配置文件 (web.xml), Jar包 (lib/servlet-api.jar), class文件 (com.dz.servlet.MyServlet)
WebProject.iml: 模块配置文件
External Libraries: 外部Jar文件
4.2 IDEA开发Servlet
使用开发工具编写Servlet, 仍要手工导入servlet-api.jar文件, 并与项目关联
步骤:
在WEB-INF下新建lib目录, 将servlet-api.jar复制到里面, 鼠标选中lib目录右键选择Add as Library
4.2.1 编写Servlet
创建MyServlet, 实现Servlet接口, 覆盖5个方法
4.2.2 配置web.xml
<?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_3_1.xsd"
version ="3.1" >
<servlet >
<servlet-name > MyServlet</servlet-name >
<servlet-class > com.dz.servlet.MyServlet</servlet-class >
</servlet >
<servlet-mapping >
<servlet-name > MyServlet</servlet-name >
<url-pattern > /MyServlet</url-pattern >
</servlet-mapping >
</web-app >
4.2.3 部署Web项目
在Tomcat的webapps目录下, 新建WebProject文件夹
直接将IDEA中的WEB-INF文件夹复制过来, 现在里面已经有了lib目录 (存的Jar包)和web.xml 配置文件
然后在WEB-INF下, 创建classes目录 , 将IDEA中编译后的MyServlet.class文件复制至此(有包的话复制整个包, 例: com.dz.servlet.MyServlet, 则把com整个复制过去)
问题: 每当我们编写了新的Servlet或者重新编译, 都需要手工将新的.class部署到Tomcat中, 较为麻烦, 如何实现自动部署?
4.3 IDEA部署Web项目
前面我们是在Tomcat的webapps目录下新建应用程序目录myweb, 然后把静态资源和Servlet复制到相关目录下. 若使用IDEA则不需要我们复制了, 可以通过IDEA集成Tomcat服务器, 实现自动部署
4.3.1 IDEA集成Tomcat
点击File选项, 选择Settings
选择Build, Execution, Deployment下的Application Servers
点击+号, 选择Tomcat Server
选择Tomcat安装目录, 点击OK即可
最后点击OK
4.3.2 项目部署Tomcat
点击Run下的 Edit Configuration
点击+号, 选择Tomcat Server, 选择Local
选择Deployment, 点击+号, 选择Artifact, 添加当前项目
点击运行按钮, 即可运行项目
4.4 其他操作
4.4.1 关联第三方jar包
方法一:
在WEB-INF 目录下新建lib目录
复制jar包到lib目录中
右击lib目录, 选择Add as Library
选择Project Library, 完成
Clobal Library 表示所有工程都可以使用
Project Library 表示当前工程中所有模块都可以使用
Module Library 表示当前模块可以使用
方法二[推荐]:
点击File下的Project Structure
点击Project Settings下的Libraries
点击+号, 选择java, 然后继续选择jar包所在的目录, 点击OK即可
4.4.2 如何导出war包
项目完成后, 有时候需要打成war包方便部署. war包可以直接放入Tomcat的webapps目录中, 启动Tomcat后自动解压, 即可访问
点击项目结构Project Structure(IDEA图标那一排的倒数第三个图标, 或者File下可直接找到)
选择Artifacts, 点击+号
选择Web Application: Archive--->For...
点击Build下的Build Artifacts, 选择WebProject: war--->build构建项目
在out\artifacts\目录中, 查看生产的war包, 把war包放入Tomcat的webapps目录, 启动Tomcat自动解压即可访问
五. HTTP协议
5.1 什么是HTTP
超文本传输协议 (HTTP, Hyper Text Transfer Protocol) 是互联网上应用最为广泛的一种网络协议, 是一个基于请求与响应模式的, 无状态的, 应用层的协议, 运行于TCP协议基础之上
5.2 HTTP协议特点
支持客户端(浏览器) / 服务器模式
简单快递: 客户端只向服务器发送请求方法和路径, 服务器即可响应数据, 因而通信速度很快. 请求方法常用的有GET, POST等
灵活: HTTP允许传输任意类型的数据, 传输的数据类型由Content-Type标识
无连接: 无连接指的是每次TCP连接只处理一个或多个请求, 服务器处理完客户的请求后, 即断开连接, 采用这种方式可以节省传输时间
HTTP1.0版本是一个请求响应之后, 直接就断开了, 称为短连接
HTTP1.1版本不是响应后直接断开, 而是等几秒钟, 这几秒中之内有新的请求, 那么还是通过之前的连接通道来收发消息, 如果过了这几秒钟用户没有发送新的请求, 就会断开连接, 称为长连接
在一个TCP连接上可以传送多个HTTP请求和响应
多个请求和响应过程可以重叠进行
增加了更多的请求头和响应头
Connection 报头来控制
无状态: HTTP协议是无状态协议
5.3 HTTP协议通信流程
客户与服务器建立连接 (三次握手)
客户向服务器发送请求
服务器接收请求, 并根据请求返回相应的文件作为应答
客户与服务器关闭连接 (四次挥手)
5.4 请求报文和响应报文 [了解]
5.4.1 HTTP请求报文
当浏览器向web服务器发出请求时, 它向服务器传递了一个数据块, 也就是请求信息(请求报文), HTTP请求信息由4部分组成
请求行
请求头(Request Header)
空行
请求正文
5.4.2 HTTP响应报文
HTTP响应报文与HTTP请求报文相似, HTTP响应也由4个部分组成
状态行
响应头(Response Header)
空行
响应正文
5..4.3 常见状态码
200 OK 客户端请求成功
302 Found 临时重定向
403 Forbidden 服务器收到请求, 但是拒绝提供服务. 服务器通常会在响应正文中给出不提供服务的原因
404 Not Found 请求的资源不存在, 例如: 输入了错误的URL
500 Internal Server Error 服务器发生不可预期的错误, 导致无法完成客户端的请求
六. Servlet详解[重点]
6.1 Servlet接口
在Servlet API中最重要的是Servlet接口, 所有Servlet都会直接或间接的与该接口发生联系, 或是直接实现该接口, 或间接继承自实现了该接口的类, 该接口包括以下5个方法:
void init(ServletConfig config)
ServletConfig getServletConfig()
void service(ServletRequest req, ServletResponse res)
String getServletInfo()
void destroy()
6.1.2 GenericServlet抽象类
GenericServlet使编写Servlet变得更容易, 它提供声明周期方法 init 和 destroy 的简单实现, 要编写一般的Servlet, 只需重写抽象Service 方法即可
public class GenServlet extends GenericServlet {
@Override
public void service (ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("继承了GenericServlet抽象类!" );
}
}
6.1.3 HttpServlet类
HttpServlet是继承GenericServlet的基础上进一步的扩展. 提供将要被子类化以创建适用于Web 站点的Http servlet 的抽象类
HttpServlet的子类必须至少重写一个方法, 该方法通常是以下这些方法之一:
doGet: 如果servlet 支持 HTTP GET请求
doPost: 用于HTTP POST请求
doPut: 用于HTTP PUT请求
doDelete: 用于HTTP DELETE请求
6.2 Servlet两种创建方式
6.2.1 实现接口Servlet
public class MyServlet implements Servlet {
@Override
public void init (ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig () {
return null ;
}
@Override
public void service (ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("My First Web Project!" );
System.out.println(new Date ());
System.out.println("成功导出war包!" );
}
@Override
public String getServletInfo () {
return null ;
}
@Override
public void destroy () {
}
}
6.2.2 继承HttpServlet (推荐)
public class HttpsServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是get请求的内容!" );
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是post请求的内容!" );
}
}
6.2.3 常见错误
HTTP Status 404 资源找不到
第一种情况:地址书写有误
第二种情况: 地址没有问题, 把IDEA项目中out目录删除, 然后重新运行
Servlet地址配置重复
both mapped to the url-pattern [/helloservlet] which is not permitted
Servlet地址配置错误
比如没有写/ Invalid[helloservlet2] in servlet mapping
6.3 Servlet两种配置方式
6.3.1 使用web.xml (Servlet2.5之前使用, 通用配置,各版本支持)
<?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_3_1.xsd"
version ="3.1" >
<servlet >
<servlet-name > MyServlet</servlet-name >
<servlet-class > com.dz.servlet.MyServlet</servlet-class >
<load-on-startup > 1</load-on-startup >
</servlet >
<servlet-mapping >
<servlet-name > MyServlet</servlet-name >
<url-pattern > /ms</url-pattern >
</servlet-mapping >
</web-app >
6.3.2 配置属性
url-pattern定义匹配规则, 取值说明:
精确匹配 /具体的名称 只有url路径是具体的名称时才会触发Servlet
后缀匹配 *.xxx 只要是以xxx结尾的就匹配触发Servlet
通配符匹配 /* 匹配所有请求, 包含服务器的所有资源
通配符匹配 / 匹配所有请求, 包含服务器的所有资源, 不包括.jsp
load-on-startup
1. 元素标记容器是否应该在web应用程序启动时就加载这个servlet
2. 它的值必须是一个整数, 表示servlet被加载的先后顺序
3. 如果该元素的值为负数或者没有设置, 则容器会认为Servlet被请求时再加载
4. 如果值为整数或者0时, 表示容器在应用启动时就加载并初始化这个servlet, 值越小, servlet的优先级越高, 就越先被加载, 值相同时, 容器就会自己选择顺序来加载
6.3.3 使用注解 (Servlet3.0后支持, 推荐)
@WebServlet(value = {"/bs", "/bss"},loadOnStartup = 0)
public class BasicServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是GET!" );
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是POST!" );
}
}
6.3.4 @WebServer注解常用属性
name: Servlet名字 (可选)
value: 配置url路径, 可以配置多个
urlPatterns: 配置url路径, 和value作用一样, 不能同时使用
loadOnStartup: 配置Servlet的创建时机, 如果是0或者正数则启动时创建, 如果是负数则访问时创建. 数字越小优先级越高
七. Servlet应用
7.1 request对象
在Servlet中用来处理客户端请求需要用doGet或doPost方法的request对象
request对象, response对象作为参数传递给doGet, doPost方法
7.1.1 get和post的区别
get请求
get提交的数据会放在URL之后, 以?分隔URL和传输数据, 参数之间以&相连
get方式以明文传递 数据量小, 不安全
效率高, 浏览器默认请求方式为GET请求
对应的Servlet的方法是doGet
post请求
post方法是把提交的数据放在HTTP包的Body中
密文传递数据, 数据量大, 安全
效率相对没有GET高
对应的Servlet的方法是doPost
7.1.2 request主要方法
String getParameter(String name)
void setCharacterEncoding(String charset)
7.1.3 request应用
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 注册页面</title >
</head >
<body >
<form action ="/WebProject_war_exploded/rs" method ="get" >
<p >
<label for ="1" > 用户名:</label >
<input type ="text" name ="username" id ="1" >
</p >
<p >
<label for ="2" > 密码: </label >
<input type ="password" name ="password" id ="2" >
</p >
<p >
<input type ="submit" value ="注册" >
</p >
</form >
</body >
</html >
@WebServlet(value = {"/rs"})
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username" );
String password = req.getParameter("password" );
System.out.println("提交的数据: " + username + "\t" + password );
}
}
7.1.4 get请求收参问题
产生乱码是因为服务器和客户端沟通的编码不一致造成的, 因此解决的办法是: 在客户端和服务器之间设置一个统一的编码, 之后就按照此编码进行数据的传输和接收
7.1.5 get中文乱码
在Tomcat7及以下版本, 客户端以UTF-8的编码传输数据到服务器, 而服务器端的request对象使用的是ISO8859-1 这个字符编码来接收数据, 服务器和客户端沟通的编码不一致因此才会产生中文乱码的
解决办法: 在接收到消息数据后, 先获取request对象以ISO8859-1 字符编码接收到的原始数据的字节数组, 然后通过字节数组以指定的编码构建字符串, 解决乱码问题
Tomcat8的版本中get方式不会出现乱码了, 因为服务器对url的编码格式可以进行自动转换
解决get中文乱码的代码
@WebServlet(value = {"/rs"})
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username" );
username = new String (username.getBytes("ISO8859-1" ),"UTF-8" );
String password = req.getParameter("password" );
System.out.println("提交的数据: " + username + "\t" + password );
}
}
7.1.6 post中文乱码
由于客户端是以UTF-8字符编码将表单数据传输到服务器的, 因此服务器也需要设置以UTF-8字符编码进行接收
解决方案: 使用从ServletRequest接口继承而来的setCharacterEncoding(charset)方法进行通一的编码设置
@WebServlet(value = {"/rs"})
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8" );
String username = req.getParameter("username" );
String password = req.getParameter("password" );
System.out.println("提交的数据: " + username + "\t" + password );
}
}
7.2 response对象
response对象用于响应客户请求并向客户端输出信息
7.2.1 response主要方法
setHeader(name, value)
setContentType(String)
setCharacterEncoding(String)
getWriter()
7.2.2 response应用
PrintWriter printWriter = resp.getWriter();
printWriter.println("register success!!" );
如果输出内容包括中文, 则会出现乱码, 因为服务器默认采用ISO8859-1 编码响应内容
7.2.3 解决输出中文乱码
设置服务器端响应的编码格式
设置客户端响应内容的头内容的文件类型及编码格式
resp.setCharacterEncoding("UTF-8" );
resp.setHeader("Content-type" , "text/html;charset=UTF-8" );
不推荐
同时设置服务端的编码格式和客户端响应的文件类型及响应时的编码格式
resp.setContentType("text/html;charset=UTF-8" );
7.3 综合案例(Servlet + JDBC)
步骤:
MySQL数据库中
Servlet项目中
将所需的jar包导入 到web---WEB-INF---lib中
mysql-connector-java-5.1.25-bin.jar
commons-dbutils-1.7.jar
druid-1.1.5.jar
servlet-api.jar
src下创建database.properties
里面是连接MySQL数据库和Druid连接池的配置信息
src下创建com.dz.servletProject目录,在此目录下分别有以下操作
utils(工具类 )目录下创建DbUtils 工具类
entity(实体类 )目录下创建Admin 用户实体类
dao(数据库访问层 )目录下创建AdminDao 接口以及imp l目录, impl目录下创建AdminDao接口的实现类AdminDaoImpl
service(逻辑业务层 )目录下创建AdminService 接口以及impl 目录, impl目录下创建AdminService接口的实现类AdminServiceImpl
servlet(服务器端的java程序 )目录下创建LoginServlet 用户登陆类和ShowAllAdminServlet 展示所有用户信息类
web目录下创建login.html文件
以下是部分代码
7.3.1 数据库
CREATE TABLE admin(
username VARCHAR (20 ) PRIMARY KEY NOT NULL ,
PASSWORD VARCHAR (20 ) NOT NULL ,
phone VARCHAR (11 ) NOT NULL ,
address VARCHAR (20 ) NOT NULL
)CHARSET= utf8;
SELECT * FROM admin;
INSERT INTO admin(username,PASSWORD,phone,address)
VALUE ('张三' ,'123456' ,'12345678901' ,'地球' );
INSERT INTO admin(username,PASSWORD,phone,address)
VALUE ('李四' ,'123456' ,'12345678902' ,'地球' );
7.3.2 database.properties
driver =com.mysql.jdbc.Driver
url =jdbc:mysql://localhost:3306/companydb?useUnicode=true&characterEncoding=UTF-8
username =root
password =root
initialSize =10
maxActive =20
minIdle =5
maxWait =3000
7.3.3 DbUtils
public class DbUtils {
private static DruidDataSource ds;
private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal <>();
static {
Properties properties = new Properties ();
InputStream inputStream = DbUtils.class.getResourceAsStream("/database.properties" );
try {
properties.load(inputStream);
ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection () {
Connection conn = THREAD_LOCAL.get();
try {
if (conn == null ) {
conn = ds.getConnection();
THREAD_LOCAL.set(conn);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
public static void begin () {
Connection conn = null ;
try {
conn = getConnection();
conn.setAutoCommit(false );
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public static void commit () {
Connection conn = null ;
try {
conn = getConnection();
conn.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
closeAll(conn,null ,null );
}
}
public static void rollback () {
Connection conn = null ;
try {
conn = getConnection();
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
closeAll(conn,null ,null );
}
}
public static void closeAll (Connection conn, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null ) {
resultSet.close();
}
if (statement != null ) {
statement.close();
}
if (conn != null ) {
conn.close();
THREAD_LOCAL.remove();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
7.3.4 Admin
public class Admin {
private String username;
private String password;
private String phone;
private String address;
public Admin () {
}
public Admin (String username, String password, String phone, String address) {
this .username = username;
this .password = password;
this .phone = phone;
this .address = address;
}
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 getPhone () {
return phone;
}
public void setPhone (String phone) {
this .phone = phone;
}
public String getAddress () {
return address;
}
public void setAddress (String address) {
this .address = address;
}
@Override
public String toString () {
return "Admin{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", phone='" + phone + '\'' +
", address='" + address + '\'' +
'}' ;
}
}
7.3.5 AdminDao
public interface AdminDao {
int insert (Admin admin) ;
int delete (String username) ;
int update (Admin admin) ;
Admin select (String username) ;
List<Admin> selectAll () ;
}
7.3.6 AdminDaoImpl
public class AdminDaoImpl implements AdminDao {
private QueryRunner queryRunner = new QueryRunner ();
@Override
public int insert (Admin admin) {
return 0 ;
}
@Override
public int delete (String username) {
return 0 ;
}
@Override
public int update (Admin admin) {
return 0 ;
}
@Override
public Admin select (String username) {
try {
Admin admin = queryRunner.query(DbUtils.getConnection(), "select * from admin where username=?" , new BeanHandler <Admin>(Admin.class), username);
return admin;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
@Override
public List<Admin> selectAll () {
try {
List<Admin> adminList = queryRunner.query(DbUtils.getConnection(), "select * from admin" , new BeanListHandler <Admin>(Admin.class));
return adminList;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
}
7.3.7 AdminService
public interface AdminService {
Admin login (String username, String password) ;
List<Admin> showALlAdmin () ;
}
7.3.8 AdminServiceImpl
public class AdminServiceImpl implements AdminService {
private AdminDao adminDao = new AdminDaoImpl ();
@Override
public Admin login (String username, String password) {
Admin result = null ;
try {
DbUtils.begin();
Admin admin = adminDao.select(username);
if (admin != null ) {
if (admin.getPassword().equals(password)) {
result = admin;
}
}
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return result;
}
@Override
public List<Admin> showALlAdmin () {
List<Admin> adminList = null ;
try {
DbUtils.begin();
adminList = adminDao.selectAll();
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return adminList;
}
}
7.3.9 LoginServlet
@WebServlet(value = "/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8" );
resp.setContentType("text/html;charset=UTF-8" );
String username = req.getParameter("username" );
String password = req.getParameter("password" );
AdminService adminService = new AdminServiceImpl ();
Admin admin = adminService.login(username, password);
PrintWriter printWriter = resp.getWriter();
if (admin != null ) {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>结果页面</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<h1>登陆成功!</h1>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}else {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>结果页面</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<h1>登陆失败!</h1>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
7.3.10 ShowAllAdminServlet
@WebServlet(value = "/showAll")
public class ShowAllAdminServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8" );
AdminService adminService = new AdminServiceImpl ();
List<Admin> adminList = adminService.showALlAdmin();
PrintWriter printWriter = resp.getWriter();
if (adminList != null ) {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>展示所有用户</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<table border='1'>" );
printWriter.println("<tr>" );
printWriter.println(" <th>username</th>" );
printWriter.println(" <th>password</th>" );
printWriter.println(" <th>phone</th>" );
printWriter.println(" <th>address</th>" );
printWriter.println("</tr>" );
for (Admin admin : adminList) {
printWriter.println("<tr>" );
printWriter.println(" <td>" +admin.getUsername()+"</td>" );
printWriter.println(" <td>" +admin.getPassword()+"</td>" );
printWriter.println(" <td>" +admin.getPhone()+"</td>" );
printWriter.println(" <td>" +admin.getAddress()+"</td>" );
printWriter.println("</tr>" );
}
printWriter.println("</table>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}else {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>展示所有用户</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<h3>当前没有用户!</h3>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
7.3.11 login.html
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 登陆页面</title >
</head >
<body >
<form action ="/WebProject_war_exploded/login" method ="post" >
<p >
<label for ="1" > 用户名:</label >
<input type ="text" name ="username" id ="1" >
</p >
<p >
<label for ="2" > 密码: </label >
<input type ="password" name ="password" id ="2" >
</p >
<p >
<input type ="submit" value ="登陆" >
</p >
</form >
</body >
</html >
八. 转发与重定向
8.1 现有问题
8.1.1 业务, 显示分离
问题: 业务逻辑和显示结果分离后, 如何跳转到显示结果的Servlet?
业务逻辑得到的数据结果如何传递给显示结果的Servlet?
8.2 转发
转发的作用在服务器端, 将请求发送给服务器上的其他资源, 以共同完成一次请求的处理
8.2.1 页面跳转
调用业务逻辑的Server中, 编写以下代码
request.getRequestDispatcher("/目标URL-pattern").forward(request, response);
使用forward跳转时, 是在服务器内部跳转, 地址栏不发生变化, 属于同一次请求
8.2.2 数据传递
forward表示一次请求, 是在服务器内部跳转, 可以共享同一次request作用域中的数据
request作用域: 拥有存储数据的空间, 作用范围是一次请求有效(一次请求可以经过多次转发)
可以将数据存入request后, 在一次请求过程中的任何位置进行获取
可传递任何数据(基本数据类型, 对象, 数组, 集合等)
存数据: request.setAttribute(key, value);
以键值对形式存储在request作用域中.key为String类型 , value为Object类型
取数据: request.getAttribute(key);
通过String类型的key访问Object类型的value
调用业务逻辑
@WebServlet(value = "/showAllController")
public class ShowAllAdminController extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AdminService adminService = new AdminServiceImpl ();
List<Admin> adminList = adminService.showALlAdmin();
req.setAttribute("adminList" , adminList);
req.getRequestDispatcher("/showAllJSP" ).forward(req,resp);
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
显示
@WebServlet(value = "/showAllJSP")
public class ShowAllAdminJSP extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8" );
List<Admin> adminList = (List)req.getAttribute("adminList" );
PrintWriter printWriter = resp.getWriter();
if (adminList != null ) {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>展示所有用户</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<table border='1'>" );
printWriter.println("<tr>" );
printWriter.println(" <th>username</th>" );
printWriter.println(" <th>password</th>" );
printWriter.println(" <th>phone</th>" );
printWriter.println(" <th>address</th>" );
printWriter.println("</tr>" );
for (Admin admin : adminList) {
printWriter.println("<tr>" );
printWriter.println(" <td>" +admin.getUsername()+"</td>" );
printWriter.println(" <td>" +admin.getPassword()+"</td>" );
printWriter.println(" <td>" +admin.getPhone()+"</td>" );
printWriter.println(" <td>" +admin.getAddress()+"</td>" );
printWriter.println("</tr>" );
}
printWriter.println("</table>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}else {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>展示所有用户</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<h3>当前没有用户!</h3>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
8.2.3 转发特点
转发是服务器行为
转发是浏览器只做了一次访问请求
转发浏览器地址不变
转发两次跳转之间存储的信息不会丢失, 所以可以通过request进行数据的传递
转发只能将请求转发给同一个Web应用中的组件
8.3 重定向
重定向作用在客户端, 客户端将请求发送给服务器后, 服务器响应给客户端一个新的请求地址, 客户端重新发送请求
8.3.1 页面跳转
在调用业务逻辑的Servlet中, 编写以下代码
response.sendRedirect("目标URI");
URI统一资源标识符(Uniform Resource Identifier), 用来表示服务器中定位一个资源, 资源在web项目中的路径(/project/source)
使用redirect跳转时, 是在客户端跳转, 地址栏发生变化, 属于多次请求
8.3.2 数据传递
sendRedirect跳转时, 地址栏改变, 代表客户端重新发送的请求. 属于两次请求
response没有作用域, 两次request中的数据无法共享
传递数据:通过URL的拼接进行数据传递("/WebProject/b?username=tom");
获取数据: request.getParameter("username");
8.3.3 重定向特点
重定向是客户端行为
重定向是浏览器做了至少两次的访问请求
重定向浏览器地址改变
重定向两次跳转之间传输的信息会丢失(request范围)
重定向可以指向任何资源, 包括当前应用程序中的其他资源, 同一个站点上的其他应用程序中的资源, 其他站点的资源
8.4 转发, 重定向总结
当两个Servlet需要传递数据时, 选择forward转发, 不建议使用sendRedirect进行传递
九. Servlet生命周期
9.1.1 实例化
当用户第一次访问Servlet时, 由容器(Tomcat服务器)调用Servlet的构造器创建具体的Servlet对象. 也可以在容器启动之后立刻创建实例. 使用如下代码可以设置Servlet是否在服务器启动时就创建
< load-on-startup>1< /load-on-startup>
数字为0或者正数: 容器启动时创建,数字越小, 优先级越高
数字为负数或者不写这条语句: 被访问时创建
注意: 只执行一次
9.1.2 初始化
在初始化阶段, init()方法会被调用, 这个方法在javax.servlet.Servlet接口中定义. 其中, 方法以一个ServletConfig类型的对象作为参数
注意: init()方法只被执行一次
9.1.3 服务
当客户端有一个请求时, 容器就会将请求ServletRequest与响应ServletResponse对象转给Servlet, 以参数的形式传给service 方法
9.1.4 销毁
当Servlet容器(Tomcat服务器)停止或重新启动都会引起销毁Servlet对象并调用destroy方法
9.1.5 Servlet执行流程
浏览器发送请求
容器(Tomcat服务器)解析请求
创建Servlet实例
调用init()
调用service()
输出响应
容器向浏览器发送响应
容器调用destroy()
十. Servlet特性
10.1 线程安全问题
Servlet在访问之后, 会执行实例化操作. 创建一个Servlet对象, 而我们Tomcat容器可以同时多个线程并发访问同一个Servlet, 如果在方法中对成员变量做修改操作, 就会有线程安全的问题
10.2 如何保证线程安全
synchronized
实现SingleThreadModel接口
servlet实现SingleThreadModel接口后, 每个线程都会创建servlet实例, 这样每个客户端请求就不存在共享资源的问题, 但是servlet响应客户端请求的效率太低, 所以已经淘汰
尽可能使用局部变量
@WebServlet(value = "/ss")
public class SafeServlet extends HttpsServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String message = "登陆成功!" ;
resp.setContentType("text/html;charset=UTF-8" );
PrintWriter printWriter = resp.getWriter();
printWriter.println(message);
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
十一. 状态管理
11.1 现有问题
HTTP协议是无状态的, 不能保存每次提交的信息
如果用户发来一个新的请求, 服务器无法知道它是否与上次的请求有联系
对于那些需要多次提交数据才能完成的Web操作, 比如登陆来说, 就成问题了
11.2 概念
将浏览器与web服务器之间多次交互当做一个整体来处理, 并且将多次交互所涉及的数据(即状态) 保存下来
11.3 状态管理分类
客户端状态管理技术: 将状态保存在客户端. 代表性的是Cookie技术
服务器状态管理技术: 将状态保存在服务器端,. 代表性的是session技术 (服务器传递sessionID时需要使用Cookie的方式)
十二. Cookie的使用
12.1 什么是Cookie
Cookie是在浏览器访问Web服务器的某个资源时, 由Web服务器在HTTP响应消息头中附带传送给浏览器的一小段数据
一旦Web浏览器保存了某个Cookie, 那么它在以后每次访问该该Web服务器时, 都应在HTTP请求头中将这个Cookie回传给Web服务器
一个Cookie主要由标识该信息的名称(name) 和 值(value)组成
Client
http:
Server
Client首次请求Server
LoginServlet extends HttpServlet {
}
Client再次请求Server
ShowServlet extends HttpServlet {
}
12.2 创建Cookie
@WebServlet(value = "/cs")
public class CookieServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie ("username" ,"dz" );
cookie.setPath("/WebProject_war_exploded/get" );
cookie.setMaxAge(60 *60 );
resp.addCookie(cookie);
}
}
12.3 获取Cookie
@WebServlet(value = "/get")
public class GetServlet extends HttpsServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
if (cookies != null ) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("username" )) {
String value = cookie.getValue();
System.out.println(cookie.getName() + ":" + value);
break ;
}
}
}
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
12.4 修改Cookie
Cookie cookie2 = new Cookie ("username" ,"dz2" );
cookie2.setPath("/WebProject_war_exploded/get" );
cookie2.setMaxAge(60 *60 *24 *7 );
resp.addCookie(cookie2);
注意: 如果改变Cookie的name和有效路径会新建Cookie, 而改变Cookie的值,和有效期会覆盖原有Cookie
12.5 Cookie编码与解码
Cookie默认不支持中文, 只能包含ASCII字符, 所以Cookie需要对Unicode字符进行编码, 否则会出现乱码
编码可以使用java.net.URLEncoder类的encode(String str, String encoding) 方法
解码使用java.net.URLDecoder类的decode(String str, String encoding) 方法
12.5.1 创建带中文Cookie
Cookie cookie = new Cookie (URLEncoder.encode("姓名" ,"UTF-8" ),URLEncoder.encode("张三" ,"UTF-8" ));
cookie.setPath("/WebProject_war_exploded/get" );
cookie.setMaxAge(60 *60 );
resp.addCookie(cookie);
12.5.2 读取带中文Cookie
Cookie[] cookies = req.getCookies();
if (cookies != null ) {
for (Cookie cookie : cookies) {
String cookieName = URLDecoder.decode(cookie.getName(),"UTF-8" );
String cookieValue = URLDecoder.decode(cookie.getValue(),"UTF-8" );
System.out.println(cookieName + ":" + cookieValue);
}
}
12.6 Cookie优点和缺点
12.6.1 优点
可配置到期规则
简单性: Cookie是一种基于文本的轻量结构, 包含简单的键值对
数据持久性: Cookie默认在过期之前是可以一直存在客户端浏览器上的
12.6.2 缺点
大小受到限制: 大多数浏览器对Cookie的大小有4K, 8K字节的限制
用户配置为禁用: 有些用户禁用了对浏览器或客户端设备接收Cookie的能力, 因此限制了这一功能
潜在的安全风险: Cookie可能会被篡改. 会对安全性造成潜在危险或者导致依赖于Cookie的应用程序失败
十三. Session对象[重点]
13.1 Session概述
Session用于记录用户的状态. Session指的是在一段时间内, 单个客户端与Web服务器的一连串相关的交互过程
在一个Session中, 客户可能会多次请求访问同一个资源, 也有可能请求访问各种不同的服务器资源
13.2 Session原理
服务器会给每一次会话分配一个Session对象
同一个浏览器 发起的多次请求, 同属于一次会话(Session)
首次使用到Session时, 服务器会自动创建Session, 并创建Cookie存储SessionId发送回客户端
注意: session是服务端创建的
13.3 Session使用
Session作用域: 拥有存储数据的空间, 作用范围是一次会话有效
一次会话是使用同一浏览器发送的多次请求. 一旦浏览器关闭, 则结束会话
可以将数据存入Session中, 在一次会话的任意位置进行获取
可传递任何数据(基本数据类型, 数组, 对象, 集合)
13.3.1 获取Session
session是服务器自动创建的, 通过request对象获取
HTTPSession session = request.getSession();
System.out.println("Id: " + session.getId());
13.3.2 Session保存数据
setAttribute(属性名,Object) 保存数据到session中
session.setAttribute("key" , value);
13.3.3 Session获取数据
getAttribute(属性名); 获取session中的数据
session.getAttribute("key" );
13.3.4 Session移除数据
removeAttribute(属性名); 从session中删除数据
session.removeAttribute("key" );
13.4 Session与Request应用区别
request是一次请求有效, 请求改变, 则request改变
session是一次会话有效, 浏览器改变, 则session改变
13.4.1 Session应用
@WebServlet(name = "SessionServlet", value = "/sss")
public class SessionServlet extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("username" ,"dz" );
request.setAttribute("password" ,"1234" );
response.sendRedirect("/WebProject_war_exploded/getValue" );
System.out.println(session.getId());
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
13.4.2 GetValueServlet.java
@WebServlet(name = "GetValueServlet",value = "/getValue")
public class GetValueServlet extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String s = (String)session.getAttribute("username" );
String password = (String)request.getAttribute("password" );
System.out.println("从session中获得了: " + s);
System.out.println("从request中获得了: " + password);
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
13.5 Session的生命周期
开始: 第一次使用到Session的请求产生, 则创建Session
结束:
浏览器关闭, 则失效
Session超时, 则失效
session.setMaxInactiveInterval(seconds);//设置最大有效时间(单位: 秒)
手工销毁, 则失效
session.invalidate();//登陆退出, 注销
13.5.1 Session失效
session.setMaxInactiveInterval(60 *60 );
session.invalidate();
13.6 浏览器禁用Cookie解决方案[了解]
13.6.1 浏览器禁用Cookie的后果
服务器在默认情况下, 会使用Cookie的方式将sessionID发送给浏览器, 如果用户禁止Cookie, 则sessionID不会被浏览器保存, 此时, 服务器可以使用如URL重写这样的方式来发送sessionID
13.6.2 URL重写
浏览器在访问服务器上的某个地址时, 不再使用原来的那个地址, 而是使用改写过的地址 (即在原来的地址后面加上了sessionID)
13.6.3 实现URL重写
response.encodeRedirectURL(String url)生成重写的URL
HttpSession session = request.getSession();
String newUrl = response.encodeRedirectURL("/WebProject_war_exploded/gets" );
response.sendRedirect(newUrl);
13.7 Session实现权限验证
在7.3的Servlet+JDBC综合案例的基础下进行升级
现在要求:
增加管理员表, 只有管理员通过登陆才能查看所有用户信息
若在网址栏中直接访问用户信息网址, 则跳转到管理员登陆界面
管理员在登陆成功后, 跳转到用户信息页面, 且在页面最上方显示"欢迎您,xxx管理员"字样
提示: 需要把管理员Mgr和用户列表adminList放入session中存储, 这样可以在程序任何地方通过session.getAttribute方法进行调用
13.7.1 创建管理员表
CREATE TABLE manager(
username VARCHAR (20 ) PRIMARY KEY,
PASSWORD VARCHAR (20 ) NOT NULL
)CHARSET= utf8;
根据管理员表创建实体类Admin(代码此处省略)
在dao目录下编写ManagerDao接口和ManagerDaoImpl实现类
ManagerDao接口
public interface ManagerDao {
Manager select (String username) ;
}
ManagerDaoImpl实现类
public class ManagerDaoImpl implements ManagerDao {
private QueryRunner queryRunner = new QueryRunner ();
@Override
public Manager select (String username) {
try {
Manager manager = queryRunner.query(DbUtils.getConnection(), "select * from manager where username=?" , new BeanHandler <Manager>(Manager.class),username);
return manager;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
}
service下编写ManagerService接口和ManagerServiceImpl实现类
ManagerService接口
public interface ManagerService {
Manager login (String username,String password) ;
}
ManagerServiceImpl实现类
public class ManagerServiceImpl implements ManagerService {
private ManagerDao managerDao = new ManagerDaoImpl ();
@Override
public Manager login (String username, String password) {
Manager manager = null ;
try {
DbUtils.begin();
Manager temp = managerDao.select(username);
if (temp != null ) {
if (temp.getPassword().equals(password)) {
manager = temp;
}
}
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return manager;
}
}
13.7.2 登陆页面
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 管理员登录</title >
</head >
<body >
<form action ="/WebProject_war_exploded/loginMgr" method ="post" >
<p >
<label for ="1" > 用户名:</label >
<input type ="text" name ="username" id ="1" >
</p >
<p >
<label for ="2" > 密码: </label >
<input type ="password" name ="password" id ="2" >
</p >
<p >
<input type ="submit" value ="登陆" >
</p >
</form >
</body >
</html >
13.7.3 LoginMgrController
servlet下的controller目录下, 负责调用业务逻辑(管理员登陆)
@WebServlet(name = "LoginMgrController",value = "/loginMgr")
public class LoginMgrController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8" );
response.setContentType("text/html;charset=UTF-8" );
String username = request.getParameter("username" );
String password = request.getParameter("password" );
ManagerService managerService = new ManagerServiceImpl ();
Manager mgr = managerService.login(username, password);
if (mgr != null ) {
HttpSession session = request.getSession();
session.setAttribute("mgr" ,mgr);
response.sendRedirect("/WebProject_war_exploded/showAllController" );
}else {
response.sendRedirect("/WebProject_war_exploded/loginMgr.html" );
}
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
13.7.4 ShowAllAdminController
servlet下的controller目录下, 负责调用业务逻辑(查所有用户信息)
@WebServlet(value = "/showAllController")
public class ShowAllAdminController extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Manager mgr = (Manager)session.getAttribute("mgr" );
if (mgr != null ) {
AdminService adminService = new AdminServiceImpl ();
List<Admin> adminList = adminService.showALlAdmin();
session.setAttribute("adminList" , adminList);
resp.sendRedirect("/WebProject_war_exploded/showAllJSP" );
}else {
resp.sendRedirect("/WebProject_war_exploded/loginMgr.html" );
}
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
13.7.5 ShowAllAdminJSP
servlet下的jsp目录下, 负责展示最终结果
@WebServlet(value = "/showAllJSP")
public class ShowAllAdminJSP extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Manager mgr = (Manager)session.getAttribute("mgr" );
List<Admin> adminList = (List)session.getAttribute("adminList" );
resp.setContentType("text/html;charset=UTF-8" );
PrintWriter printWriter = resp.getWriter();
if (adminList != null ) {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>展示所有用户</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<h1>欢迎您: " + mgr.getUsername() +"</h1>" );
printWriter.println("<table border='1'>" );
printWriter.println("<tr>" );
printWriter.println(" <th>username</th>" );
printWriter.println(" <th>password</th>" );
printWriter.println(" <th>phone</th>" );
printWriter.println(" <th>address</th>" );
printWriter.println("</tr>" );
for (Admin admin : adminList) {
printWriter.println("<tr>" );
printWriter.println(" <td>" +admin.getUsername()+"</td>" );
printWriter.println(" <td>" +admin.getPassword()+"</td>" );
printWriter.println(" <td>" +admin.getPhone()+"</td>" );
printWriter.println(" <td>" +admin.getAddress()+"</td>" );
printWriter.println("</tr>" );
}
printWriter.println("</table>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}else {
printWriter.println("<html>" );
printWriter.println("<head>" );
printWriter.println("<meta charset='UTF-8'>" );
printWriter.println("<title>展示所有用户</title>" );
printWriter.println("</head>" );
printWriter.println("<body>" );
printWriter.println("<h3>当前没有用户!</h3>" );
printWriter.println("</body>" );
printWriter.println("</html>" );
}
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
13.8 Session实战保存验证码
13.8.1 创建验证码
导入ValidateCode.jar
创建生成验证码的Servlet
@WebServlet(name = "CreateCodeController",value = "/createCode")
public class CreateCodeController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ValidateCode code = new ValidateCode (200 , 30 , 4 , 20 );
String codes = code.getCode();
HttpSession session = request.getSession();
session.setAttribute("codes" ,codes);
code.write(response.getOutputStream());
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
13.8.2 登陆页面
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 管理员登录</title >
</head >
<body >
<form action ="/WebProject_war_exploded/loginMgr" method ="post" >
<p >
<label for ="1" > 用户名:</label >
<input type ="text" name ="username" id ="1" >
</p >
<p >
<label for ="2" > 密码: </label >
<input type ="password" name ="password" id ="2" >
</p >
<p >
<label for ="3" > 验证码:</label >
<input type ="text" name ="inputVcode" id ="3" >
<img src ="/WebProject_war_exploded/createCode" alt ="验证码" >
</p >
<p >
<input type ="submit" value ="登陆" >
</p >
</form >
</body >
</html >
13.8.3 LoginMgrController
@WebServlet(name = "LoginMgrController",value = "/loginMgr")
public class LoginMgrController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8" );
response.setContentType("text/html;charset=UTF-8" );
String username = request.getParameter("username" );
String password = request.getParameter("password" );
String inputVcode = request.getParameter("inputVcode" );
String codes = (String)request.getSession().getAttribute("codes" );
if (!inputVcode.isEmpty() && inputVcode.equalsIgnoreCase(codes)) {
ManagerService managerService = new ManagerServiceImpl ();
Manager mgr = managerService.login(username, password);
if (mgr != null ) {
HttpSession session = request.getSession();
session.setAttribute("mgr" ,mgr);
response.sendRedirect("/WebProject_war_exploded/showAllController" );
}else {
response.sendRedirect("/WebProject_war_exploded/loginMgr.html" );
}
}else {
response.sendRedirect("/WebProject_war_exploded/loginMgr.html" );
}
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
十四. ServletContext对象[重点]
14.1 ServletContext概述
全局对象, 也拥有作用域, 对应一个Tomcat中的Web应用
当Web服务器启动时, 会为每一个Web应用程序创建一块共享的存储区域(ServletContext)
ServletContext在Web服务器启动时创建, 服务器关闭时销毁
14.2 获取ServletContext对象
GenericServlet提供了getServletContext方法. (推荐) this.getServletContext();
HttpServletRequest提供了getServletContext()方法.(推荐)
HttpSession提供了getServletContext()方法
14.3 ServletContext作用
14.3.1 获取项目真实路径
String realpath=servletContext.getRealPath("/" );
14.3.2 获取项目上下文路径
System.out.println(servletContext.getContextPath());
System.out.println(request.getContextPath());
14.3.3 全局容器
ServletContext拥有作用域, 可以存储数据到全局容器中
存储数据: servletContext.setAttribute("name", value);
获取数据: servletContext.getAttribute("name");
移除数据: servletContext.removeAttribute("name");
14.4 ServletContext特点
唯一性: 一个应用对应一个ServletContext
生命周期: 只要容器不关闭或者应用不卸载, ServletContext就一直存在
14.5 ServletContext应用场景
@WebServlet(name = "ShowCounterController",value = "/showCounterController")
public class ShowCounterController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
Integer counter = (Integer) servletContext.getAttribute("counter" );
if (counter == null ) {
counter = 1 ;
}else {
counter += 1 ;
}
servletContext.setAttribute("counter" ,counter);
System.out.println("Servlet被访问次数: " + counter);
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
14.6 作用域总结
HttpServletRequest: 一次请求, 请求响应之间有效
HttpSession: 一次会话开始, 浏览器不关闭或不超时之前有效
ServletContext: 服务器启动开始, 服务器停止之前有效
十五. 过滤器[重点]
15.1 现有问题
在以往的Servlet中, 有没有冗余的代码, 多个Servlet都要进行编写
15.2 概念
过滤器(Filter) 是处于客户端与服务器目标资源之间的一道过滤技术
15.3 过滤器作用
执行地位在Servlet之前. 客户端发送请求时, 会先经过Filter, 再到达目标Servlet中; 响应时, 会根据执行流程再次反向执行Filter
可以解决多个Servlet共性代码的冗余问题(例如: 乱码处理, 登陆验证)
15.4 编写过滤器
Servlet API中提供了一个Filter接口, 开发人员编写一个Java类实现这个接口即可, 那么这个类就被称之为过滤器(Filter)
15.4.1实现过程
编写Java类实现Filter接口
在doFilter方法中编写拦截逻辑
设置拦截路径
过滤器
@WebFilter(value = "/t")
public class MyFilter implements Filter {
@Override
public void init (FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("---My Filter---" );
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("---end---" );
}
@Override
public void destroy () {
}
}
Servlet
@WebServlet(name = "TargetServlet",value = "/t")
public class TargetServlet extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("---Target---" );
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
15.5 过滤器配置
15.5.1 注解配置(推荐)
在自定义的Filter类上使用注解@WebFilter(value="/过滤目标资源")
15.5.2 xml配置
<filter >
<filter-name > Xml</filter-name >
<filter-class > com.dz.filter.XmlFilter</filter-class >
</filter >
<filter-mapping >
<filter-name > Xml</filter-name >
<url-pattern > /test</url-pattern >
</filter-mapping >
15.5.3 过滤器路径
过滤器的过滤路径通常有三种形式
精确过滤匹配 如: /index.jsp, /myservlet1
后缀过滤匹配 如: *.jsp, *.html, *.jpg
通配符过滤匹配/*, 表示拦截所有. 注意过滤器不能使用/匹配. /aaa/bbb/*允许
15.6 过滤器链和优先级
15.6.1 过滤器链
客户端对服务器请求之后, 服务器调用Servlet之前会执行一组过滤器(多个过滤器), 那么这组过滤器就称作一条过滤器链
每个过滤器实现某个特定的功能, 当第一个Filter的doFilter方法被调用时, Web服务器会创建一个代表Filter链的FilterChain对象传递给该方法, 在doFilter方法中, 开发人员如果调用了FilterChain对象的doFilter方法, 则Web服务器会检查FilterChain对象中是否还有filter, 如果有, 则调用第二个filter, 如果没有, 则调用目标资源(XxxServlet)
15.6.2 过滤器优先级
在一个Web应用中, 可以开发编写多个Filter, 这些Filter组合起来称之为一个Filter链. 优先级:
如果为注解的话, 是按照类全名称的字符串顺序决定作用顺序
如果是web.xml, 则按照filter-mapping 注册顺序, 从上往下
web.xml配置高于注解方式
如果注解和web.xml同时配置, 会创建多个过滤器对象, 造成过滤多次
15.7 过滤器经典应用
15.7.1 过滤器解决编码
@WebFilter(filterName = "EncodingFilter",value = "/*")
public class EncodingFilter implements Filter {
public void destroy () {
}
public void doFilter (ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8" );
resp.setContentType("text/html;charset=UTF-8" );
chain.doFilter(req, resp);
}
public void init (FilterConfig config) throws ServletException {
}
}
15.7.2 权限验证
@WebServlet(value = "/showAllController")
public class ShowAllAdminController extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AdminService adminService = new AdminServiceImpl ();
List<Admin> adminList = adminService.showALlAdmin();
req.getSession().setAttribute("adminList" , adminList);
resp.sendRedirect("/WebProject_war_exploded/showAllJSP" );
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
@WebFilter(filterName = "CheckFilter",value = "/showAllController")
public class CheckFilter implements Filter {
public void destroy () {
}
public void doFilter (ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
HttpSession session = request.getSession();
Manager mgr = (Manager)session.getAttribute("mgr" );
if (mgr != null ) {
chain.doFilter(request, response);
}else {
response.sendRedirect(request.getContextPath() + "/loginMgr.html" );
}
}
public void init (FilterConfig config) throws ServletException {
}
}
十六. 综合案例 (EmpProject)
16.1 数据库环境搭建
该案例是EmpProject员工管理系统, 使用了两张表
16.1.1 创建数据库
CREATE DATABASE emp;
USE emp;
16.1.2 创建数据库表
CREATE TABLE emp(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR (20 ) NOT NULL ,
salary DOUBLE NOT NULL ,
age INT NOT NULL
)CHARSET= utf8;
CREATE TABLE empManager(
username VARCHAR (20 ) NOT NULL ,
PASSWORD VARCHAR (20 ) NOT NULL
)CHARSET= utf8;
项目中的entity实体层代码此处未给出, 根据数据库表自行创建即可
16.2 创建Web项目
创建Web项目, 导入相关jar包
mysql-connector-java-5.1.25-bin.jar
druid-1.1.5.jar
commons-dbutils-1.7.jar
ValidateCode.jar
16.3 基础环境搭建
项目下创建包目录结构
com.dz.emp.controller 调用业务逻辑的Servlet
com.dz.emp.dao 数据访问层
com.dz.emp.dao.impl 数据访问层实现类
com.dz.emp.entity 实体类
com.dz.emp.filter 过滤器
com.dz.emp.jsp 打印显示页面的Servlet
com.dz.emp.service 业务逻辑层
com.dz.emp.service.impl 业务逻辑层实现类
com.dz.emp.utils 工具类
database.properties 数据库连接及连接池配置文件
web下创建empLogin.html
16.4 database.properties配置文件
#<!-- 连接设置 -->
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#<!-- 最大连接数量 -->
maxActive=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 60000 毫秒/1000 等于60 秒 -->
maxWait=3000
16.5 DbUtils工具类
public class DbUtils {
private static DruidDataSource ds;
private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal <>();
static {
Properties properties = new Properties ();
try {
InputStream inputStream = DbUtils.class.getResourceAsStream("/database.properties" );
properties.load(inputStream);
ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection () {
Connection conn = THREAD_LOCAL.get();
try {
if (conn == null ) {
conn = ds.getConnection();
THREAD_LOCAL.set(conn);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
public static void begin () {
Connection conn = null ;
try {
conn = getConnection();
conn.setAutoCommit(false );
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public static void commit () {
Connection conn = null ;
try {
conn = getConnection();
conn.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
closeAll(conn,null ,null );
}
}
public static void rollback () {
Connection conn = null ;
try {
conn = getConnection();
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
closeAll(conn,null ,null );
}
}
public static void closeAll (Connection conn, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null ) {
resultSet.close();
}
if (statement != null ) {
statement.close();
}
if (conn != null ) {
conn.close();
THREAD_LOCAL.remove();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
16.6 dao数据访问层
16.6.1 EmpManagerDao接口
public interface EmpManagerDao {
EmpManager select (String username) ;
}
16.6.2 EmpDao接口
public interface EmpDao {
int insert (Emp emp) ;
int delete (int id) ;
int update (Emp emp) ;
Emp select (int id) ;
List<Emp> selectAll () ;
}
16.6.3 EmpManagerDao接口实现类
public class EmpManagerDaoImpl implements EmpManagerDao {
private QueryRunner queryRunner = new QueryRunner ();
@Override
public EmpManager select (String username) {
try {
EmpManager empManager = queryRunner.query(DbUtils.getConnection(),"select * from empManager where username=?" , new BeanHandler <EmpManager>(EmpManager.class), username);
return empManager;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
}
16.6.4 EmpDao接口实现类
public class EmpDaoImpl implements EmpDao {
private QueryRunner queryRunner = new QueryRunner ();
@Override
public int insert (Emp emp) {
try {
int result = queryRunner.update(DbUtils.getConnection(), "insert into emp(name,salary,age) values(?,?,?)" , emp.getName(), emp.getSalary(), emp.getAge());
return result;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return 0 ;
}
@Override
public int delete (int id) {
try {
int result = queryRunner.update(DbUtils.getConnection(),"delete from emp where id = ?" ,id);
return result;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return 0 ;
}
@Override
public int update (Emp emp) {
try {
int result = queryRunner.update(DbUtils.getConnection(), "update emp set name=?,salary=?,age=? where id=?" , emp.getName(), emp.getSalary(), emp.getAge(), emp.getId());
return result;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return 0 ;
}
@Override
public Emp select (int id) {
try {
Emp emp = queryRunner.query(DbUtils.getConnection(), "select * from emp where id=?" , new BeanHandler <Emp>(Emp.class), id);
return emp;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
@Override
public List<Emp> selectAll () {
try {
List<Emp> empList = queryRunner.query(DbUtils.getConnection(), "select * from emp" , new BeanListHandler <Emp>(Emp.class));
return empList;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
}
16.7 service业务逻辑层
16.7.1 EmpManagerService接口
public interface EmpManagerService {
EmpManager login (String username,String password) ;
}
16.7.2 EmpService接口
public interface EmpService {
int addEmp (Emp emp) ;
int removeEmp (int id) ;
int modify (Emp emp) ;
Emp showEmp (int id) ;
List<Emp> showAllEmp () ;
}
16.7.3 EmpManagerService接口实现类
public class EmpManagerServiceImpl implements EmpManagerService {
private EmpManagerDao empManagerDao = new EmpManagerDaoImpl ();
@Override
public EmpManager login (String username, String password) {
EmpManager empManager = null ;
try {
DbUtils.begin();
EmpManager temp = empManagerDao.select(username);
if (temp != null ) {
if (temp.getPassword().equals(password)) {
empManager = temp;
}
}
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return empManager;
}
}
16.7.4 EmpService接口实现类
public class EmpServiceImpl implements EmpService {
private EmpDao empDao = new EmpDaoImpl ();
@Override
public int addEmp (Emp emp) {
int result = 0 ;
try {
DbUtils.begin();
result = empDao.insert(emp);
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return result;
}
@Override
public int removeEmp (int id) {
int result = 0 ;
try {
DbUtils.begin();
result = empDao.delete(id);
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return result;
}
@Override
public int modify (Emp emp) {
int result = 0 ;
try {
DbUtils.begin();
result = empDao.update(emp);
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return 0 ;
}
@Override
public Emp showEmp (int id) {
Emp emp = null ;
try {
DbUtils.begin();
emp = empDao.select(id);
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return emp;
}
@Override
public List<Emp> showAllEmp () {
List<Emp> empList = new ArrayList <>();
try {
DbUtils.begin();
List<Emp> temp = empDao.selectAll();
if (temp != null ) {
empList = temp;
}
DbUtils.commit();
} catch (Exception e) {
DbUtils.rollback();
e.printStackTrace();
}
return empList;
}
}
16.8 controller(调用业务逻辑的Servlet)
16.8.1 创建验证码
@WebServlet(name = "CreateCodeController",value = "/createCode")
public class CreateCodeController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ValidateCode validateCode = new ValidateCode (200 , 30 , 4 , 20 );
String codes = validateCode.getCode();
HttpSession session = request.getSession();
session.setAttribute("codes" ,codes);
validateCode.write(response.getOutputStream());
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.8.2 管理员登陆
@WebServlet(name = "EmpManagerLoginController",value = "/manager/EmpManagerLoginController")
public class EmpManagerLoginController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username" );
String password = request.getParameter("password" );
String inputVcode = request.getParameter("inputVcode" );
String codes = (String)request.getSession().getAttribute("codes" );
if (!inputVcode.isEmpty() && inputVcode.equalsIgnoreCase(codes)) {
EmpManagerService empManagerService = new EmpManagerServiceImpl ();
EmpManager empManager = empManagerService.login(username,password);
if (empManager != null ) {
HttpSession session = request.getSession();
session.setAttribute("empManager" ,empManager);
response.sendRedirect(request.getContextPath() + "/manager/safe/showAllEmpController" );
}else {
response.sendRedirect( request.getContextPath() + "/empLogin.html" );
}
}else {
response.sendRedirect( request.getContextPath() + "/empLogin.html" );
}
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.8.3 查询所有员工信息
@WebServlet(name = "ShowAllEmpController",value = "/manager/safe/showAllEmpController")
public class ShowAllEmpController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
EmpService empService = new EmpServiceImpl ();
List<Emp> empList = empService.showAllEmp();
if (empList != null ) {
request.setAttribute("empList" ,empList);
request.getRequestDispatcher("/manager/safe/showAllEmpJSP" ).forward(request,response);
}
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.8.4 查询单个员工信息
@WebServlet(name = "ShowEmpController",value = "/manager/safe/showEmpController")
public class ShowEmpController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer id = Integer.valueOf(request.getParameter("id" ));
EmpService empService = new EmpServiceImpl ();
Emp emp = empService.showEmp(id);
request.setAttribute("emp" ,emp);
request.getRequestDispatcher("/manager/safe/showUpdateEmpInfoJSP" ).forward(request,response);
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.8.5 新增员工信息
@WebServlet(name = "InsertEmpController",value = "/manager/safe/insertEmpController")
public class InsertEmpController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name" );
Double salary = Double.valueOf(request.getParameter("salary" ));
Integer age = Integer.valueOf(request.getParameter("age" ));
Emp emp = new Emp (name,salary,age);
EmpService empService = new EmpServiceImpl ();
empService.addEmp(emp);
response.sendRedirect(request.getContextPath() + "/manager/safe/showAllEmpController" );
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.8.6 删除单个员工信息
@WebServlet(name = "RemoveEmpController",value = "/manager/safe/removeEmpController")
public class RemoveEmpController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer id = Integer.valueOf(request.getParameter("id" ));
EmpService empService = new EmpServiceImpl ();
empService.removeEmp(id);
response.sendRedirect(request.getContextPath() + "/manager/safe/showAllEmpController" );
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.8.7 修改单个员工信息
@WebServlet(name = "UpdateEmpController",value = "/manager/safe/updateEmpController")
public class UpdateEmpController extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer id = Integer.valueOf(request.getParameter("id" ));
String name = request.getParameter("name" );
Double salary = Double.valueOf(request.getParameter("salary" ));
Integer age = Integer.valueOf(request.getParameter("age" ));
Emp emp = new Emp (id, name, salary, age);
EmpService empService = new EmpServiceImpl ();
empService.modify(emp);
response.sendRedirect(request.getContextPath() + "/manager/safe/showAllEmpController" );
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.9 filter过滤器
16.9.1 字符编码过滤器
@WebFilter(filterName = "EncodingFilter",value = "/manager/*")
public class EncodingFilter implements Filter {
public void destroy () {
}
public void doFilter (ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8" );
resp.setContentType("text/html;charset=UTF-8" );
chain.doFilter(req, resp);
}
public void init (FilterConfig config) throws ServletException {
}
}
16.9.2 权限验证过滤器
@WebFilter(filterName = "CheckFilter",value = "/manager/safe/*")
public class CheckFilter implements Filter {
public void destroy () {
}
public void doFilter (ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
HttpSession session = request.getSession();
EmpManager empManager = (EmpManager) session.getAttribute("empManager" );
if (empManager != null ) {
chain.doFilter(request, response);
}else {
response.sendRedirect(request.getContextPath() + "/empLogin.html" );
}
}
public void init (FilterConfig config) throws ServletException {
}
}
16.10 jsp(打印显示页面的Servlet)
16.10.1 展示所有用户信息的页面
@WebServlet(name = "showAllEmpJSP",value = "/manager/safe/showAllEmpJSP")
public class showAllEmpJSP extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Emp> empList = (List<Emp>)request.getAttribute("empList" );
PrintWriter printWriter = response.getWriter();
printWriter.println("<html>" );
printWriter.println(" <head>" );
printWriter.println(" <meta charset='UTF-8'>" );
printWriter.println(" <title>查询所有员工页面</title>" );
printWriter.println(" </head>" );
printWriter.println(" <body>" );
printWriter.println(" <form action='/EmpProject/manager/safe/showInsertEmpJSP'>" );
printWriter.println(" <p><input type='submit' value='新增'></p>" );
printWriter.println(" </form>" );
printWriter.println(" <table border='1'>" );
printWriter.println(" <tr>" );
printWriter.println(" <td>编号</td>" );
printWriter.println(" <td>姓名</td>" );
printWriter.println(" <td>工资</td>" );
printWriter.println(" <td>年龄</td>" );
printWriter.println(" <td colspan='2'>操作</td>" );
printWriter.println(" </tr>" );
for (Emp emp : empList) {
printWriter.println(" <tr>" );
printWriter.println(" <td>" +emp.getId()+"</td>" );
printWriter.println(" <td>" +emp.getName()+"</td>" );
printWriter.println(" <td>" +emp.getSalary()+"</td>" );
printWriter.println(" <td>" +emp.getAge()+"</td>" );
printWriter.println(" <td><a href='" +request.getContextPath() + "/manager/safe/removeEmpController?id=" +emp.getId()+"" +"'>删除</a></td>" );
printWriter.println(" <td><a href = " +request.getContextPath() + "/manager/safe/showEmpController?id=" +emp.getId()+"" +">修改</a></td>" );
printWriter.println(" </tr>" );
}
printWriter.println(" </table>" );
printWriter.println(" </body>" );
printWriter.println("</html>" );
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.10.2 展示新增员工操作时的页面
@WebServlet(name = "ShowInsertEmpJSP",value = "/manager/safe/showInsertEmpJSP")
public class ShowInsertEmpJSP extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter printWriter = response.getWriter();
printWriter.println("<html>" );
printWriter.println(" <head>" );
printWriter.println(" <meta charset='UTF-8'>" );
printWriter.println(" <title>新增员工信息页面</title>" );
printWriter.println(" </head>" );
printWriter.println(" <body>" );
printWriter.println(" <form action='/EmpProject/manager/safe/insertEmpController' method='post'>" );
printWriter.println(" <p>姓名:<input type='text' name='name'></p>" );
printWriter.println(" <p>工资:<input type='text' name='salary'></p>" );
printWriter.println(" <p>年龄:<input type='text' name='age'></p>" );
printWriter.println(" <p><input type='submit' value='提交'></p>" );
printWriter.println(" </form>" );
printWriter.println(" </body>" );
printWriter.println("</html>" );
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.10.3 展示修改员工信息时的页面
@WebServlet(name = "ShowUpdateEmpInfoJSP",value = "/manager/safe/showUpdateEmpInfoJSP")
public class ShowUpdateEmpInfoJSP extends HttpServlet {
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Emp emp = (Emp) request.getAttribute("emp" );
PrintWriter printWriter = response.getWriter();
printWriter.println("<html>" );
printWriter.println(" <head>" );
printWriter.println(" <meta charset='UTF-8'>" );
printWriter.println(" <title>修改员工信息页面</title>" );
printWriter.println(" </head>" );
printWriter.println(" <body>" );
printWriter.println(" <form action='/EmpProject/manager/safe/updateEmpController' method='post'>" );
printWriter.println(" <p>编号:<input type='text' name='id' value='" +emp.getId()+"' readonly></p>" );
printWriter.println(" <p>姓名:<input type='text' name='name' value='" +emp.getName()+"'></p>" );
printWriter.println(" <p>工资:<input type='text' name='salary' value='" +emp.getSalary()+"'></p>" );
printWriter.println(" <p>年龄:<input type='text' name='age' value='" +emp.getAge()+"'></p>" );
printWriter.println(" <p><input type='submit' value='修改'></p>" );
printWriter.println(" </form>" );
printWriter.println(" </body>" );
printWriter.println("</html>" );
}
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
16.11 empLogin.html
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 管理员登录</title >
</head >
<body >
<form action ="/EmpProject/manager/EmpManagerLoginController" method ="post" >
<p >
<label for ="1" > 用户名:</label >
<input type ="text" name ="username" id ="1" >
</p >
<p >
<label for ="2" > 密码: </label >
<input type ="password" name ="password" id ="2" >
</p >
<p >
<label for ="3" > 验证码:</label >
<input type ="text" name ="inputVcode" id ="3" >
<img src ="/EmpProject/createCode" alt ="验证码" >
</p >
<p >
<input type ="submit" value ="登陆" >
</p >
</form >
</body >
</html >
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步