1. Servlet
1.1 概念:
server applet, 运行在服务器端的小程序
- Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。
- 将来我们自定义一个类,实现Servlet接口,复写方法。
1.2 快速入门:
1.21 创建JavaEE项目
- 点击
New->project
/Module
->JavaEnterprise
- 配置
Tomcat
, 并选择Web Application
示例:
2.2 定义一个类,实现Servlet接口
1 | public class ServletDemo01 implements Servlet |
2.3 实现接口中的抽象方法
1 | package com.uesct.web.servlet; |
2.4 配置Servlet
在web.xml
中配置:
1 | <!--配置servlet--> |
2.5 启动tomcat服务器
示例:
多个项目如何部署呢?
1. Deployment 设置中war exploded
在浏览器里分别根据虚拟路径+映射的url
进行不同项目的访问
1.3 Servlet的执行原理
- 当服务器接受到客户端浏览器的请求后,会解析请求
URL
路径,获取访问的Servlet
的资源路径 - 查找
web.xml
文件,是否有对应的<url-pattern>
标签体内容。 - 如果有,则在找到对应的
<servlet-class>
全类名 tomcat
会将字节码文件加载进内存,并且创建其对象- 调用其方法
1.4 Servlet中的生命周期方法:
1.41 init方法
被创建:执行init
方法,只执行一次
1 | public void init(ServletConfig servletConfig) throws ServletException |
Servlet什么时候被创建?
默认情况下,第一次被访问时,Servlet被创建
可以配置执行Servlet的创建时机。
在
<servlet>
标签下配置
第一次被访问时,创建
<load-on-startup>
的值为负数在服务器启动时,创建
<load-on-startup>
的值为0
或正整数
Servlet是单例的
Servlet的init
方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
问题:多个用户同时访问时,可能存在线程安全问题。
解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值
1.42 service方法
提供服务:执行service
方法,执行多次
1 | public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException |
每次访问Servlet时,service
方法都会被调用一次。
1.43 destroy方法
被销毁:执行destroy
方法,只执行一次
- Servlet被销毁时执行。服务器关闭时,Servlet被销毁
- 只有服务器正常关闭时,才会执行
destroy
方法。 - destroy方法在Servlet被销毁之前执行,一般用于释放资源
1.5 Servlet3.0:
好处: 支持注解配置。可以不需要web.xml
了。
步骤:
创建JavaEE项目,选择Servlet的版本
3.0
以上,可以不创建web.xml
定义一个类,实现Servlet接口
复写方法
在类上使用
@WebServlet
注解,进行配置@WebServlet("资源路径")
1
2
3
4
5"/demo") (urlpatterns=
或者
"/demo") (value=
或者省略value
"/demo") (
@WebServlet
注解
1 | ({ElementType.TYPE}) |
示例:
新建web项目,注意不勾选Create web.xml
1.6 IDEA与tomcat的相关配置
- IDEA会为每一个tomcat部署的项目单独建立一份配置文件
查看控制台的Log:
1
Using CATALINA_BASE: "C:\Users\LiuFei\.IntelliJIdea2017.3\system\tomcat\_servlet01"
- 工作空间项目和 tomcat部署的web项目
tomcat
真正访问的是“tomcat
部署的web
项目”,”tomcat
部署的web
项目”对应着”工作空间项目” 的web目录下的所有资源WEB-INF
目录下的资源不能被浏览器直接访问。
- 断点调试:使用”小虫子”启动 dubug 启动
1.7 Servlet的体系结构
1 | Servlet -- 接口 |
1.71 GenericServlet
GenericServlet
:将Servlet
接口中其他的方法做了默认空实现,只将service()
方法作为抽象, 将来定义Servlet类时,可以继承GenericServlet
,实现service()
方法即可.
1.72 HttpServlet:
HttpServlet
对http
协议的一种封装,简化操作
定义类继承
HttpServlet
复写
doGet/doPost
方法1
2
3
4
5
6
7
8
9
10
11"/demo1") (
public class ServletDemo01 extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet....");
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost...");
}
}
1.8 Servlet相关配置
urlpartten:Servlet访问路径
1.81 一个Servlet
可以定义多个访问路径 :
@WebServlet({"/d1","/d2","/d3"})
1.82 路径定义规则:
/xxx
:路径匹配/xxx/xxx
:多层路径,目录结构*.do
:扩展名匹配
2. HTTP协议
2.1 概念:
Hyper Text Transfer Protocol 超文本传输协议
2.11 传输协议:
定义了,客户端和服务器端通信时,发送数据的格式
2.12 特点:
- 基于
TCP/IP
的高级协议 - 默认端口号:
80
- 基于请求/响应模型的:一次请求对应一次响应
- 无状态的:每次请求之间相互独立,不能交互数据
2.13 历史版本:
1.0
:每一次请求响应都会建立新的连接1.1
:复用连接
2.2 request
2.21 请求消息数据格式
字符串格式:
1 | POST /login.html HTTP/1.1 |
2.211 请求行
请求方式 请求url
请求协议/版本GET /login.html HTTP/1.1
2.2111 请求方式:
HTTP
协议有7
中请求方式,常用的有2
种
GET
:- 请求参数在请求行中,在
url
后。 - 请求的
url
长度有限制的 - 不太安全
- 请求参数在请求行中,在
POST
:- 请求参数在请求体中
- 请求的
url
长度没有限制的 - 相对安全
2.212 请求头:
客户端浏览器告诉服务器一些信息
请求头名称: 请求头值
常见的请求头:
User-Agent
:浏览器告诉服务器,我访问你使用的浏览器版本信息- 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
Referer
:http://localhost/login.html告诉服务器,我(当前请求)从哪里来?
作用:
防盗链:
统计工作:
2.213 请求空行
空行,就是用于分割POST
请求的请求头和请求体的。
2.214 请求体(正文):
- 封装POST请求消息的请求参数的
2.22 Request对象
2.221. request对象和response对象的原理
request和response对象是由服务器创建的。我们来使用它们
request对象是来获取请求消息,response对象是来设置响应消息
2.222 request对象继承体系结构:
1 | ServletRequest -- 接口 |
2.223 request功能:
2.2231 获取请求消息数据
2.2232 获取请求行数据
1 | GET /day14/demo1?name=zhangsan HTTP/1.1 |
方法:
获取请求方式 :
GET
String getMethod()
获取虚拟目录:
/day14
String getContextPath()
获取Servlet路径:
/demo1
String getServletPath()
获取
get
方式请求参数:name=zhangsan
String getQueryString()
获取请求
URI
:/day14/demo1
String getRequestURI():
/day14/demo1
StringBuffer getRequestURL()
:http://localhost/day14/demo1
URL
:统一资源定位符 : http://localhost/day14/demo1 中华人民共和国URI
:统一资源标识符 : /day14/demo1 共和国获取协议及版本:
HTTP/1.1
String getProtocol()
获取客户机的IP地址:
String getRemoteAddr()
示例:
1 | package com.uestc.web.servlet02; |
2.2233 获取请求头数据
方法:
String getHeader(String name):
通过请求头的名称获取请求头的值
Enumeration<String> getHeaderNames():
获取所有的请求头名称
示例1:打印所有的请求头的名称以及对于的值
1 | package com.uestc.web.servlet02; |
示例2:
1 | "/demo01"}) ({ |
2.2234 获取请求体数据:
请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
步骤:
获取流对象
BufferedReader getReader():
获取字符输入流,只能操作字符数据ServletInputStream getInputStream():
获取字节输入流,可以操作所有类型数据,在文件上传知识点后讲解再从流对象中拿数据
示例:
- 首先创建
regist.html
1 |
|
- 然后创建
RequestDemo01.java
文件
1 | "/requestDemo01") ( |
- 启动tomcat服务器,在浏览区中访问
http://localhost:8080/servlet02/regist.html
2.224 其他功能:
2.2241. 获取请求参数通用方式:
不论get
还是post
请求方式都可以使用下列方法来获取请求参数
String getParameter(String name):
根据参数名称获取参数值 username=zs&password=123示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21"/requestDemo01") (
public class RequestDemo01 extends HttpServlet{
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//get 获取请求参数
//根据参数的名称获取参数值
String username=req.getParameter("username");
System.out.println("get");
System.out.println(username);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post 获取请求参数
//根据参数的名称获取参数值
String username=req.getParameter("username");
System.out.println("post");
System.out.println(username);
}
}
String[] getParameterValues(String name):
根据参数名称获取参数值的数组hobby=xx&hobby=game
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13//servlet类
"/requestDemo01") (
public class RequestDemo01 extends HttpServlet{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post 获取请求参数
//根据参数名称获取参数值的数组
String [] hobbies=req.getParameterValues("hobby");
for(String hobby:hobbies){
System.out.println(hobby);
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<!-- regist.html-->
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<form action="/servlet02/requestDemo01" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输出密码" name="password"><br>
<input type="checkbox" name="hobby" value="game">游戏
<input type="checkbox" name="hobby" value="study">学习
<input type="submit" type="注册">
</form>
</body>
</html>
Enumeration<String> getParameterNames():
获取所有请求的参数名称示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15"/requestDemo01") (
public class RequestDemo01 extends HttpServlet{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post 获取请求参数
//根据参数名称获取参数值的数组
Enumeration<String> parameterNames=req.getParameterNames();
while(parameterNames.hasMoreElements()){
String name=parameterNames.nextElement();
System.out.println(name);
String value=req.getParameter(name);
System.out.println(value);
System.out.println("---------------------------");
}
}Map<String,String[]> getParameterMap():
获取所有参数的map集合示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18"/requestDemo01") (
public class RequestDemo01 extends HttpServlet{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post 获取请求参数
//根据参数名称获取参数值的数组
Map<String, String []> map=req.getParameterMap();
Set<String> set=map.keySet();
for(String name:set){
String [] values=map.get(name);
System.out.println(name);
for(String value:values){
System.out.println(value);
}
System.out.println("--------------");
}
}
}
中文乱码问题:
get
方式:tomcat 8
已经将get
方式乱码问题解决了post
方式:会乱码- 解决:在获取参数前,设置
request
的编码request.setCharacterEncoding("utf-8");
- 解决:在获取参数前,设置
2.2242 请求转发:
一种在服务器内部的资源跳转方式
步骤:
通过
request
对象获取请求转发器对象:RequestDispatcher
1
getRequestDispatcher(String path)
使用
RequestDispatcher
对象来进行转发:1
forward(ServletRequest request, ServletResponse response)
特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中。
- 转发是一次请求
示例:
新建RequestDemo02.java
1 | "/requestDemo02") ( |
2.2243 共享数据:
域对象:
一个有作用范围的对象,可以在范围内共享数据
request域:
代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
void setAttribute(String name,Object obj):
存储数据Object getAttitude(String name):
通过键获取值void removeAttribute(String name):
通过键移除键值对获取
ServletContext
:ServletContext getServletContext()
示例:
1 | "/requestDemo02") ( |
1 | "/requestDemo01") ( |
2.3 案例1:用户登录
2.31 用户登录案例需求:
编写
login.html
登录页面
username
&password
两个输入框使用
Druid
数据库连接池技术,操作mysql
day14数据库中user表
使用
JdbcTemplate
技术封装JDBC
登录成功跳转到
SuccessServlet
展示:登录成功!用户名,欢迎您
登录失败跳转到
FailServlet
展示:登录失败,用户名或密码错误
2.32 开发步骤
- 创建项目,导入
html
页面,配置文件,jar
包
导入jar
包之后需要Add as Library
- 创建数据库环境
1
2
3
4
5
6
7CREATE DATABASE day14;
USE day14;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(32) UNIQUE NOT NULL,
password VARCHAR(32) NOT NULL
);
创建包
com.uestc.domin
,创建类User
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43package com.uestc.domin;
/**
* 用户的实体类
*/
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}创建包
com.uestc.util
,编写工具类JDBCUtils`1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45package com.uestc.util;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* JDBC工具类,使用Durid连接池
*/
public class JDBCUtils {
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro=new Properties();
//使用classLoader加载配置文件,获取字节输入流
InputStream is=JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化连接池对象
ds=DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接池对象
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 获取连接Connection对象
*/
}创建包
com.uestc.dao
,创建类UserDao
,提供login
方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.uestc.dao;
import com.uestc.domin.User;
import com.uestc.util.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
/**
*操作数据库中User表的类
*/
public class UserDao {
//生命JDBCTemplate对象共用
private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 登陆方法
* @param loginUser 只有用户名和密码
* @return user包含用户全部数据
*/
public User login(User loginUser){
//1.编写sql
String sql="select * from user where username=? and password=?";
//2.调用query方法
User user=template.queryForObject(sql,
new BeanPropertyRowMapper<User>(User.class),
loginUser.getUsername(),loginUser.getPassword());
return user;
}
}单元测试
login
方法,新建包com.uestc.test
, 创建UserDaoTest
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.uestc.test;
import com.uestc.dao.UserDao;
import com.uestc.domin.User;
import org.junit.Test;
public class UserDaoTest {
public void testLogin(){
User loginUser=new User();
loginUser.setUsername("liufei");
loginUser.setPassword("123456");
UserDao dao=new UserDao();
User user=dao.login(loginUser);
System.out.println(user);
}
}
编写
cn.uestc.web.servlet.LoginServlet
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47package com.uestc.web.servlet;
import com.uestc.dao.UserDao;
import com.uestc.domin.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
"/loginServlet") (
public class LoginServlet extends HttpServlet{
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("utf-8");
//2.获取请求参数
String username=req.getParameter("username");
String password=req.getParameter("password");
//3.封装user对象
User loginUser=new User();
loginUser.setUsername(username);
loginUser.setPassword(password);
//4.调用UserDao的login的方法
UserDao dao=new UserDao();
User user=dao.login(loginUser);
//5.判断user
if(user==null){
//登录失败
req.getRequestDispatcher("/failServlet").forward(req,resp);
}else{
//登录成功
//存储数据
req.setAttribute("user",user);
//转发
req.getRequestDispatcher("/successServlet").forward(req,resp);
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}编写
FailServlet
和SuccessServlet
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27//FailServlet类
package com.uestc.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
"/failServlet") (
public class FailedServlet extends HttpServlet{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//给页面写一句话
//设置编码
resp.setContentType("text/html;charset=utf-8");
//输出
resp.getWriter().write("登录失败, 用户名或密码错误");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32//SuccessServlet类
package com.uestc.web.servlet;
import com.uestc.domin.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
"/successServlet") (
public class SuccessServlet extends HttpServlet{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//给页面写一句话
//获取request域中共享的user对象
User user=(User)req.getAttribute("user");
if(user!=null){
//设置编码
resp.setContentType("text/html;charset=utf-8");
//输出
resp.getWriter().write("登录成功!"+user.getUsername()+"欢迎您!");
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}login.html
中form
表单的action
路径的写法1
虚拟目录+Servlet的资源路径
示例:
![image-20201018151952299](C:\Users\Liu Fei\AppData\Roaming\Typora\typora-user-images\image-20201018151952299.png)
![image-20201018152115095](C:\Users\Liu Fei\AppData\Roaming\Typora\typora-user-images\image-20201018152115095.png)
BeanUtils
工具类,简化数据封装首先导入
beanUtils
的jar
包 然后使用
beanUtils
![image-20201018154652738](C:\Users\Liu Fei\AppData\Roaming\Typora\typora-user-images\image-20201018154652738.png)
2.31 BeanUtils工具类
BeanUtils
用于封装JavaBean
的
JavaBean
:标准的Java
类, 用于封装数据
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
注意的成员变量和属性的区别:
属性:setter
和getter
方法截取后的产物
例如:getUsername()
–> Username
–> username
有时候属性和成员变量不相同
方法:
setProperty()
getProperty()
populate(Object obj , Map map)
:将map集合的键值对信息,封装到对应的JavaBean
对象中
示例:
2.4 response
响应消息:服务器端发送给客户端的数据
2.41 响应消息的数据格式
字符串格式:
1 | #响应字符串格式 |
2.411 响应行
2.4111组成:
协议/版本 响应状态码 状态码描述
2.4112 响应状态码:
服务器告诉客户端浏览器本次请求和响应的一个状态。
状态码都是3位数字
状态码分类:
1xx
:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码2xx
:成功。代表:200
3xx
:重定向。代表:302
(重定向),304
(访问缓存)4xx
:客户端错误。代表:
404
(请求路径没有对应的资源)405
:请求方式没有对应的doXxx
方法
5xx
:服务器端错误。代表:500
(服务器内部出现异常)
2.412 响应头:
2.4121 格式:
头名称: 值
2.4122 常见的响应头:
头名称:
Content-Type
:服务器告诉客户端本次响应体数据格式以及编码格式Content-disposition
:服务器告诉客户端以什么格式打开响应体数据值:
in-line
: 默认值,在当前页面内打开attachment;filename=xxx
:以附件形式打开响应体。文件下载
2.413 响应空行
2.414 响应体:
传输的数据
2.42 Response对象
功能:设置响应消息
2.421 设置响应行
格式:HTTP/1.1 200 ok
设置状态码:setStatus(int sc)
2.422 设置响应头:
setHeader(String name, String value)
2.423 设置响应体:
使用步骤:
获取输出流
字符输出流:
PrintWriter getWriter()
字节输出流:
ServletOutputStream getOutputStream()
使用输出流,将数据输出到客户端浏览器
2.43 案例:
重定向:资源跳转的方式
2.4311 代码实现:
1 | //1. 设置状态码为302 |
创建
ResponseDemo01
Servlet类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package com.uestc.web.servlet;
import com.sun.org.apache.xpath.internal.SourceTree;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 重定向
* 访问/responseDemo01,会自动跳转到/responseDemo02
*/
"/responseDemo01") (
public class ResponseDemo01 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("responseDemo01启动。。。");
//1.设置状态码302
resp.setStatus(302);
//设置响应头location
resp.setHeader("location","/servlet03/responseDemo02");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}创建
ResponseDemo02
Servlet类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package com.uestc.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
"/responseDemo02") (
public class ResponseDemo02 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("responseDemo02启动。。。");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
简单的重定向方法:
1 | response.sendRedirect("/day15/responseDemo2"); |
2.4311 forward 和 redirect 区别
2.43111 重定向的特点: redirect
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求。不能使用request对象来共享数据
2.43112 转发的特点:forward
- 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源 3. 转发是一次请求,可以使用request对象来共享数据
2.4312 路径写法:
路径分类
相对路径:通过相对路径不可以确定唯一资源
- 如:
./index.html
- 不以
/
开头,以.
开头路径
规则:找到当前资源和目标资源之间的相对位置关系
./
:当前目录../
: 后退一级目录- 如:
绝对路径:通过绝对路径可以确定唯一资源
- 如:http://localhost/day15/responseDemo2 /day15/responseDemo2
- 以
/
开头的路径
规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
给
客户端浏览器
使用:需要加虚拟目录
(项目的访问路径)建议:虚拟目录动态获取:
request.getContextPath()
如
<a>
,<form>
重定向
…给
服务器
使用:不需要加虚拟目录转发路径
2.432 服务器输出字符数据到浏览器
2.4321 步骤:
获取字符输出流
输出数据
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.uestc.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
"/responseDemo03") (
public class ResponseDemo03 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取字符输出流
PrintWriter pw=resp.getWriter();
//2.输出数据
pw.write("<h1>hello response</h2>");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
2.4322 乱码问题:
PrintWriter pw = response.getWriter()
;获取的流的默认编码是ISO-8859-1
设置该流的默认编码
告诉浏览器响应体使用的编码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package com.uestc.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
"/responseDemo03") (
public class ResponseDemo03 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取流对象之前,设置流的默认编码:ISO-8859-1 设置为:GBK
//resp.setCharacterEncoding("utf-8");
//告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码
//resp.setHeader("content-type", "text/html;charset=utf-8");
//简单的形式,设置编码
resp.setContentType("text/html;charset=utf-8");
//1.获取字符输出流
PrintWriter pw=resp.getWriter();
//2.输出数据
pw.write("<h1>您好啊, response</h2>");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
2.433 服务器输出字节数据到浏览器
2.4331 步骤:
获取字节输出流
输出数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package com.uestc.web.servlet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
"/responseDemo04") (
public class ResponseDemo04 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
//1.获取字节输出流
ServletOutputStream sos=resp.getOutputStream();
//2.输出数据
sos.write("你好".getBytes("utf-8"));
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}2.434 验证码
本质:图片
目的:防止恶意表单注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64package com.uestc.web.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
"/checkCode") (
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int width=100;
int height=50;
//1.创建对象,在内存中的图片(验证码图片对象)
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1 背景填充
//获取画笔对象
Graphics g=image.getGraphics();
//设置画笔颜色
g.setColor(Color.PINK);
//填充颜色
g.fillRect(0,0,width,height);
//2.2 画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width-1,height-1);
String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//生成随机角标
Random rd=new Random();
for(int i=0;i<4;i++){
int index=rd.nextInt(str.length());
//获取字符
char ch=str.charAt(index);
//2.3 写验证码
g.drawString(ch+"",(width/5)*(i+1),25);
}
//2.4 画干扰线
//生成随机坐标点
for(int i=0;i<5;i++){
int x1=rd.nextInt(width);
int y1=rd.nextInt(height);
int x2=rd.nextInt(width);
int y2=rd.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",resp.getOutputStream());
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
2.5 ServletContext对象
2.51 概念:
代表整个web应用,可以和程序的容器(服务器)来通信
2.52 获取:
通过
request
对象获取1
request.getServletContext();
通过
HttpServlet
获取1
this.getServletContext();
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18"/servletContextDemo1") (
public class ServletContextDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通过request对象获取
ServletContext context1=req.getServletContext();
//通过HttpServlet获取
ServletContext context2=this.getServletContext();
System.out.println(context1);
System.out.println(context2);
System.out.println(context1.equals(context2));
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
2.53 功能:
2.531 获取MIME类型:
MIME类型:在互联网通信过程中定义的一种文件数据类型
格式: 大类型/小类型 text/html
image/jpeg
获取:
1 | String getMimeType(String file) |
示例:
1 | "/servletContextDemo1") ( |
2.532 域对象:共享数据
1 | 1. setAttribute(String name,Object value) |
ServletContext
对象范围:所有用户所有请求的数据
示例:
新建
servletContextDemo1.java
,通过ServletContext
域对象赋值1
2
3
4
5
6
7
8
9
10
11
12
13
14"/servletContextDemo2") (
public class ServletContextDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context=this.getServletContext();
String msg=(String)context.getAttribute("msg");
System.out.println(msg);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}新建
servletContextDemo2.java
,获取ServletContext
域对象的值1
2
3
4
5
6
7
8
9
10
11
12
13
14"/servletContextDemo2") (
public class ServletContextDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context=this.getServletContext();
String msg=(String)context.getAttribute("msg");
System.out.println(msg);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
2.533 获取文件的真实(服务器)路径
方法:
1 | String getRealPath(String path) |
示例: 想要获取文件的真实路径(区别与工作空间的目录)
1 | "/servletContextDemo3") ( |
2.6 案例 文件下载
2.61 需求
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件下载
2.62 分析:
超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
任何资源都必须弹出下载提示框
使用响应头设置资源的打开方式:
1
content-disposition:attachment;filename=xxx
2.63 步骤
定义页面,编辑超链接
href
属性,指向Servlet
,传递资源名称filenam
定义
Servlet
- 获取文件名称
- 使用字节输入流加载文件进内存
- 指定response的响应头: content-disposition:attachment;filename=xxx
- 将数据写出到response输出流
示例代码:
1 | package com.uestc.web.download; |
2.63 中文乱码问题
解决思路:
获取客户端使用的浏览器版本信息
根据不同的版本信息,设置filename的编码方式不同
步骤:
新建utils工具类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.uestc.web.utils;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}解决乱码问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54package com.uestc.web.download;
import com.uestc.web.utils.DownLoadUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
"/downloadServlet") (
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求参数,文件名称
String filename=req.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1 找到文件服务器路径
ServletContext context=this.getServletContext();
String realpath=context.getRealPath("/img/"+filename);
//2.2 用字节流关联
FileInputStream fis=new FileInputStream(realpath);
//3.设置response的响应头
//3.1设置相应头类型:contend-type
//获取文件的mimeType
String minType=context.getMimeType(filename);
resp.setHeader("content-type",minType);
//解决中文文件名问题
//1.获取user-agent请求头
String agent=req.getHeader("user-agent");
//2.使用工具类方法编码文件名即可
filename=DownLoadUtils.getFileName(agent,filename);
//3.2 设置相应头的打开方式:contend-disposition
resp.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream sos=resp.getOutputStream();
byte [] buff=new byte[1024*8];
int len=0;
while ((len=fis.read(buff))!=-1){
sos.write(buff,0,len);
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
3. 会话技术
3.1 概念
会话:一次会话中包含多次请求和响应。
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
3.2 功能:
在一次会话的范围内的多次请求间,共享数据
3.3 方式:
- 客户端会话技术:
Cookie
- 服务器端会话技术:
Session
3.31 Cookie:
3.311 概念:
客户端会话技术,将数据保存到客户端
3.312 快速入门
使用步骤:
创建
Cookie
对象,绑定数据1
new Cookie(String name, String value)
发送
Cookie
对象1
response.addCookie(Cookie cookie)
获取
Cookie
,拿到数据1
Cookie[] request.getCookies()
示例:
首先创建CookieDemo1
类
1 | "/cookieDemo1") ( |
然后创建CookieDemo2
类
1 | "/cookieDemo2") ( |
启动服务器,分别访问http://localhost:8080/servlet_cookie/cookieDemo
和http://localhost:8080/servlet_cookie/cookieDemo2
3.313 实现原理
基于响应头set-cookie和请求头cookie实现
3.314 cookie的细节
1. 一次可不可以发送多个cookie?
可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可
示例:
1 | "/cookieDemo1") ( |
2. cookie在浏览器中保存多长时间?
默认情况下,当浏览器关闭后,Cookie数据被销毁
持久化存储:
setMaxAge(int seconds)
正数
:将Cookie
数据写到硬盘的文件中, 持久化存储。并指定cookie
存活时间,时间到后,cookie
文件自动失效负数
:默认值零
:删除cookie
信息
示例:
1 | "/cookieDemo1") ( |
3. cookie能不能存中文?
在
tomcat 8
之前cookie
中不能直接存储中文数据。需要将中文数据转码—一般采用
URL
编码(%E3)在
tomcat 8
之后,cookie
支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
4. cookie共享问题?
假设在一个
tomcat
服务器中,部署了多个web项目,那么在这些web项目中cookie
能不能共享?默认情况下cookie不能共享
setPath(String path)
:设置cookie
的获取范围。默认情况下,设置当前的虚拟目录- 如果要共享,则可以将
path
设置为"/"
- 如果要共享,则可以将
不同的
tomcat
服务器间cookie
共享问题?setDomain(String path)
:如果设置一级域名相同,那么多个服务器之间cookie可以共享例如:
setDomain(".baidu.com")
那么
tieba.baidu.com
和news.baidu.com中cookie
可以共享
5. Cookie的特点和作用
- 特点
cookie
存储数据在客户端浏览器- 浏览器对于单个cookie 的大小有限制(
4kb
) 以及 对同一个域名下的总cookie
数量也有限制(20
个)
- 作用:
- cookie一般用于存出少量的不太敏感的数据
- 在不登录的情况下,完成服务器对客户端的身份识别
3.315 案例:记住上一次访问时间
3.3151 需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
3.3152 分析:
可以采用
Cookie
来完成在服务器中的
Servlet
判断是否有一个名为lastTime
的cookie
有:不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:2018年6月10日11:50:20
- 写回Cookie:lastTime=2018年6月10日11:50:01
没有:是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie:lastTime=2018年6月10日11:50:01
3.3153 代码实现
1 | "/cookieTest") ( |
启动服务器
3.32 Session
3.321 概念:
服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中:HttpSession
3.322 快速入门:
获取
HttpSession
对象:1
HttpSession session = request.getSession();
使用
HttpSession
对象:1
2
3Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)示例:
首先创建
SessionDemo1
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17"/sessionDemo1") (
public class SessionDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//使用sessiong共享数据
//1.获取session对象
HttpSession session=req.getSession();
//2.存储数据
session.setAttribute("msg","hello session");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}然后创建
SessionDemo2
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18"/sessionDemo2") (
public class SessionDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//使用sessiong获取数据
//1.获取session对象
HttpSession session=req.getSession();
//2.存储数据
Object msg=session.getAttribute("msg");
System.out.println(msg);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}分别访问
http://localhost:8080/servlet_session/sessionDemo1
和
http://localhost:8080/servlet_session/sessionDemo2
3.323 原理
Session的实现是依赖于Cookie的。
3.324 细节:
1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
默认情况下: 不是。
如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
1 | Cookie c = new Cookie("JSESSIONID",session.getId()); |
2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
session的钝化:
在服务器正常关闭之前,将session对象系列化到硬盘上
** session的活化:**
在服务器启动后,将session文件转化为内存中的session对象即可。
3. session什么时候被销毁?
服务器关闭
session对象调用
invalidate()
。session默认失效时间 30分钟
选择性配置修改
1
2
3 <session-config>
<session-timeout>30</session-timeout>
</session-config>
3.325 session的特点
session用于存储一次会话的多次请求的数据,存在服务器端
session可以存储任意类型,任意大小的数据
session与Cookie的区别:
- session存储数据在服务器端,Cookie在客户端
- session没有数据大小限制,Cookie有
- session数据安全,Cookie相对于不安全
3.2 案例:验证码
3.21 案例需求:
- 访问带有验证码的登录页面
login.jsp
- 用户输入用户名,密码以及验证码。
- 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登录页面,提示:验证码错误
- 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
3.22 代码实现
首先新建login.jsp
1 | <%-- |
创建success.jsp
1 | <%-- |
然后新建LoginServlet
类
1 | "/loginServlet") ( |
新建CheckCodeServlet
类
1 | "/checkCodeServlet") ( |
效果展示:
![image-20201103151228393](C:\Users\Liu Fei\AppData\Roaming\Typora\typora-user-images\image-20201103151228393.png)
4. JSP入门学习
4.1 概念:
Java Server Pages: java服务器端页面
可以理解为:一个特殊的页面,其中既可以指定定义
html
标签,又可以定义java
代码
用于简化书写!!!
4.2 原理
JSP本质上就是一个Servlet
4.3 JSP的脚本:
JSP定义Java代码的方式
1. `<% 代码 %>`:定义的`java`代码,在`service方法`中。service方法中可以定义什么,该脚本中就可以定义什么。
2. `<%! 代码 %>`:定义的`java`代码,在jsp转换后的java类的成员位置。
3. `<%= 代码 %>`:定义的`java`代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
4.4 JSP的内置对象:
在jsp页面中不需要获取和创建,可以直接使用的对象
jsp一共有9个内置对象。
今天学习3个:
request
response
out
:字符输出流对象。可以将数据输出到页面上。和response.getWriter()
类似response.getWriter()和out.write()的区别:
- 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
- response.getWriter()数据输出永远在out.write()之前
4.5 案例:改造Cookie案例
1 | <%@ page import="java.net.URLDecoder" %> |
4.6 指令
4.61 作用:
用于配置JSP页面,导入资源文件
4.62 格式:
1 | <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %> |
4.63 分类
4.631 page
配置JSP页面的
contentType
:等同于response.setContentType()
- 设置响应体的
mime
类型以及字符集 - 设置当前
jsp
页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding
属性设置当前页面的字符集)
- 设置响应体的
import
:导包errorPage
:当前页面发生异常后,会自动跳转到指定的错误页面isErrorPage
:标识当前也是是否是错误页面。true
:是,可以使用内置对象exceptionfalse
:否。默认值。不可以使用内置对象exception
1
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="500.jsp" %>
4.632 include
页面包含的。导入页面的资源文件
1 | <%"top.jsp"%> file= |
4.633 taglib
导入资源
1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> |
4.7 注释
html
注释:1
<!--只能注释html代码片段 -->
jsp
注释:推荐使用1
<%--可以注释所有 --%>
4.8 内置对象
在jsp页面中不需要创建,直接使用的对象
一共有9个:
变量名 真实类型 作用
pageContext
PageContext 当前页面共享数据,还可以获取其他八个内置对象request
HttpServletRequest 一次请求访问的多个资源(转发)session
HttpSession 一次会话的多个请求间application
ServletContext 所有用户间共享数据response
HttpServletResponse 响应对象page
Object 当前页面(Servlet)的对象 thisout
JspWriter 输出对象,数据输出到页面上config
ServletConfig Servlet的配置对象exception
Throwable 异常对象
5. MVC 开发模式
5.1 jsp演变历史
- 早期只有servlet,只能使用response输出标签数据,非常麻烦
- 后来又jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表,造成难于维护,难于分工协作
- 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性
5.2 MVC
M:
Model
,模型:JavaBean
- 完成具体的业务操作,如:查询数据库,封装对象
V:
View
,视图:JSP
- 展示数据
C:
Controller
,控制器:Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
优缺点:
1. 优点:
- 耦合性低,方便维护,可以利于分工协作
- 重用性高
2. 缺点:
1. 使得项目架构变得复杂,对开发人员要求高
6. EL表达式
6.1 概念
Expression Language 表达式语言
6.2 作用
替换和简化jsp页面中java代码的编写
6.3 语法:
1 | ${表达式} |
注意:
jsp默认支持el表达式的。如果要忽略el表达式
- 设置jsp中
page
指令中:isELIgnored="true"
忽略当前jsp页面中所有的el表达式 \${表达式}
:忽略当前
这个el表达式
6.4 使用:
6.41 运算
运算符:
算数运算符:
+ - * /(div) %(mod)
比较运算符:
> < >= <= == !=
逻辑运算符:
&&(and) ||(or) !(not)
空运算符:
empty
功能:用于判断字符串、集合、数组对象是否为
null
或者长度
是否为0
${empty list}:
判断字符串、集合、数组对象是否为null
或者长度
为0
${not empty str}
:表示判断字符串、集合、数组对象是否不为null
并且长度>0
示例:*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<%--
Created by IntelliJ IDEA.
User: Liu Fei
Date: 2020/11/3
Time: 16:19
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>算术运算符</h3>
${3+4}<br>
${3/4}<br>
${3 div 4}<br>
${3 % 4}<br>
${3 mod 4}<br>
<h3>比较运算符</h3>
${3==4}<br>
<h3>逻辑运算符</h3>
${3>4 && 3<4}<br>
${3>4 and 3<4}<br>
</body>
</html>效果展示:*
6.42 获取值
el表达式只能从域对象中获取值
6.421 语法
6.4211 ${域名称.键名}
从指定域中获取指定键的值
域名称:
pageScope –> pageContext
requestScope –> request
sessionScope –> session
applicationScope –> application(ServletContext)
示例:在request
域中存储了name=张三
,使用${requestScope.name}
进行获取
1 | <%-- |
6.4212 ${键名}
表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
示例:
1 | <%-- |
6.4213 获取对象、List集合、Map集合的值
1.对象:${域名称.键名.属性名}
本质上会去调用对象的getter
方法
示例:
创建JavaBean对象
1 | package com.uestc.domain; |
创建el.jsp
1 | <%-- |
效果展示:
2. List集合:${域名称.键名[索引]}
示例:
1 | <%-- |
显示效果:
3. Map集合:
${域名称.键名.key名称}
${域名称.键名["key名称"]}
1 | <%-- |
效果展示:
6.43 隐式对象
el表达式中有11个隐式对象
pageContext
:获取
jsp
其他八个内置对象1
${pageContext.request.contextPath}:动态获取虚拟目录JSTL
7. JSTL
7.1 概念
JavaServer Pages Tag Library JSP标准标签库
是由Apache组织提供的开源的免费的jsp标签 <标签>
7.2 作用
用于简化和替换jsp页面上的java代码
7.3 使用步骤
导入
jstl
相关jar
包引入标签库:
taglib
指令:<%@ taglib %>
使用标签
示例:
1.导入jstl
相关jar
引入标签库:
taglib
指令:<%@ taglib %>
1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
7.4 常用的JSTL标签
7.41 if
:
相当于java代码的
if
语句
属性:test
必须属性,接受boolean
表达式
- 如果表达式为
true
,则显示if
标签体内容,如果为false,则不显示标签体内容 - 一般情况下,
test
属性值会结合el表达式
一起使用
注意:
* c:if标签没有`else`情况,想要else情况,则可以在定义一个`c:if`标签
示例:
1 | <%@ page import="java.util.ArrayList" %> |
7.42 choose
:
相当于java代码的
switch
语句
使用choose标签声明 相当于switch声明
- 使用when标签做判断 相当于case
- 使用otherwise标签做其他情况的声明 相当于default
示例:
1 | <%-- |
7.43 foreach
相当于java代码的
for
语句
1.完成重复的操作
1 | for(int i=0;i<10;i++){} |
属性:
begin
:开始值end
:结束值var
:临时变量step
:步长varStatus
:循环状态对象index
:容器中元素的索引,从0
开始count
:循环次数,从1
开始
示例:
1 | <%-- |
效果展示:
遍历容器
1
2List<User> list;
for(User u:list){}示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %><%--
Created by IntelliJ IDEA.
User: Liu Fei
Date: 2020/11/3
Time: 23:52
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
List list=new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
request.setAttribute("list",list);
%>
<c:forEach items="${list}" var="i" varStatus="s">
${i} ${s.index} ${s.count}<br>
</c:forEach>
</body>
</html>效果展示:
需求:在request域中有一个存有User对象的List集合。需要使用jstl+el将list集合数据展示到jsp页面的表格table中
7.5 小练习
需求:在request域
中有一个存有User对象
的List集合。需要使用jstl+el
将list集合数据展示到jsp页面的表格table中\
- 新建
User
类
1 | package com.uestc.domain; |
- 新建
jstl_test.jsp
1 | <%@ page import="java.util.ArrayList" %> |
- 效果展示
8. 三层架构:软件设计架构
- 界面层(表示层):用户看的得界面。用户可以通过界面上的组件和服务器进行交互
- 业务逻辑层:处理业务逻辑的。
- 数据访问层:操作数据存储文件。
9. 案例:用户信息列表展示
9.1 需求
用户信息的增删改查操作
9.2 设计
9.21 技术选型:
Servlet+JSP+MySQL+JDBCTemplate+Duird+BeanUtils+tomcat
9.22 数据库设计
1 | create database day17; -- 创建数据库 |
9.3 开发
9.31 环境搭建
创建数据库环境
创建项目,导入需要的
jar
包将前端静态页面复制到web目录下
9.32 综合练习
简单功能
列表查询
登录
添加
删除
修改
复杂功能
删除选中
分页查询
好处:
- 减轻服务器内存的开销
- 提升用户体验
复杂条件查询
9.321 列表查询功能
项目目录:
新建
list.jsp
查询页面1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%"c" uri="http://java.sun.com/jsp/jstl/core" %> prefix=
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>用户信息管理系统</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style type="text/css">
td, th {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h3 style="text-align: center">用户信息列表</h3>
<div style="float: left;">
<form class="form-inline">
<div class="form-group">
<label for="exampleInputName2">姓名</label>
<input type="text" class="form-control" id="exampleInputName2" >
</div>
<div class="form-group">
<label for="exampleInputName3">籍贯</label>
<input type="text" class="form-control" id="exampleInputName3" >
</div>
<div class="form-group">
<label for="exampleInputEmail2">邮箱</label>
<input type="email" class="form-control" id="exampleInputEmail2" >
</div>
<button type="submit" class="btn btn-default">查询</button>
</form>
</div>
<div style="float: right;margin: 5px;">
<a class="btn btn-primary" href="add.html">添加联系人</a>
<a class="btn btn-primary" href="add.html">删除选中</a>
</div>
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th><input type="checkbox"></th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<c:forEach items="${users}" var="user" varStatus="s">
<tr>
<td><input type="checkbox"></td>
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td><a class="btn btn-default btn-sm" href="update.html">修改</a> <a class="btn btn-default btn-sm" href="">删除</a></td>
</tr>
</c:forEach>
</table>
<div>
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
<span style="font-size: 25px;margin-left: 5px;">
共16条记录,共4页
</span>
</ul>
</nav>
</div>
</div>
</body>
</html>新建
User
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64package com.uestc.dao;
public class User {
private int id;
private String name;
private String gender;
private int age;
private String address;
private String qq;
private String emil;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getQq() {
return qq;
}
public void setQq(String qq) {
this.qq = qq;
}
public String getEmil() {
return emil;
}
public void setEmil(String emil) {
this.emil = emil;
}
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", address='" + address + '\'' +
", qq='" + qq + '\'' +
", emil='" + emil + '\'' +
'}';
}
}新建
JDBCUtils
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package com.uestc.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* JDBC工具类 使用Durid连接池
*/
public class JDBCUtils {
private static DataSource ds ;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
//使用ClassLoader加载配置文件,获取字节输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接池对象
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 获取连接Connection对象
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
新建
UserDao
接口以及对应的实现类UserDaoImpl
1
2
3
4
5
6
7
8
9//UserDao
package com.uestc.dao;
import java.util.List;
/**
* 用户操作的DAO
*/
public interface UserDao {
public List<User> findAll();
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//UserDaoImpl
package com.uestc.dao.impl;
import com.uestc.dao.User;
import com.uestc.dao.UserDao;
import com.uestc.utils.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
public class UserDaoImpl implements UserDao {
private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDataSource());
public List<User> findAll() {
//使用JDBC完成查询
//1.定义sql
String sql="select * from user";
List<User> list= template.query(sql,new BeanPropertyRowMapper<User>(User.class));
return list;
}
}新建
UserService
接口以及对应的实现类UserServiceImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//UserService
package com.uestc.service;
import com.uestc.dao.User;
import java.util.List;
/**
* 用户管理的业务接口
*/
public interface UserService {
/**
* 查询所有用户信息
* @return
*/
public List<User> findAll();
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//UserServiceImpl
package com.uestc.service.impl;
import com.uestc.dao.User;
import com.uestc.dao.UserDao;
import com.uestc.dao.impl.UserDaoImpl;
import com.uestc.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService{
private UserDao dao=new UserDaoImpl();
public List<User> findAll() {
//调用dao完成查询
return dao.findAll();
}
}新建
UserListServlet
类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34package com.uestc.web.servlet;
import com.uestc.dao.User;
import com.uestc.service.UserService;
import com.uestc.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
"/userListServlet") (
public class UserListServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//调用UserService完成查询
UserService service=new UserServiceImpl();
List<User> users=service.findAll();
//将list存入request域
req.setAttribute("users",users);
//转发到jsp页面
req.getRequestDispatcher("/list.jsp").forward(req,resp);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
效果展示:
9.322 登录功能
建立登录界面
login.jsp
和 登录成功跳转界面index.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63//login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>管理员登录</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
function refreshCode() {
//1.获取验证码的图片对象
var vcode=document.getElementById("vcode");
//2.设置src属性,加时间戳
vcode.src="${pageContext.request.contextPath}/checkCodeServlet?time="+new Date().getTime();
}
</script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">管理员登录</h3>
<form action="${pageContext.request.contextPath}/loginServlet" method="post">
<div class="form-group">
<label for="user">用户名:</label>
<input type="text" name="username" class="form-control" id="user" placeholder="请输入用户名"/>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control" id="password" placeholder="请输入密码"/>
</div>
<div class="form-inline">
<label for="vcode">验证码:</label>
<input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码" style="width: 120px;"/>
<a href="javascript:refreshCode()">
<img src="${pageContext.request.contextPath}/checkCodeServlet" title="看不清点击刷新" id="vcode"/>
</a>
</div>
<hr/>
<div class="form-group" style="text-align: center;">
<input class="btn btn btn-primary" type="submit" value="登录">
</div>
</form>
<!-- 出错显示的信息框 -->
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" >
<span>×</span></button>
<strong>${requestScope.login_msg}</strong>
</div>
</div>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36//index.jsp
<%--
Created by IntelliJ IDEA.
User: Liu Fei
Date: 2020/11/5
Time: 10:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%"c" uri="http://java.sun.com/jsp/jstl/core" %> prefix=
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>首页</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
<div>${login_user.name},欢迎您 </div>
<div align="center">
<a>${requestScope.user}</a>
<a href="${pageContext.request.contextPath}/userListServlet" style="text-decoration:none;font-size:33px">查询所有用户信息</a>
</div>
</body>
</html>
新建
LoginServlet
和CheckCodeServlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56"/loginServlet") (
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("utf-8");
//2.获取数据
//2.1 获取用户填写的验证码
String verifycode=req.getParameter("verifycode");
Map<String,String[]> map=req.getParameterMap();
//3.验证码校验
HttpSession session=req.getSession();
String checkCode_session=(String)session.getAttribute("CHECKCODE_SERVER");
session.removeAttribute("CHECKCODE_SERVER");//确保验证码的一次性
if(verifycode.equalsIgnoreCase(checkCode_session)){
//验证码正确
//4.封装User对象
User user=new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//5.调用service查询
UserService service=new UserServiceImpl();
User loginUser=service.login(user);
if(loginUser==null){
//查找失败
//提示信息
req.setAttribute("login_msg","用户名或者密码错误");
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}else{
//登录成功
//将用户存入session
session.setAttribute("login_user",loginUser);
//跳转页面
resp.sendRedirect(req.getContextPath()+"/index.jsp");
}
//6.判断是否登录成功
}else{
//验证码不一致
//提示信息
req.setAttribute("login_msg","验证码错误");
//跳转登录页面
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82package com.uestc.web.servlet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 验证码
*/
"/checkCodeServlet") (
public class CheckCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//服务器通知浏览器不要缓存
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
//在内存中创建一个长80,宽30的图片,默认黑色背景
//参数一:长
//参数二:宽
//参数三:颜色
int width = 80;
int height = 30;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics g = image.getGraphics();
//设置画笔颜色为灰色
g.setColor(Color.GRAY);
//填充图片
g.fillRect(0,0, width,height);
//产生4个随机验证码,12Ey
String checkCode = getCheckCode();
//将验证码放入HttpSession中
request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
//设置画笔颜色为黄色
g.setColor(Color.YELLOW);
//设置字体的小大
g.setFont(new Font("黑体",Font.BOLD,24));
//向图片上写入验证码
g.drawString(checkCode,15,25);
//将内存中的图片输出到浏览器
//参数一:图片对象
//参数二:图片的格式,如PNG,JPG,GIF
//参数三:图片输出到哪里去
ImageIO.write(image,"PNG",response.getOutputStream());
}
/**
* 产生4位随机字符串
*/
private String getCheckCode() {
String base = "0123456789ABCDEFGabcdefg";
int size = base.length();
Random r = new Random();
StringBuffer sb = new StringBuffer();
for(int i=1;i<=4;i++){
//产生0到size-1的随机值
int index = r.nextInt(size);
//在base字符串中获取下标为index的字符
char c = base.charAt(index);
//将c放入到StringBuffer中去
sb.append(c);
}
return sb.toString();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}效果展示:
9.323 添加功能
创建
add.jsp
创建添加联系人页面1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- HTML5文档-->
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>添加用户</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<center><h3>添加联系人页面</h3></center>
<form action="${pageContext.request.contextPath}/addUserServlet" method="post">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
</div>
<div class="form-group">
<label>性别:</label>
<input type="radio" name="gender" value="男" checked="checked"/>男
<input type="radio" name="gender" value="女"/>女
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
</div>
<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" class="form-control" id="jiguan">
<option value="广东">广东</option>
<option value="广西">广西</option>
<option value="湖南">湖南</option>
</select>
</div>
<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" class="form-control" name="qq" placeholder="请输入QQ号码"/>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="text" class="form-control" name="email" placeholder="请输入邮箱地址"/>
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交" />
<input class="btn btn-default" type="reset" value="重置" />
<input class="btn btn-default" type="button" value="返回" />
</div>
</form>
</div>
</body>
</html>并修改
list.jsp
中添加联系人按钮的超链接使其指向add.jsp
页面![image-20201109172004690](C:\Users\Liu Fei\AppData\Roaming\Typora\typora-user-images\image-20201109172004690.png)
新建
AddUserServlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34"/addUserServlet") (
public class AddUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("utf-8");
//2.获取参数
Map<String,String[]> map=req.getParameterMap();
//3.封装对象
User user=new User();
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//4.调用service保存
UserService service=new UserServiceImpl();
service.addUser(user);
//5.跳转到UserListServlet
resp.sendRedirect(req.getContextPath()+"/userListServlet");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}在
Service
和UserDao
中添加add()
方法Service
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26//UserService
/**
* 用户管理的业务接口
*/
public interface UserService {
/**
* 查询所有用户信息
* @return
*/
public List<User> findAll();
/**
* 登录方法
* @param loginUser
* @return
*/
public User login(User loginUser);
/**
* 保存User
* @param user
*/
public void addUser(User user);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19//UserServiceImpl
public class UserServiceImpl implements UserService{
private UserDao dao=new UserDaoImpl();
public List<User> findAll() {
//调用dao完成查询
return dao.findAll();
}
public void addUser(User user) {
dao.add(user);
}
public User login(User loginUser) {
return dao.findUserByUsernameAndPassWord(loginUser.getUsername(),loginUser.getPassword());
}
}Dao:
1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.uestc.dao;
import java.util.List;
/**
* 用户操作的DAO
*/
public interface UserDao {
public List<User> findAll();
public User findUserByUsernameAndPassWord(String userName, String password);
public void add(User user);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.uestc.dao.impl;
public class UserDaoImpl implements UserDao {
private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDataSource());
public List<User> findAll() {
//使用JDBC完成查询
//1.定义sql
String sql="select * from user";
List<User> list= template.query(sql,new BeanPropertyRowMapper<User>(User.class));
return list;
}
public User findUserByUsernameAndPassWord(String username, String password) {
try{
String sql="select * from user where username=? and password = ?";
User user=template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class),username,password);
return user;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
public void add(User user) {
//定义sql
String sql="insert into user value(null,?,?,?,?,?,?,null,null)";
//执行sql
template.update(sql,user.getName(),user.getGender(),user.getAge(),user.getAddress(),user.getQq(),user.getEmail());
}
}效果展示
9.324 删除功能
修改
list.jsp
中删除
选项使其指向deleteUserServlet
,并将需要删除的id传入参数中创建
DeleteUserServlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23"/deleteUserServlet") (
public class DeleteUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("utf-8");
//2.获取参数id
String id=req.getParameter("id");
//3.调用service删除
UserService serive=new UserServiceImpl();
serive.deleteUser(id);
//4.跳转查询所有的servlet
resp.sendRedirect(req.getContextPath()+"/userListServlet");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}在
Service
和UserDao
中添加delete()
方法Service
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29package com.uestc.service;
/**
* 用户管理的业务接口
*/
public interface UserService {
/**
* 查询所有用户信息
* @return
*/
public List<User> findAll();
/**
* 登录方法
* @param loginUser
* @return
*/
public User login(User loginUser);
/**
* 保存User
* @param user
*/
public void addUser(User user);
/**
* 删除user
* @param id
*/
public void deleteUser(String id);
}
1 | package com.uestc.service.impl; |
DAO:
1 | package com.uestc.dao; |
1 | package com.uestc.dao.impl; |
效果展示:
问题:为了防止误删,需要添加提醒
1 | <!--list.jsp--> |
9.325 修改功能
修改
list.jsp
中修改
使其指向findUserServlet
新建
FindUserServlet
目的:是先根据
id
获取user
,然后再update.jsp
中回显
原有的user信息1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.uestc.web.servlet;
"/findUserServlet") (
public class FindUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
UserService service=new UserServiceImpl();
//1.获取id
String id=req.getParameter("id");
//2.根据id查找user
User user=service.findUserById(id);
//3.将user信息存入request域中
req.setAttribute("user",user);
//3.跳转update.jsp
req.getRequestDispatcher("/update.jsp").forward(req,resp);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}新建
update.jsp
注意:
在
FindUserServlet
中已经将查到的User中的信息保存在request域
中, 我们只需要通过el
和jstl
表达式获取将
action
指向UpdateServlet
创建隐藏域,传递
id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>修改用户</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/jquery-2.1.0.min.js"></script>
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">修改联系人</h3>
<form action="${pageContext.request.contextPath}/updateServlet" method="post">
<!--隐藏域提交id-->
<input type="hidden" name="id" value="${user.id}">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" value="${user.name}" readonly="readonly" />
</div>
<div class="form-group">
<label>性别:</label>
<c:if test="${user.gender=='男'}">
<input type="radio" name="gender" value="男" checked />男
<input type="radio" name="gender" value="女" />女
</c:if>
<c:if test="${user.gender=='女'}">
<input type="radio" name="gender" value="男" />男
<input type="radio" name="gender" value="女" checked />女
</c:if>
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="text" class="form-control" id="age" name="age" value="${user.age}" />
</div>
<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" class="form-control" >
<c:if test="${user.address=='安徽'}">
<option value="安徽" selected>安徽</option>
<option value="广西">广西</option>
<option value="湖南">湖南</option>
</c:if>
<c:if test="${user.address=='广东'}">
<option value="安徽" >安徽</option>
<option value="广东" selected>广东</option>
<option value="湖南">湖南</option>
</c:if>
<c:if test="${user.address=='湖南'}">
<option value="安徽" >安徽</option>
<option value="广东">广东</option>
<option value="湖南" selected>湖南</option>
</c:if>
</select>
</div>
<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" class="form-control" name="qq" value="${user.qq}"/>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="text" class="form-control" name="email" value="${user.email}" />
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交" />
<input class="btn btn-default" type="reset" value="重置" />
<input class="btn btn-default" type="button" value="返回"/>
</div>
</form>
</div>
</body>
</html>新建
UpdateServlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44package com.uestc.web.servlet;
import com.uestc.dao.User;
import com.uestc.service.UserService;
import com.uestc.service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
"/updateServlet") (
public class UpdateServlet extends HttpServlet{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("utf-8");
//2.获取表单参数
Map<String,String[]> map=req.getParameterMap();
System.out.println(map.get("id"));
//3.封装user对象
User user=new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//4.调用service的update方法;
UserService service=new UserServiceImpl();
service.updateUser(user);
//5.跳转到查询所有
resp.sendRedirect(req.getContextPath()+"/userListServlet");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}在
Userservice
及其实现类UserserviceImpl
中添加update
方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45package com.uestc.service;
import com.uestc.dao.User;
import java.util.List;
/**
* 用户管理的业务接口
*/
public interface UserService {
/**
* 查询所有用户信息
* @return
*/
public List<User> findAll();
/**
* 登录方法
* @param loginUser
* @return
*/
public User login(User loginUser);
/**
* 保存User
* @param user
*/
public void addUser(User user);
/**
* 删除User
* @param id
*/
public void deleteUser(String id);
/**
* 根据id查找用户
* @param id
* @return
*/
public User findUserById(String id);
/**
* 更新User
* @param user
*/
public void updateUser(User user);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39package com.uestc.service.impl;
import com.uestc.dao.User;
import com.uestc.dao.UserDao;
import com.uestc.dao.impl.UserDaoImpl;
import com.uestc.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService{
private UserDao dao=new UserDaoImpl();
public List<User> findAll() {
//调用dao完成查询
return dao.findAll();
}
public void addUser(User user) {
dao.add(user);
}
public void deleteUser(String id) {
dao.delete(Integer.valueOf(id));
}
public User findUserById(String id) {
return dao.findUserById(Integer.valueOf(id));
}
public void updateUser(User user) {
dao.update(user);
}
public User login(User loginUser) {
return dao.findUserByUsernameAndPassWord(loginUser.getUsername(),loginUser.getPassword());
}
}
在
UserDao
及其实现类UserDaoImpl
中添加update
方法1
2
3
4
5
6
7
8
9
10
11
12
13package com.uestc.dao;
import java.util.List;
/**
* 用户操作的DAO
*/
public interface UserDao {
public List<User> findAll();
public User findUserByUsernameAndPassWord(String userName, String password);
public void add(User user);
public void delete(int id);
public User findUserById(int id);
public void update(User user);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57package com.uestc.dao.impl;
public class UserDaoImpl implements UserDao {
private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDataSource());
public List<User> findAll() {
//使用JDBC完成查询
//1.定义sql
String sql="select * from user";
List<User> list= template.query(sql,new BeanPropertyRowMapper<User>(User.class));
return list;
}
public User findUserByUsernameAndPassWord(String username, String password) {
try{
String sql="select * from user where username=? and password = ?";
User user=template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class),username,password);
return user;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
public void add(User user) {
//定义sql
String sql="insert into user value(null,?,?,?,?,?,?,null,null)";
//执行sql
template.update(sql,user.getName(),user.getGender(),user.getAge(),user.getAddress(),user.getQq(),user.getEmail());
}
public void delete(int id) {
//定义sql
String sql="delete from user where id=?";
//执行sql
template.update(sql,id);
}
public void update(User user) {
String sql = "update user set name = ?,gender = ? ,age = ? , address = ? , qq = ?, email = ? where id = ?";
template.update(sql, user.getName(), user.getGender(), user.getAge(), user.getAddress(), user.getQq(), user.getEmail(), user.getId());
}
public User findUserById(int id) {
//定义sql
String sql="select * from user where id=?";
//执行sql
try {
User user=template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),id);
return user;
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
}
效果展示*:
9.326 删除选中功能
完成
全选功能
首先需要用
form
包裹table
,并为每个选中按钮添加id
然后通过
javascript
来给删除选中按钮
绑定单击事件![image-20201112100143949](C:\Users\Liu Fei\AppData\Roaming\Typora\typora-user-images\image-20201112100143949.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%"c" uri="http://java.sun.com/jsp/jstl/core" %> prefix=
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>用户信息管理系统</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style type="text/css">
td, th {
text-align: center;
}
</style>
<script>
function deleteUser(id) {
//用户安全提示
if(confirm("您确定删除么?")){
//访问路径
location.href="${pageContext.request.contextPath}/deleteUserServlet?id="+id;
}
}
window.onload=function() {
//给删除选中按钮添加单击事件
document.getElementById("delSelected").onclick=function(){
//表单提交
document.getElementById("form").submit();
}
//全选功能
//获取第一个cb
document.getElementById("firstCb").onclick= function(){
//获取下面列表中所有的cb
var cbs= document.getElementsByName("uid");
//遍历
for(var i=0;i< cbs.length;i++){
//4.设置这些cbs[i]的状态=firstCb.checked
//cbs[i].checked=this.checked;
cbs[i].checked = this.checked;
}
}
}
</script>
</head>
<body>
<div class="container">
<h3 style="text-align: center">用户信息列表</h3>
<div style="float: left;">
<form class="form-inline">
<div class="form-group">
<label for="exampleInputName2">姓名</label>
<input type="text" class="form-control" id="exampleInputName2" >
</div>
<div class="form-group">
<label for="exampleInputName3">籍贯</label>
<input type="text" class="form-control" id="exampleInputName3" >
</div>
<div class="form-group">
<label for="exampleInputEmail2">邮箱</label>
<input type="email" class="form-control" id="exampleInputEmail2" >
</div>
<button type="submit" class="btn btn-default">查询</button>
</form>
</div>
<div style="float: right;margin: 5px;">
<a class="btn btn-primary" href="${pageContext.request.contextPath}/add.jsp">添加联系人</a>
<a class="btn btn-primary" href="javascript:void(0);" id="delSelected">删除选中</a>
</div>
<form id="form" action="${pageContext.request.contextPath}/delSelectServlet" method="post">
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th><input type="checkbox" id="firstCb"></th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<c:forEach items="${users}" var="user" varStatus="s">
<tr>
<td><input type="checkbox" name="uid" value="${user.id}"></td>
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td><a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>
<a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id})">删除</a></td>
</tr>
</c:forEach>
</table>
</form>
<div>
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
<span style="font-size: 25px;margin-left: 5px;">
共16条记录,共4页
</span>
</ul>
</nav>
</div>
</div>
</body>
</html>
完成
删除选中
功能,新建delSelectServlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.uestc.web.servlet;
"/delSelectServlet") (
public class DelSelectServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取所有id
String [] ids=request.getParameterValues("uid");
//2.调用service删除
UserService service=new UserServiceImpl();
service.delSelectedUser(ids);
//3.跳转到查询所有的servlet
response.sendRedirect(request.getContextPath()+"/userListServlet");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}在
Userservice
及其实现类UserserviceImpl
中添加delSelectedUser
方法1
2
3
4package com.uestc.service;
import com.uestc.dao.User;
import java.util.List;
/**- 用户管理的业务接口
- /
public interface UserService {
/**
查询所有用户信息
- @return
*/
public ListfindAll();
/**
- @return
登录方法
- @param loginUser
- @return
- /
public User login(User loginUser);
/**
- 保存User
- @param user
- /
public void addUser(User user);
/**
- 删除User
- @param id
- /
public void deleteUser(String id);
/**
- 根据id查找用户
- @param id
- @return
- /
public User findUserById(String id);
/**
- 更新User
- @param user
- /
public void updateUser(User user);
/**
- 批量删除
- @param ids
- /
public void delSelectedUser(String []ids);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
```java
package com.uestc.service.impl;
import com.uestc.dao.User;
import com.uestc.dao.UserDao;
import com.uestc.dao.impl.UserDaoImpl;
import com.uestc.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService{
private UserDao dao=new UserDaoImpl();
@Override
public List<User> findAll() {
//调用dao完成查询
return dao.findAll();
}
@Override
public void addUser(User user) {
dao.add(user);
}
@Override
public void deleteUser(String id) {
dao.delete(Integer.valueOf(id));
}
@Override
public User findUserById(String id) {
return dao.findUserById(Integer.valueOf(id));
}
@Override
public void updateUser(User user) {
dao.update(user);
}
@Override
public void delSelectedUser(String [] ids) {
//1.遍历
for(String id :ids){
dao.delete(Integer.valueOf(id));
}
}
@Override
public User login(User loginUser) {
return dao.findUserByUsernameAndPassWord(loginUser.getUsername(),loginUser.getPassword());
}
}
效果展示:
删除部分选中:
![](https://cdn.jsdelivr.net/gh/feiLiuTech/imgbed@main/GitLearning/20201112102111.png)
删除全选
![](https://cdn.jsdelivr.net/gh/feiLiuTech/imgbed@main/GitLearning/20201112102353.png)
优化:
问题:没有选中任何复选框,点击删除选中会出现空指针异常
,并且需要删除提示
解决:
1 | <script> |
效果展示: 此时不会出现空指针异常
9.327 分页查询
10. Filter:过滤器
10.1 概念
生活中的过滤器:净水器, 空气净化器,土匪、
web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
过滤器的作用:一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…
10.2 快速入门:
10.3 步骤:
- 定义一个类,实现接口
Filter
- 复写方法
- 配置拦截路径
web.xml
- 注解
示例:
1 | package com.uestc.web.filter; |
10.3 过滤器细节:
10.31 web.xml配置
1 |
|
10.32 过滤器执行流程
执行过滤器
执行放行后的资源
回来执行过滤器放行代码下边的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.uestc.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
"/*")//访问所有资源之前,都会执行该过滤器 (
public class FilterDemo2 implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//对request对象请求消息增强
System.out.println("filterDemo2被执行了。。。");
//放行
filterChain.doFilter(servletRequest,servletResponse);
//对response对象的响应消息增强
System.out.println("filterDemo2回来了。。。");
}
public void destroy() {
}
}
10.33 过滤器生命周期方法
init
:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源doFilter
:每一次请求被拦截资源时,会执行。执行多次destroy
:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
10.4 过滤器配置详解
10.41 拦截路径配置:
- 具体资源路径:
/index.jsp
只有访问index.jsp
资源时,过滤器才会被执行 - 拦截目录:
/user/*
访问/user
下的所有资源时,过滤器都会被执行 - 后缀名拦截:
*.jsp
访问所有后缀名为jsp
资源时,过滤器都会被执行 - 拦截所有资源:
/*
访问所有资源时,过滤器都会被执行
10.42 拦截方式配置:
资源被访问的方式
注解配置:
设置dispatcherTypes
属性
REQUEST
:默认值。浏览器直接请求资源FORWARD
:转发访问资源INCLUDE
:包含访问资源ERROR
:错误跳转资源ASYNC
:异步访问资源
示例演示:
新建过滤器
FilterDemo3
并设置dispatcherTypes
属性为REQUEST
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.uestc.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//浏览器直接请求index.jsp资源是,该该过滤器会被执行
"/index.jsp", dispatcherTypes = DispatcherType.REQUEST) ( value=
public class FilterDemo3 implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo3执行了。。。");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
新建
ServletDemo1
并对index.jsp
进行转发1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.uestc.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
"/user/servletDemo1") (
public class ServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}效果展示:
- 当直接访问
index.jsp
的时候,过滤器被执行了
当访问
/user/servletDemo1
时候,过滤器没有执行
- 当直接访问
同理可得:当设置dispatcherTypes
属性为FORWARD
的时候
当直接访问
index.jsp
的时候,过滤器不会执行当访问
/user/servletDemo1
时候,过滤器执行如果想要同时index.jsp和转发资源的时候过滤器都执行,那么我们只需要
dispatcherTypes
设置成数组形式1
"/index.jsp", dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.`FORWARD`}) ( value=
web.xml配置
设置<dispatcher></dispatcher>
标签即可
10.5 滤器链(配置多个过滤器)
10.51 执行顺序:
如果有两个过滤器:过滤器1和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
10.52 过滤器先后顺序问题:
注解配置:按照类名的字符串比较规则比较,值小的先执行
如: AFilter 和 BFilter,AFilter就先执行了。
web.xml配置:
<filter-mapping>
谁定义在上边,谁先执行
10.6 案例:
案例1_登录验证
需求
- 访问day17_case案例的资源。验证其是否登录
- 如果登录了,则直接放行。
- 如果没有登录,则跳转到登录页面,提示”您尚未登录,请先登录”。
分析
代码实现:
新建LoginFilter
1 | package com.uestc.web.filter; |
案例2_敏感词汇过滤
需求:
1. 对day17_case案例录入的数据进行敏感词汇过滤
2. 敏感词汇参考《敏感词汇.txt》
3. 如果是敏感词汇,替换为 ***
分析:
1. 对`request`对象进行**增强**。增强获取参数相关方法
2. 放行。传递代理对象
增强对象的功能:
设计模式:一些通用的解决固定问题的方式
- 装饰模式
- 代理模式
代码实现:
创建过滤器
SensitiveWordFilter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49package com.uestc.web.filter;
"/*") (
public class SensitiveWordFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1.创建代理对象,增强getParameter方法
ServletRequest proxy_req=(ServletRequest)Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强getParameter方法
//判断是否是getParameter方法
if(method.getName().equals("getParameter")){
//增强返回值
String value=(String)method.invoke(req, args);
if(value!=null){
for(String str:list){
if(value.contains(str)){
value=value.replace(str,"***");
}
}
}
return value;
}
return method.invoke(req, args);
}
});
chain.doFilter(proxy_req, resp);
}
private List<String> list=new ArrayList<String>();//敏感词汇list集合
public void init(FilterConfig config) throws ServletException {
try {
//1.获取文件的真实路径
ServletContext context=config.getServletContext();
String realpath=context.getRealPath("/WEB-INF/classes/敏感词汇.txt");
//2.读取文件
BufferedReader br=new BufferedReader(new FileReader(realpath));
//3.将文件的每一行数据添加到list
String line=null;
while((line=br.readLine())!=null){
list.add(line);
}
br.close();
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
}创建测试
Testservlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.uestc.web.servlet;
"/testServlet") (
public class TestServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name=req.getParameter("name");
String msg=req.getParameter("msg");
System.out.println(name+msg);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}效果展示:
![image-20201113150837968](C:\Users\Liu Fei\AppData\Roaming\Typora\typora-user-images\image-20201113150837968.png)