课程回顾:Servlet技术
Servlet的概述
1.Servlet在javax.servlet.Servlet接口,有5个方法。
2.接收和响应从客户端发送过来的请求。
Servlet的入门
1.入门的程序
* 实现Servlet的接口,实现5个方法
* 编写配置文件web.xml中编写
<servlet>
<servlet-name>随便写
<servlet-class>全路径
<servlet-mapping>
<servlet-name>和上面相同
<url-pattern>访问的路径
Servlet的生命周期
1.总结
* 第一次访问的时候,Servlet被创建,创建后立即调用init方法进行初始化,调用一次。
* 提供服务,调用service方法,N次。
* 服务器关闭的时候,servlet实例被销毁,销毁之前调用destroy方法进行销毁,调用一次。
Servlet接口和实现类的一些关系
1.简便开发Servlet
2.以后的开发步骤
* 继承HttpServlet,重写doGet和doPost方法
* 编写配置文件
自动加载
1.第一次访问的时候,才会创建Servlet实例,配置,服务器在启动的时候,就可以创建Servlet实例对象了!!
2.在<servlet>标签下<load-on-startup> 值0正整数
url-pattern的配置
1.配置有三种方式
* 完全路径匹配 /demo
* 目录匹配 /*
* 扩展名匹配 *.do
2.配置多个Servlet,到底访问哪一个?
* 优先级 完全路径匹配 > 目录 > 扩展名
WEB的路径的问题
1.相对路径
* 找到访问资源的位置的关系。
* WEB开发中很少写相对路径
2.绝对路径
* http://localhost/day09/demo1
* /day09/demo1
* 项目名称前有 / (绝对路径都是以/开头的)
* 绝对路径分成两种
* 客户端绝对路径
* 从客户端出发
* 包含项目名称
* 服务器端绝对路径
* 已经进入到服务器的内部了。
* 不用编写项目名称
ServletConfig接口
1.和配置文件的相关的接口,init方法
2.方法
* 获取到servlet-name的名称
* 获取初始化参数
* 获取ServletContext域对象
ServletContext对象
1.域对象(传递数据) ,域的作用的范围不同的,ServletContext域的范围,代表的是整个WEB的应用!!
2.Servlet的特点
* 服务器启动的时候创建,服务器关闭的就销毁了!!
* 被WEB所有的资源所共享!!
* 与天地同寿!!
3.作用
* 获取全局的初始化参数(全局:所有的Servlet中都可以通过ServletContext来获取初始化参数)
* 实现数据的共享
* 读取资源的文件
* getResourceAsStream("服务器绝对路径,不包含项目名称")
* getRealPath("服务器绝对路径,不包含项目名称")
今天内容:ServletRequest和ServletResponse
ServletResponse对象概述
1.概述
* ServletResponse对象,代表的响应的对象(从服务器端到客户端),记住:从服务器向客户端输出一些内容,都找response对象!
* ServletResponse子对象,是HttpServletResponse(一般情况下都使用HttpServletResponse)
* 都是接口,实现类是Tomcat服务器创建的!!
2.看文档(掌握的一些方法)
* ServletOutputStream getOutputStream() -- 获取字节是输出流(重点)
* PrintWriter getWriter() -- 获取字符的输出流(重点)
* void setCharacterEncoding(String charset) -- 设置编码,设置response对象的缓冲区的编码(重点)
* void setContentType(String type) -- 设置头(Content-Type),解决浏览器打开文件时采用的编码(重点)
* void addCookie(Cookie cookie) -- 回写Cookie(今天不讲)
* void addHeader(String name, String value) -- 设置响应头
* 一个头,对应多个值!!
* void addDateHeader(String name, long date) -- 设置响应vv头
* 设置日期的头信息
* void sendRedirect(String location) -- 重定向的功能(重点)
* String location 要重定向的地址,不用设置302的状态码
* location 客户端绝对路径(包含项目名称!!)
* void setHeader(String name, String value) -- 设置响应头(重点)
* 一个头,对应的一个值!!(常用)
* void setStatus(int sc) -- 设置状态码
重定向的案例
1.重定向的代码怎么编写?重定向到底有什么样的作用?重定向应用在哪?
2.重定向的理论
* 先班长借钱,班长没钱(给我一个暗号(状态吗 302),但是回一个地址(冲订单的一个地址,使用头信息location)),浏览器获取到了302,和location的头,直接就去访问location的地址了!!
* 两次请求,两次响应!!
3.重定向应用在哪?
* 完成的页面的跳转!!
4.开始重定向的案例
* 头信息
* location --设置重定向的地址
* 302状态码 -- 必须要返回的
5.登陆的重定向的案例
* 需求:编写登陆的页面,输入用户名和密码,把表单提交到后台的Servlet程序中。在后台接收到用户输入的内容,进行判断,如果用户名和密码都是admin,登陆成功了,跳转到成功的页面!!如果有一个不是admin,跳转回登陆的页面!!
6.代码
* 前台页面
<h3>登陆页面</h3>
<form action="/day10/login" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="登陆" />
</form>
* 后台代码
/**
* 表单提交编写完成了!!
* 分析
* * 先接收用户输入的数据(没学过!!只能先使用一下)
* * 进行判断,用户名和密码是否都是admin,
* * 如果是,说明登陆成功,跳转到成功的页面
* * 如果不是,说明登陆失败,跳转到登陆页面
*/
// 接收数据
String username = request.getParameter("username");
String password = request.getParameter("password");
// 进行判断
if("admin".equals(username) && "admin".equals(password)){
// 登陆成功
// 成功页面
response.sendRedirect("/day10/response/suc.html");
}else{
// 登陆失败
response.sendRedirect("/day10/response/login.html");
}
页面定时刷新(refresh)
1.学习一个头信息就可以了。
2.响应的头信息
* refresh
* response.setHeader("refresh","5;url=/day10/xxx/xxx.html");
3.模拟页面的定时的跳转
4.代码
<body onload="run()">
<h3>页面将在<span id="spanId">5</span>秒后跳转!!</h3>
</body>
<script type="text/javascript">
// 页面在一加载的时候,开始执行了!!
// 页面一加载完成,run方法就会执行,开始读秒的操作!!
var x = 5;
function run(){
var span = document.getElementById("spanId");
// innerHTML
span.innerHTML = x;
x--;
// 每隔一秒减一次 window
window.setTimeout("run()", 1000);
}
</script>
禁用浏览器的缓存
1.不用记!!查询文档就可以了!!
2.禁用浏览器的缓存。
3.演示禁用缓存的代码
* 模拟的例子:模拟页面显示当前的时间。
* 需要使用3个头信息来完成禁用缓存!!
4.三个头信息中有一个头信息值是日期类型的。
* 方法还需要改变
* setDateHeader(String name,long m)
5.头的开始的字母是C E P
// 设置3个头信息 C E P
response.setHeader("Cache-Control", "no-cache");
// 日期格式
response.setDateHeader("Expires", -1);
// 字符串
response.setHeader("Pragma", "no-cache");
向页面输出中文乱码的问题
1.目的:输出中文,先获取输出的流。response对象提供了两个方式!!
* ServletOutputStream getOutputStream() -- 获取字节是输出流
* PrintWriter getWriter() -- 获取字符的输出流
2.使用字节的输出流,输出中文的乱码的问题
* 使用字节流输出中文的时候,有可能乱码!!
* 获取byte数组的编码和浏览器打开文件的编码不一致造成的!!
* 解决这个问题
* 目的:把编码保证一致!!
* 获取byte数组指定一个编码(编码一)!!
* "哈罗我的".getBytes("UTF-8")
* 设置浏览器默认打开文件的编码(编码二)!!
* response.setHeader("Content-Type", "text/html;charset=UTF-8");
* 编码一和编码二一致,就不会产生乱码的问题!!
3.使用字符的输出流,输出中文的乱码问题
* 使用字符流输出中文,必须会产生乱码的!
* Tomcat服务器7以下版本都使用的是ISO-8859-1编码!!
* 解决问题
* 手动设置response缓冲区的编码,设置UTF-8(编码一)
* void setCharacterEncoding("UTF-8")
* 设置浏览器打开文件采用的编码。(编码二)
* response.setHeader("Content-Type", "text/html;charset=UTF-8");
* 编码一和编码二一致,不会产生乱码!!
4.总结,输出中文的乱码的问题,分成两种情况
* 字节
* 获取byte数组的时候,设置指定的编码
* "哈罗我的".getBytes("UTF-8")
* 设置浏览器打开文件时采用的编码
* response.setHeader("Content-Type", "text/html;charset=UTF-8");
* 字符
* 设置response对象的缓冲区的编码
* void setCharacterEncoding("UTF-8")
* 设置浏览器打开文件时采用的编码
* response.setHeader("Content-Type", "text/html;charset=UTF-8");
* 字符流的简便的方式
* response.setContentType("text/html;charset=UTF-8");
文件下载
1.记住一句话,两个头一个流
2.两个响应头
* Content-Type -- 值就不能自己手写了,有方法可以来获取文件的格式(MIME类型)
* Content-Disposition -- 以附件的形式打开,值的写法是固定的。attachment;filename= +文件的名称(中文会乱码)
3.一个流
* 先获取到要下载的文件的输入流
4.代码
* 前台代码
<h3>文件的下载</h3>
<h4><a href="/day10/download?filename=girl.jpg">girl.jpg</a></h4>
<h4><a href="/day10/download?filename=girl7.jpg">girl7.jpg</a></h4>
<h4><a href="/day10/download?filename=w.jpg">w.jpg</a></h4>
* 后台代码
// 接收参数(接收文件名称)
String filename = request.getParameter("filename");
// 设置两个头信息
String type = this.getServletContext().getMimeType(filename);
response.setContentType(type);
response.setHeader("Content-Disposition", "attachment;filename="+filename);
// 要下载的文件的文件名称已经获取到了 filename=girl.jpg filename=w.jpg
// 目的:需要找到该文件名称的文件,获取该文件的输入流
// 获取该文件的路径
// path是download的绝对磁盘路径
String path = this.getServletContext().getRealPath("/download");
System.out.println("文件夹的路径:"+path);
// 拼接成文件的路径
String filepath = path+"/"+filename;
System.out.println("文件的路径:"+filepath);
// 文件的输入已经获取到了
InputStream in = new FileInputStream(filepath);
// 获取输出流
OutputStream os = response.getOutputStream();
// 拷贝
int len = 0;
byte [] b = new byte[1024];
while((len = in.read(b)) != -1){
os.write(b, 0, len);
}
in.close();
os.close();
验证码
1.验证码画图!!
2.注意
* 验证码的程序不能在前台完成校验!!只能后台校验!!
* 有可能有中文?中文的数据也是提前准备好的。
3.分析过程
/**
* 1.获取画布对象
* 2.获取画笔对象
* 2.1 画布默认是黑色的,目的给画布设置成灰色!!
* 2.2 画实心的矩形,大小和画布一样大,覆盖的效果。
* 3.准备好数据
* 3.1 通过随机的方式获取数据,通过画笔的对象把数据画到图片上就可以了。
* 4.把内存中的图片输出到客户端上
*/
4.代码
int width = 120;
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);
// 设置颜色
g.setColor(Color.BLUE);
g.drawRect(0, 0, width-1, height-1);
g.setColor(Color.YELLOW);
// 设置字体
g.setFont(new Font("隶书", Font.BOLD, 18));
// 准备好一些数据,把数据画到画布上
String words = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
Random random = new Random();
int x = 20;
int y = 20;
// 随机获取4个字符,显示画布上
for (int i = 0; i < 4; i++) {
// 随机获取字符
int index = random.nextInt(words.length());
// 获取该位置的字符
char ch = words.charAt(index);
// System.out.println(ch+"");
// 向 画布上写字符串
g.drawString(ch+"", x, y);
x += 20;
}
// 画干扰线
g.setColor(Color.GREEN);
int x1,y1,x2,y2;
for (int i = 0; i < 4; i++) {
x1 = random.nextInt(width);
y1 = random.nextInt(height);
x2 = random.nextInt(width);
y2 = random.nextInt(height);
g.drawLine(x1, y1, x2, y2);
}
// 先输出到客户端上
ImageIO.write(image, "jpg", response.getOutputStream());
ServletRequest对象的概述
ServletRequest对象的概述
1.request对象代表的请求的对象(从客户端到服务器端),把客户端的一些信息封装到request对象中。
2.想获取到客户端的内容,需要找request对象。
3.ServletRequest也是一个接口,子接口是HttpServletRequest接口。实现类由Tomcat服务器提供的实现类。
4.方法
* Object getAttribute(String name) -- 获取域对象中的值(重点)
* String getParameter(String name) -- 获取请求的参数(获取一个值 text password radio)(重点)
* Map<String,String[]> getParameterMap() -- 获取请求的参数(返回的Map集合的key是name的名称,值是用户输入的值) (重点)
* String[] getParameterValues(String name) -- 获取请求的参数(获取的表单中的复选框的值)
* String getRemoteAddr() -- 获取ip地址
* void removeAttribute(String name) -- 删除值
* void setAttribute(String name, Object o) -- 存入值(重点)
* void setCharacterEncoding(String env) -- 设置request对象的缓冲区的编码(重点)
* String getHeader(String name) -- 获取请求头的信息(重点)
获取客户端的一些信息
1.学习有一些方法,但是非常非常多的,不用记。简单介绍一遍,以后用了,查询文档就可以了!!
2.方法和获取的内容
* http://localhost:8080/day10/AServlet?username=xxx&password=yyy
* String getScheme():获取协议,http
* String getServerName():获取服务器名,localhost
* String getServerPort():获取服务器端口,8080
* String getContextPath():获取项目名,/day10
* String getServletPath():获取Servlet路径,/AServlet
* String getQueryString():获取参数部分,即问号后面的部分。username=xxx&password=yyy
* String getRequestURI():获取请求URI,等于项目名+Servlet路径。/day10/AServlet
* String getRequestURL():获取请求URL,等于不包含参数的整个请求路径。http://localhost:8080/day10/AServlet
3.需要大家记住一个方法
* request.getContextPath() – 获取的项目名称
获取请求头的信息
1.请求头,重要的几个?
* referer -- 记住当前网页的来源,作用:防止盗链
* user-agent -- 判断浏览器的版本
2.获取头的方法
* request.getHeader("头");
3.user-agent的头的作用
* 代码 String agent = request.getHeader("user-agent");
* 作用
* 可以判断浏览器
* 文件下载的时候,弹出的窗口显示中文的话,会乱码的!!解决乱码的问题。
* 根据不同的浏览器,采用不能编码来解决。
4.referer的头
* 记住当前网页的来源
* 防止盗链(有代码)
获取请求的参数(表单)
1.获取请求的参数,提供了三个方法。
2.方法
* String getParameter(String name) -- 获取请求的参数(获取一个值 text password radio)
* Map<String,String[]> getParameterMap() -- 获取请求的参数(返回的Map集合的key是name的名称,值是用户输入的值)
* String[] getParameterValues(String name) -- 获取请求的参数(获取的表单中的复选框的值)
3.演示方法
4.代码
* 前台代码
<h3>注册页面</h3>
<form action="/day10/reg" method="get">
姓名:<input type="text" name="name" /><br/>
密码:<input type="password" name="password" /><br/>
爱好:<input type="checkbox" name="love" value="java" />java
<input type="checkbox" name="love" value="lq" />篮球
<input type="checkbox" name="love" value="dbj" checked/>大宝剑
<br/>
<input type="submit" value="注册" />
</form>
* 后台代码
// 解决的是post中文乱码的问题
// request.setCharacterEncoding("UTF-8");
// 先接收用户名
String name = request.getParameter("name");
// 需要自己重新构造
name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
String password = request.getParameter("password");
System.out.println(name+" : "+password);
// 获取爱好
String [] loves = request.getParameterValues("love");
System.out.println("爱好:"+Arrays.toString(loves));
// 其他的处理了
System.out.println("====================================");
// 通过getParameterMap方法获取表单中的值
Map<String, String []> map = request.getParameterMap();
// map的key(name的名称 -- name password love)
// map的value(用户输入的值 meimei 123 java dbj)
Set<String> keys = map.keySet();
// 获取到每一个key值
for (String key : keys) {
String [] values = map.get(key);
System.out.println(key+" : "+Arrays.toString(values));
}
获取请求中文乱码问题
1.提交中文,会产生乱码的问题。目的:需要解决中文乱码的问题。
2.解决request获取请求参数的中文乱码的问题
* post
* 设置request缓冲区的编码就ok了。
* 表单的html页面是UTF-8编码,把数据传入Tomcat服务器中。Tomcat创建的request对象。默认的编码是ISO-8859-1
* 不支持中文。request缓冲区的默认的编码是ISO-8859-1
* 支持设置,设置request缓冲区的编码就可以了。
* void setCharacterEncoding("UTF-8)
* get
* 自己手动解决乱码的问题。
* name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
3.总结
* request获取请求参数的中文乱码的问题,分成两种请,分成post和get方式
* post和get解决方案是不同的
* post
* 设置request缓冲区的编码就可以了
* setCharacterEncoding("UTF-8)
* get
* 先获取到用户输入的值,手动自己转编码
* name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
request域对象
1.域对象:通过域对象传递数据。
2.方法
* setAttribute()
* getAttribute()
* removeAttribute()
3.范围的不同
* ServletContext域对象,范围是最大的,(代表整个WEB的应用,在WEB项目中,所有的资源都共享ServletContext域对象)
* request域对象,域的范围比较小了,代表的是一次请求的范围!!(发送请求,得到响应,就是一次请求的范围!!)
4.有什么作用?
* 用来传递数据,会传递什么数据?
* 以后:在会servlet中获取数据,需要把数据展示到页面上。提示的信息!!
转发和重定向的区别
1.会编写转发的代码,理解转发的含义。
2.掌握转发和重定向的区别(什么使用转发,什么使用重定向)
3.转发:和重定向的功能比较类似的,转发也可以完成页面的跳转的功能!!
4.转发代码怎么写?
* 重定向 response.sendRedirect("路径");
* 转发,找request对象,提供了一个方法
* RequestDispatcher getRequestDispatcher(String path) ,返回的是RequestDispatcher一个对象
* RequestDispatcher提供了一个方法,void forward(ServletRequest request, ServletResponse response)
* forward帮咱们转发的功能!!
* 代码怎么写?
* request.getRequestDispatcher("").forward(request,response) -- 转发的代码的编写!!
5.转发和重定向路径的写法
* 重定向的地址(客户端的绝对路径,包含项目名称)
* 转发的路径(服务器端的绝对路径,不包含项目名称)
6.转发和重定向区别
* 共同点:都可以完成页面跳转的功能!
* 不同点
* 重定向是两次请求,两次响应,转发是一次请求,一次响应,就可以request域来传递一些数据!!
* 重定向的地址栏会发生变化,转发的地址栏不会发生变化。
* 重定向可以定向到任何的页面(项目的中的页面,网络上的资源),转发只能在服务器的内部完成跳转!!