文章目录
servlet 分为两部分, 前半部分
1. ServletConfig对象
1.1 简介
- 作用:通过此对象可以读取web.xml中配置的初始化参数。
- Servlet 程序 和 ServletConfig 对象是由 Tomcat 负责创建的。Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个Servlet 程序创建时,就会创建一个ServletConfig对象。
1.2 操作演示:
- 为demo这个Servlet 配置一个参数,参数名为username,值为zouxiaopang。
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>demo</servlet-class>
<!-- 初始化参数名 -->
<init-param>
<!-- 参数名 -->
<param-name>username</param-name>
<!-- 参数值 -->
<param-value>zouxiaopang</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>
- 在
demo.java
文件中 获取 ServletConfig对象,通过 ServletConfig 对象获取在web.xml文件配置的参数。
// 获取ServletConfig对象
ServletConfig servletConfig = this.getServletConfig();
// 根据配置的名字获取值
String value = servletConfig.getInitParameter("username");
// 获取servlet别名
System.out.println(servletConfig.getServletName());
System.out.println(value);
2. ServletContext对象
2.1 定义与作用
定义:
- ServletContext是一个接口,它表示Servlet上下文对象。
- 一个web工程,只有一个ServletContext对象实例。
- ServletContext对象是一个域对象。
- ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁。
作用:
- ServletContext既然代表着当前web站点,那么所有Servlet都共享着一个ServletContext对象,所以Servlet之间可以通过ServletContext实现通讯。
- ServletConfig获取的是配置的是单个Servlet的参数信息,ServletContext可以获取的是配置整个web站点的参数信息
- 利用ServletContext 读取web站点的资源文件
- 实现Servlet的转发(用ServletContext转发不多,主要用request转发)
域对象
- 域对象,是可以像 Map 一样存取数据的对象。 这里的域指的是存取数据的操作范围,整个 web 工程。
Map | 域对象 | |
---|---|---|
存 | put | setAttribute() |
取 | get() | getAttribute() |
删除 | remove() | removeAttribute() |
2.2 操作演示:
- 修改
demo.java
中代码
public class demo extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
String value = "zouxiaopang";
//MyName作为关键字,value作为值存进 域对象【类型于Map集合】
servletContext.setAttribute("MyName",value);
System.out.println("我是demo!");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
- 创建
demo2.java
public class demo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
//通过关键字获取存储在域对象的值
String value = (String) servletContext.getAttribute("MyName");
System.out.println("我是demo1=2:"+ value);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
- 如果直接访问
demo2
,会获取不到MyName关键字的值,值为null。
- 需要先访问
demo
,在访问demo2
,才能获取到MyName关键字的值。
2.3 获取web站点配置的信息
- web.xml文件支持对整个站点进行配置参数信息(所有Servlet都可以取到该参数信息)。
- 在
web.xml
文件中配置参数信息
<context-param>
<param-name>MyName</param-name>
<param-value>zouxiaopang</param-value>
</context-param>
- 在
demo.java
中通过名称获取值
public class demo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
//通过名称获取值
String value = servletContext.getInitParameter("MyName");
System.out.println("我是demo2:"+ value);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
3. 同理,对该站点的所有Servlet都可以获得到MyName
的值。
2.4 读取资源文件
- 资源文件放在web目录下,直接通过文件名就能获取。
InputStream in = this.getServletContext().getResourceAsStream(
"/db.properties");
- 资源文件在src下,那么在web服务器中的位置是
WEB-INF/classes
下
InputStream in = this.getServletContext().getResourceAsStream(
"/WEB-INF/classes/db.properties");
- 资源在包中,那么在web服务器中的位置是
WEB-INF/classes/package
下
InputStream in = this.getServletContext().getResourceAsStream(
"/WEB-INF/classes/test/db.properties");
- 编写
db.properties
文件
username=zouxiaopang;
password=123456;
- 修改
demo.java
文件中代码
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
//通过类装载器获取到读取文件流
InputStream inputStream = servletContext.getResourceAsStream("/db.properties");
read(inputStream);
}
private void read(InputStream in) throws IOException {
Properties prop = new Properties();
prop.load(in);
String username = prop.getProperty("username");
String password = prop.getProperty("password");
System.out.println(username);
System.out.println(password);
}
- 访问demo页面
3. HttpServletResponse
http响应由状态⾏、实体内容、消息头、⼀个空⾏组成。HttpServletResponse对象就封装了http响应的信息。
注:如果需要设置返回给用户端的信息,可以通过HttpServletResponse对象来进行设置。
3.1 向浏览器输出数据
- 输出流(两个流只能使用一个)
字节流 | getOutputStream(); | 常用于下载(传递二进制数据) |
---|---|---|
字符流 | getWriter(); | 常用于回传字符串 |
调⽤getOutputStream()
⽅法向浏览器输出数据,可以使⽤print()
也可以使⽤write()
//获取到PrintWriter对象
PrintWriter printWriter = response.getWriter();
printWriter.write("邹小胖向前冲!");
//获取到OutputStream流
ServletOutputStream servletOutputStream = response.getOutputStream();
//向浏览器输出数据
servletOutputStream.write(("邹小胖向前冲!").getBytes());
servletOutputStream.write(("邹小胖向前冲!").getBytes("UTF-8"));
getBytes()
可以正常输出中文:代码在转成byte[]数组的时候默认查的是gb2312编码,⽽"邹小胖向前冲!"⽀持gb2312编码,所以可以正常显示出来。getBytes("UTF-8");
会出现乱码,但是程序要实现连通性,应该使用UTF-8编码。
避免乱码
- 方案一(不推荐):
// 设置服务器字符集为UTF-8
response.setCharacterEncoding("UTF-8");
// 通过响应头,设置浏览器也使用UTF-8字符集
response.setHeader("Content-Type","text/html;charset=UTF-8");
- 方案二(推荐):
//同时设置服务端和客户端都使用UTF-8字符集,还设置了响应头
//此方法必须在获取对象之前调用才有用
response.setContentType("text/html;charset=UTF-8");
3.2 实现文件下载
现在想要下载本工程下,web目录里的1.jpg,代码如下:
//获取到资源的路径
String path = this.getServletContext().getRealPath("/1.jpg");
//读取资源
FileInputStream fileInputStream = new FileInputStream(path);
//获取到文件名,路径在电脑上保存是\\形式的。
//attachment:提示用户保存
String fileName = path.substring(path.lastIndexOf("\\") + 1);
//设置消息头,告诉浏览器,我要下载1.jpg这个图⽚
response.setHeader("Content-Disposition","attachment;filename="+fileName);
// 将读取的资源传给浏览器
int len = 0;
byte[] bytes = new byte[1024];
ServletOutputStream servletOutputStream = response.getOutputStream();
while((len = fileInputStream.read(bytes)) > 0 ) {
servletOutputStream.write(bytes,0,len);
}
//关闭资源
servletOutputStream.close();
fileInputStream.close();
- path.lastIndexOf("\") + 1 解释:
如果取一个文件名 D:\img\abc.jpg,如果要得到abc.jpg,如果不加一,就会得到包括\本身,成了\abc.jpg。 - 文件名为中文,会造成乱码,解决方法:
response.setHeader("Content-Disposition", "attachment; filename=" +URLEncoder.encode(fileName, "UTF-8"));
3.3 实现自动刷新
以规定的时间让⻚⾯刷新,更新资源。
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("3秒后自动跳转至index界面.....");
//三秒后跳转到index.jsp页面,3秒自动刷新
response.setHeader("Refresh","3;url=/index.jsp");
3.4 生出随机图片
在我们登陆的时候经常要写验证码,⽽那些验证码是⼀张图⽚,就是通过HttpServletResponse写给浏览器的。
- java提供了
BufferedImage类
,生成一张图片
//在内存中⽣成⼀张图⽚,宽为80,⾼为20,类型是RGB
BufferedImage bufferedImage = new BufferedImage(80, 20,BufferedImage.TYPE_INT_RGB);
//获取到这张图⽚
Graphics graphics = bufferedImage.getGraphics();
//填充整张图⽚
graphics.fillRect(0, 0, 80, 20);
//往图⽚设置颜⾊和字体
graphics.setColor(Color.blue);
graphics.setFont(new Font(null, Font.BOLD, 20));
//往图⽚上写数据,先写个12345,横坐标是0,纵坐标是20【⾼度】
String str = makeNum();
graphics.drawString(str, 0, 20);
//要往浏览器写⼀张图⽚,那要告诉浏览器回送的类型是⼀张图⽚
response.setHeader("ContentType", "jpeg");
//java提供了图⽚流给我们使⽤,这是⼀个⼯具类
//把图⽚传进去,类型是jpg,写给浏览器
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
- 生成随机数
private String makeNum() {
Random random = new Random();
//这样就会⽣成0-7位的随机数,现在问题⼜来了,如果随机数不够7位呢?如果不够7位,我们加到7位
int anInt = random.nextInt(9999999);
//将数字转成是字符串
String num = String.valueOf(anInt);
//判断位数有多少个,不够就加
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 7 - num.length(); i++) {
stringBuffer.append("0");
}
return stringBuffer.append(num).toString();
}
3.5 重定向跳转
点击⼀个超链接,通知浏览器跳转到另外的⼀个页面就叫重定向跳转。⻚⾯之间的跳转有两种⽅式:重定向和转发。
- 在
output.java
文件中,编写代码,在页面中输入http://localhost:8080/output
会重定向到http://localhost:8080/form.jsp
中。
response.sendRedirect("/form.jsp");
-
通过观察
http协议
,看到两个状态码,分别是302、200。302状态码在http协议中代表的是临时重定向。
-
举个例⼦:我找纪律委员说:给我⼀份请假表,我要回家。纪律委员告诉我:我这⾥没有请假表,你去找辅导员吧。
-
重定向是通过302状态码和跳转地址实现的。于是可以通过设置http消息头就可以实现重定向跳转。
//设置状态码为302
response.setStatus(302);
//HttpServletResponse把常⽤的状态码封装成静态常量了,所以我们可以使⽤SC_MOVED_TEMPORARILY代表着302
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
response.setHeader("Location","/form.jsp");
4. HttpServletRequest
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。
常用方法:
方法 | 作用 |
---|---|
getRequestURI() | 获取请求的资源路径 |
getRequestURL() | 获取请求的统一资源定位符(绝对路径) |
getRemoteHost() | 获取客户端的ip地址 |
getHeader() | 获取请求头 |
getParameter() | 获取请求的参数 |
getParameterValues() | 获取请求的参数(多个值的时候使用) |
getMethod() | 获取请求的方式GET或POST |
setAttribute(key,value); | 设置域数据 |
getAttribute(key); | 获取域数据 |
getRequestDispatcher() | 获取请求转发对象 |
4.1 防盗链
我现在有某电视剧的最新资源,想要看电视剧的人需要在我的网页上看。现在别的网站的人看到我的资源,想要把我的资源粘贴在他自己的网站上。这样我独家的资源就被一个CTRL+C和CTRL+V抢走了,而反盗链就是为防止他们CRTL+C 和 CRTL+V。
- 创建
mmm.jsp
文件,为进入电视剧最新资源的跳板(必须经过此页面,才可以访问最新资源)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>点击下面链接,进入</h3>
<a href="http://localhost:8080/movie.jsp">青春有你3最新资源</a>
</body>
</html>
- 编写
movie.java
程序
注:`sendRedirect语句后面必须加return;
public class movie extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取到网页是从哪里来的
String referer = request.getHeader("Referer");
//如果不是从我的首页来或者从地址栏直接访问的,
if(referer == null||!referer.contains("localhost:8080/mmm.jsp")){
//回到必经页面mmm.jsp
response.sendRedirect("http://localhost:8080/mmm.jsp");
return;
}
else{
//能执行下面的语句,说明是从mmm.jsp点击进来的,那没问题,照常显示
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("余景天!!!大板凳!!!");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
- 修改web.xml文件
<servlet>
<servlet-name>movie</servlet-name>
<servlet-class>fangdao.movie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>movie</servlet-name>
<url-pattern>/movie.jsp</url-pattern>
</servlet-mapping>
如果直接复制http://localhost:8080/movie.jsp
,将自动跳转至如下界面
通过点击青春有你3的链接,回调到movie.jsp里
4.2 表单提交数据
- 创建form.jsp
<form action="/zouxiaopang/formpost" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>性别</td>
<td>
<input type="radio" name="gender" value="男">男
<input type="radio" name="gender" value="女">女
</td>
</tr>
<tr>
<td>爱好</td>
<td>
<input type="checkbox" name="hobbies" value="游泳">游泳
<input type="checkbox" name="hobbies" value="跑步">跑步
<input type="checkbox" name="hobbies" value="飞翔">飞翔
</td>
</tr>
<input type="hidden" name="aaa" value="my name is zouxiaopang">
<tr>
<td>你的来自于哪里</td>
<td>
<select name="address">
<option value="宁波">宁波</option>
<option value="深圳">深圳</option>
<option value="北京">北京</option>
</select>
</td>
</tr>
<tr>
<td>详细说明:</td>
<td>
<textarea cols="30" rows="2" name="textarea"></textarea>
</td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>
- 创建formpost.java文件
Tomcat服务器默认编码是ISO 8859-1,而浏览器使用的是UTF-8编码。
public class formpost extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置request字符编码的格式
request.setCharacterEncoding("UTF-8");
//通过html的name属性,获取到值
String username = request.getParameter("username");
String password = request.getParameter("password");
String gender = request.getParameter("gender");
//复选框和下拉框有多个值,获取到多个值
String[] hobbies = request.getParameterValues("hobbies");
String[] address = request.getParameterValues("address");
//获取到文本域的值
String description = request.getParameter("textarea");
//得到隐藏域的值
String hiddenValue = request.getParameter("aaa");
System.out.println("username:" + username);
System.out.println("password:" + password);
System.out.println("gender" + gender);
for(String s : hobbies)
System.out.print(s + " ");
System.out.println();
for(String s : address)
System.out.print(s + " ");
System.out.println();
System.out.println("description" + description);
System.out.println("hiddenValue" + hiddenValue);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
- 修改web.xml文件
注:url-pattern要和form表单action属性值一样
<servlet>
<servlet-name>form</servlet-name>
<servlet-class>formpost</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form</servlet-name>
<url-pattern>/zouxiaopang/formpost</url-pattern>
</servlet-mapping>
- 运行结果
4.3 超链接方式提交数据
- 常见的get方式提交数据:使用超链接,sendRedirect
格式如下:
sendRedirect("servlet的地址?参数名="+参数值 &"参数名="+参数值);
- 使用超链接将数据带给浏览器(mmm.jsp文件)
<h3>点击下面链接,选择pick的小孩</h3>
<a href="http://localhost:8080/output?name=连淮伟">连淮伟</a>
- 在
output.java
中接受数据
response.setContentType("text/html;charset=UTF-8");
String name = request.getParameter("name");
response.getWriter().write(name + "平安健康!!!");
注:提交数据能用post就用post,get太过于依赖服务器
4.4 实现转发
- 使⽤response的
sendRedirect()
可以实现重定向,做到的功能是页面跳转; - 使⽤request的
getRequestDispatcher.forward(request,response)
实现转发,做到的功能也是⻚⾯跳转
- 在
output.java
实现转发,可以添加参数!
//为name关键字设置值为 邹小胖
request.setAttribute("name","邹小胖");
// 获取到requestDispatcher 对象
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/input");
// 调用requestDispatcher 对象的 forwar() 实现转发,传入request,response
requestDispatcher.forward(request,response);
- 在
input.java
中进行处理
response.setContentType("text/html;charset=UTF-8");
String name = (String)request.getAttribute("name");
response.getWriter().write(name);
注意点
- 使⽤ServletContext和request实现Servlet之间的通讯,⼀般的原则:可以使⽤request就尽可能使⽤request。因为ServletContext代表着整个web应⽤,使⽤ServletContext会消耗⼤量的资源,⽽request对象会随着请求的结束⽽结束,资源会被回收。使⽤request域进⾏Servlet之间的通讯在开发中是⾮常频繁的。
- 如果在调⽤forward⽅法之前向Servlet引擎的缓冲区中写⼊了内容,只要写⼊到缓冲区中的内容还没有被真正输出到客户端,forward⽅法就可以被正常执⾏,原来写⼊到输出缓冲区中的内容将被清空,但是,已写⼊HttpServletResponse对象中的响应头字段信息保持有效。