1、web开发技术
- 静态web资源的开发技术
- Html
- 常用动态web资源开发技术
- JSP/Servlet、ASP、PHP等
- 在java中,动态web资源开发技术统称为javaweb
2、常见的web服务器
- weblogic:支持J2EE规范
- websphere:支持J2EE规范
- apache(tomcat):支持全部JSP以及Servlet规范,开源的
- 常见的服务器端口地址:
- http端口:80
- smtp端口:25
- pop3端口:110
- ftp端口:23
- https端口:443
3、web.xml文件
-
web应用的重要配置文件,一切涉及到对web应用中的web资源进行配置,都是在web.xml文件中进行设置的,如:
-
1、某个web资源配置为网站首页(设置index.xml为首页)
-
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
-
- 2、将Servlet程序映射到某个url地址上
- 3、为web应用配置监听器
- 4、为web应用配置过滤器
- .....
-
4、虚拟主机的配置
- 配置虚拟主机就是在tomcat服务器中配置一个网站
-
如需要在web服务器中配置一个网站,需使用Host元素进行配置,如:
<Host name="site1" appBase="d:\app">
<Context path="浏览器访问目录" docBase="应用的真实目录" />
<Host>
- 配置的主机(网站)要想被外部访问,必须在DNS服务器或Windows系统中注册
-
在Windows中的注册方式为修改计算机的hosts文件,如:
c:\Windows\System32\drivers\etc\hosts
在文件中添加如:
192.168.25.21(电脑IP) www.djh.com
-
对于web应用可以使用命令进行打包,后缀名打包为war,如:
-
web应用:news 打包:jar -cvf news.war news
- 对于打包后的war包,当拷贝到服务器目录(如:tomcat的webapps)下时会自动解压
5、tomcat配置https连接器
-
工具:
keytool -genkey -alias tomcat -keyalg RSA -alias:表示的是定义别名为tomcat RSA:表示采用的算法
-
配置:在tomcat服务器的server.xml文件中添加如下代码
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="上面工具产生的密钥库文件" keypass="上面工具中填入的密码" />
6、HTTP协议
- HTTP协议用于定义客户端与WEB服务器通讯的格式
-
使用telnet程序连接web服务器,可以使用HTTP协议获取某个页面,快速了解HTTP协议的作用,如:
扫描二维码关注公众号,回复: 161552 查看本文章在tomcat的webapps目录下有一个news应用,其中有一个1.html,则通过命令行输入下列命令可以连接并查看 telnet localhost 8080(服务器端口) (回车) GET /news/1.html HTTP/1.1 (连续回车两次可查看结果)
- HTTP协议与平台无关
-
HTTP请求
-
一个完整的HTTP请求包括以下内容:
一个请求行、若干消息头、以及实体内容,如: 请求行:(用于描述客户端的请求方式、请求的资源名称以及使用的HTTP协议版本) GET /news/my.html HTTP/1.1 多个消息:(用于描述客户端请求的主机地址以及客户端的一些环境信息等) Accept: */* Accept-Language: en-us Connection: Keep-Alive Host: localhost Reference: http://localhost/link.asp
-
请求方式有:
POST、GET、HEAD、OPTIONS、DELETE、TRACE、PUT 常用的为:GET与POST
- 用户如没有设置,默认情况下浏览器向服务器发送的都是get请求
-
GET与POST的区别:
-
GET请求,可以在请求的URL地址后以?的形式带上提交给服务器的数据,多个数据之间以&进行分割,如:
GET /mail/1.html?name=abc&password=123 HTTP/1.1
- GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K
- POST请求,可以在请求的实体内容中向服务器发送数据
- POST方式的特点:传送的数据量无限制
-
-
HTTP请求的常用头:
Accept:text/html,image/* (告诉服务器,客户端支持的数据格式) Accept-Charset:ISO-8859-1 (告诉服务器,客户端采用的编码) Accept-Encoding:gzip,compress (告诉服务器,客户端支持的数据压缩格式) Accept-Language:en-us,zh-cn (客户端的语言环境) Host:www.djh.com.cn:80 (表示请求的主机) if-Modified-Since:Tue, 11 Jul 2016 18:23:59 GMT (告诉服务器,资源的缓存时间) Referer:http://www.djh.com.cn/index.jsp (告诉服务器,是从哪个资源来访问服务器) User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36) (客户机的软件环境) Cookie (向服务器带数据) Connection:close(Keep-Alive) (表示连接状态) Date:Thu, 11 Aug 2016 10:32:14 GMT
-
-
HTTP响应:
-
一个HTTP响应代表服务器向客户端回送的数据,它包括:
一个状态行、若干消息头以及实体内容
-
如:
HTTP/1.1 200 OK //状态行(用于描述服务器对请求的处理结果) Server:Apache-Coyote/1.1 //多个响应头(用于描述服务器的基本信息以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会它送回来的数据) Date:Thu, 11 Aug 2016 10:32:14 GMT Content-Length: 18 Content-Type:text/html Content-control:private //空行 <HTML> //实体内容(代表服务器向客户端回送的数据) ....
-
-
状态行:
-
格式:
HTTP版本号 状态码 原因叙述<CRLF> 如: HTTP/1.1 200 OK
-状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数,响应状态码分为5类,如下:
100~199:表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 200~299:表示成功接收请求并已完成整个处理过程,常用200 300~399:为完成请求,客户需进一步细化请求,如:请求的资源已经移动一个新地址,常用302(会携带一个location)、304与307(和缓存相关) 400~499:客户端的请求有错误,常用404、403 500~599:服务器端出现错误,常用500
-
-
HTTP常用的响应头:
Location:http://www.djh.com/index.jsp (配合状态码302使用,用于告诉客户端寻找的资源) Server:Apache-Coyote/1.1 (告诉客户端服务器的类型) Content-Encoding:gzip (告诉客户端数据使用的压缩格式) Content-Length:18 Content-Language:zh-cn Content-Type:text/html; charset=GB2312 (通知客户端回送数据的类型) Last-Modified:Wed, 10 Aug 2016 11:32:19 GMT Refresh:1;url=http://www.djh.com (通知客户端间隔多长时间刷新一次) Content-Disposition:attachment; filename=aaa.zip (通知客户端以下载的方式打开数据,filename表示保存的文件名) Transfer-Encoding: chunked Set-Cookie:SS=Q0=5Lb_nQ; path=/search ETag:VV/"7777-1242234904000" (缓存相关的,可以做到时时更新) Expires:-1 (通知客户端将回送的数据资源缓存多长时间,-1与0表示不缓存) Cache-Control:no-cache (通知客户端不缓存数据) Pragma:no-cache (通知客户端不缓存数据) Connection:close(Keep-Alive) Date:Thu, 11 Aug 2016 10:55:36 GMT
-
如:ServletDemo:
package com.djh.servlet; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.GZIPOutputStream; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class ServletDemo */ @WebServlet("/ServletDemo") public class ServletDemo extends HttpServlet { /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.create a data String str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; System.out.println("before compress :" + str.getBytes().length); //2.create Byte Array Output Stream ByteArrayOutputStream baos = new ByteArrayOutputStream(); //3.create a GZIP stream GZIPOutputStream gzos = new GZIPOutputStream(baos); //4.start zip data gzos.write(str.getBytes()); //5.close gzos and baos gzos.close(); baos.close(); byte gzip[] = baos.toByteArray(); System.out.println("After compress : " + gzip.length); //设置数据的压缩格式 response.setHeader("Content-Encoding", "gzip"); response.setHeader("Content-Length", gzip.length + ""); //set the refresh time,表示页面每隔5秒刷新一次 // response.setHeader("Refresh", 5 + ""); // response.setHeader("Refresh", "5; url='http://www.baidu.com'"); //表示每隔5秒刷新至百度界面 response.setHeader("Content-Disposition", "attachment; filename='4.java'"); //设置以下载的方式打开数据,并保存文件名为4.java的文件 //response data response.getOutputStream().write(gzip); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } }
-
-
HTTP请求头字段:
-
Range头只是服务器只传输一部分Web资源,这个头可以用来实现断电续传功能,Range字段可以通过三种格式设置要传输的直接范围:
Range: bytes=1000-2000 //表示传输范围从1000到2000字节 Range: bytes=1000- //表示传输Web资源中第1000个字节以后的所有内容 Range: bytes=1000 //传输最后1000个字节
-
-
HTTP响应消息头字段
- Accept-Ranges:这个字段说明web服务器是否支持Range支持,则返回Accept-Ranges: bytes;如果不支持,则返回Accept-Ranges: none
-
Content-Range:指定了返回的Web资源的直接范围,这个字段值的格式是如下:
Content-Range: 1000-3000/5000
-
7、Servlet开发
- Servlet是一门用于开发动态Web资源的技术
- API中提供了一个servlet接口,若想开发一个动态web资源,需要完成以下2步:
- 编写一个Java类,实现servlet接口
- 将开发好的Java类部署到web服务器中
- 在浏览器地址栏中输入一个地址,按下回车键所发生的事:
- 1、浏览器拿到地址,优先访问本地的hosts文件获取对应的ip地址,若hosts中不存在时会去访问DNS,连上服务器
- 2、与服务器建立连接,向服务器发送http请求
- 3、web服务器根据请求的数据解析出需要访问的主机名、web应用以及web资源
- 4、首次访问时创建servlet实例
- 5、调用servlet的init()方法完成初始化serlet对象
- 6、web服务器创建请求与响应,向servlet发送请求
- 7、service()方法响应客户端的请求,并对根据请求(request)进行处理
- 8、执行servlet的service方法,对请求进行处理
- 9、将处理的数据通过service方法的response返回
- 10、web服务器根据response中的数据构建一个http响应并回复客户端
- 11、web服务器向浏览器发送http响应
- 12、浏览器根据响应进行解析,将数据提取并显示
-
Servlet接口实现类
-
默认两个实现类:
GenericServlet、HttpServlet
- HttpServlet
- HttpServlet指能够处理HTTP请求的servlet,他在原有Servlet接口上添加了一些与HTTP协议相关的处理方法
- HttpServlet在实现Servlet接口时,覆写了service方法,改方法内的代码会自动判断用户的请求方式,然后调用相应的方法(doGet或doPost)
-
-
servlet的配置文件是在web.xml文件中进行的,使用servlet与servlet_mapping完成配置
- servlet元素用于注册Servlet,其包含两个主要的子元素:servlet-name与servlet-class,分别用于设置Servlet的注册名称和Servlet的完整类名
-
一个servlet-mapping元素用于映射一个已注册的Servlet的一个对外访问路径,其包含两个子元素:servlet-name与url-pattern,分别用于指定Servlet的注册名称和Servlet的对外访问路径,如:
<web-app> <servlet> <servlet-name>news</servlet-name> <servlet-class>com.djh.cn.NewsServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>news</servlet-name> <url-pattern>/newswebapp</url-pattern> </servlet-mapping> </web-app>
- 同一个Servlet可以被映射到多个URL上,也即是多个servlet-mapping元素的servlet-name子元素的设置值可以是同一个Servlet的注册名
-
在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式
-
第一种格式是:“*.扩展名”
<servlet-mapping> <serlet-name>AnyName</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping>
-
第二种格式:以正斜杠(/)开头并以“/*”结尾(匹配任意的)
<servlet-mapping> <servlet-name>AnyName</servlet-name> <url-pattern>/action/*</url-pattern> </servlet-mapping>
-
- Servlet不能独立运行,它的运行完全由Servlet引擎控制和调度
- 一般情况下,Servlet只会创建一个Servlet实例对象(service的init方法调用),该对象会一直存在直至Web容器退出,才会被销毁(service的destory方法)
- Servlet每次的访问请求,Servlet引擎都会创建一个新的HttpServletRequest对象与一个新的HttpServerResponse对象
-
关于servlet中的子元素load-on-startup
- 当servlet中包含改元素时表示当服务器启动时就初始化执行init方法
-
servlet-on-startup元素中的数据越小表示的优先级越高,如:
<servlet> <servlet-name>AnyName</servlet> <servlet-class>包名+类名</servlet-class> <load-on-startup>2</load-on-startup> </servlet>
- 在Struts框架中就应用到了该子元素
- 用途:为web应用写一个InitServlet,这个servlet配置为启动时加载,为整个web应用创建必要的数据库表和数据
-
如果某个Servlet的映射路径仅仅是一个正斜杠(/),那么这个Servlet就称为当前web应用程序的缺省Servlet
- 所有在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,即缺省的Servlet用于处理所有其他Servlet都不处理的访问请求
- 当访问tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet
- Servlet线程安全
- 当多个客户端并发访问同一Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,若service方法内访问同一资源就可能引发线程安全问题
- Servlet实现SingleThreadModel接口,则Servlet引擎将以单线程模式来调用其service方法
- SingleThreaModel接口中没有定义任何方法,在Servlet类的定义时直接实现SingleThreadModel接口即可
- 对于实现SindleThreadModel接口的Servlet,Servlet引擎仍支持对Servlet的多线程并发访问,采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象
- 注意:SingleThreadModel并不能真正意义上解决线程安全问题,建议使用synchronized
-
Servlet配置:
-
ServletConfig对象
-
在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数,如:
<servlet> <init-param> <param-name>data</param> <param-value>djh</param-value> </init-param> <init-param> <param-name>charset</param> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>url</param> <param-value>jdbc:mysql://localhost:3306/java</param-value> </init-param> ... </servlet>
-
web容器在创建servlet实例对象时,会自动将初始化参数封装到Servlet对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet,在doGet或doPost方法中可以获取配置对象,如:
public class ServletDemo1 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //get the single parameter value String val = this.getServletConfig().getInitParameter("user"); System.out.println(val); //get the all parameter value Enumeration enu = this.getServletConfig().getInitParameterNames(); while(enu.hasMoreElements()){ String name = (String) enu.nextElement(); String value = this.getServletConfig().getInitParameter(name); System.out.println(name + ": " + value); } response.getOutputStream().write("<h2 style='color:blue'>Success</h2>".getBytes()); } }
-
-
ServletContext对象
- Web服务器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前WEB应用
- ServletContext对象可以通过getServletConfig().getServletContext()方法获得
-
一个WEB应用中的所有Servlet共享同一个ServletContext对象,Servlet对象之间可以通过ServletContext对象来实现通讯或数据共享,也即是WEB应用之间的数据通讯,如:
//先运行ServletDemo2应用,再运行ServletDemo3应用 public class ServletDemo2 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String str = "djh"; this.getServletContext().setAttribute("data", str); } } public class ServletDemo3 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String str = (String) this.getServletContext().getAttribute("data"); System.out.println(str); //djh } }
-
Servlet转发技术,getRequestDispatcher()方法,如:
public class ServletDemo4 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String str = "This is Servlet forward technology"; //使用getServletContext传递数据,不建议使用,会存在线程安全问题,建议使用request域 this.getServletContext().setAttribute("data", str); //Servlet转发技术,获取转发对象 RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/1.jsp"); //转发 rd.forward(request, response); } } 1.jsp: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <font style="color:green; font-family:consolas;"> <% //在JSP中,使用application代表context,如下: String data = (String)application.getAttribute("data"); out.write(data); %> </font> </body> </html>
-
ServletContext对象读取资源文件
-
读取资源的方式:
-
方式一:getResourceAsStream()方法
-
从properties文件中读取,使用getResourceAsStream(path)方法
1、当properties文件在src目录下时,path的值为: /WEB_INF/classes/文件名.properties 2、当文件在包名下时,path的值为: /WEB-INF/classes/包名转变的路径名/文件名.properties 如:在包名com.djh下的db.properties /WEB-INF/classes/com/djh/db.properties 3、当文件直接在web应用路径下时,path值为: /WEB-INF/文件名.properties
- 在WEB应用中不要直接使用FileInputStream读取资源文件
-
-
方式二,使用FileInputStream绝对路径的方式读取
-
获取资源文件的绝对路径:
String path = this.getServletContext().getRealPath(path); //path的值即是方式一中的path值
-
使用文件流读取
FileInputStream fis = new FileInPutStream(path);
-
使用properties的方式读取资源文件
Properties pros = new Properties(); pros.load(fis); String str1 = pros.getProperty("name"); ......
-
-
方式三,通过类装载器的形式
-
使用类装载器的getResource()方法获取文件资源URL,再通过getPath()方法获取绝对路径
String path = 类.class.getCalssLoader().getResoource("资源文件路径").getPath();
-
通过传统读文件方式FileInputStream读取资源文件
FileInputStream fis = new FileInPutStream(path);
-
- 对于读取资源文件,如果只要读取一次,在多处应用时,一般使用静态代码块来处理这部分操作
- 通过类的加载器来读取的文件不能太大
-
-
-
-
response与request对象:
-
HttpServletResponse:
- 这个对象中封装了向客户端发送数据、发送响应头、发送响应码的方法
-
方法:
setStatus(int sc)、setHeader(String name, String value)、getWriter()、getOutputStream()
-
response常见应用
-
向客户端输出中文数据(使用OutputStream输出1时,用户看到的不是1)
public class ServletDemo1 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setHeader("Content-type", "text/html;charset=UTF-8"); //设置客户端以什么编码打开,写错时,浏览器会提示以下载的形式打开 String data = "这是中文字符使用字节流输出"; //获取输出字节流 OutputStream os = response.getOutputStream(); //向response写入数据 os.write(data.getBytes("UTF-8")); //带参表示以什么编码形式写入 } }
- html中的标签可以模拟一个http响应头,可以控制浏览器的行为
-
使用字符流时注意编码格式为,可以使用如下方式更改编码格式
response.setCharacterEncoding("utf-8"); //设置response使用的码表
-
文件下载和中文文件的下载
-
如果下载的文件为中文文件名,则文件名需要经过url编码,如:
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encoder(filename, "UTF-8"));
-
-
输出随机图片(BufferedImage、ImageIO),如:验证码的应用
-
汉字在Unicode中的区间:汉字区间:0x4E00→0x9FA5(Unicode码表)(\u4e00-\u9fa5)
//构建图片 BufferedImage image= new BufferedImage(wdth, height, BufferedImage.TYPE_INT_RGB); //获取图形对象 Graphics graph = image.getGraphicas(); //设置背景色 setBackGround(graph); setBorder(graph); //设置边框 drawRandomLine(graph); //画随机线 drawRandomNum((Graphics2D)graph); //写随机数 response.setContentType("image/jpeg"); response.setHeader("expries", -1); //设置浏览器不缓存 response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); ImageIO.write(image, "jpg", response.getOutputStream()); //向response写入图片数据 private void setBackground(Graphics g){ g.setColor(Color.WHITE); g.fillRect(width,height); } private void setBorder(Graphics g){ g.setColor(Color.BLUE); g.drawRect(xpos, ypos, width-2*xpos, height-2*ypos); } private void drawRandomLine(Graphics g){ g.setColor(Color.GREEN); for(int i = 0; i = count; i++){ /count表示画多少条线 //设置线的起始坐标 int Xstart = new Random().nextInt(width); int Ystart = new Random().nextInt(height); //设置线的终点坐标 int Xend = new Random().nextInt(width); int Yend = new Random().nextInt(height); g.drawLine(Xstart, Ystart, Xend, Yend); } } private void drawRandomNum(Graphics2D g){ g.setColor(Color.BLACK); g.setFont(new Font("consolas", Font.BOLD, font_size)); for(int i = 0; i < cnt; i++){ //汉字区间:0x4E00→0x9FA5(Unicode码表)(\u4e00-\u9fa5) int degree = new Random.nextInt()%30; //表示-30与30度以内的旋转 String str = "常用汉字码表"; String fnt = str.charAt(new Random().nextInt(str.length())) + ""; //调用Graphics2D的rotate()方法旋转字体 g.rotate(degree*Math.PI/180, , font_size); g.drawString(fnt, i + 5 + (i*(font_size + 10)), font_size); //加5表示距边框一段距离 g.rotate(-degree*Math.PI/180, , font_size) } }
-
-
发送http头,控制浏览器定时刷新网页(refresh)
-
设置refresh头属性,如:
response.setHeader("refresh", "5"); //5秒刷新一次 response.setHeader("refresh", "5;url='URL地址'"); //表示5秒后将跳转至url所指向的地址页面
-
-
发送http头,控制浏览器禁止缓存当前文档内容(expires),如:
response.setHeader("expires", System.currentTimeMillis() + 1000*60); //表示保存一分钟的数据,一分钟之后重新发请求
-
通过response实现请求重定向:(注意转发与重定向的场合)
- 请求重定向:指一个web资源收到客户端请求后,通知客户端去访问另外一个web资源
- 应用场景:用户登录、购物车...
-
实现方式:
- response.sendRedirect(location)
-
如:
response.sendRedirect("/news/index.jsp"); //相当于: //response.setStatus(302); //response.setHeader("location", "/news/index.jsp");
- 实现原理:
- 302状态码和location头即可实现重定向
- 重定向特点:
- 浏览器会向服务器发送两次,即有两个request与response
- 重定向技术会使浏览器地址栏发生变化
- getOutputStream与getWrite方法互斥,调用其中任意一个方法后,就不能在调用另一个方法
-
-
HttpServletRequest:
- 代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中
-
获取客户机信息方法:
-
getRequestURL:返回客户端发出请求时的完整URL,如:
http://www.sina.com/news/1.html
-
getRequestURI:返回请求行中的资源名部分,如:
news/1.html
- getQueryString:返回请求行中的参数部分
- getRemoteAddr:返回请求的客户端IP地址
- getRemoteHost:返回请求客户机的的完整主机名
- getRemotePort:返回客户端使用的网络端口号
- getLocalAddr:返回WEB服务器的IP地址
- getMethod:得到客户机请求方式
-
-
对于中文数据的提交需要先编码,后提交(在获取数据之前,设置请求的编码格式),如:
request.setCharacterEncoding("utf-8"); //针对于POST提交有效 //对于GET方式的提交,可以使用反向ISO-8859-1查找,如: username = request.getParameter("username"); username= new String(username.getBytes("iso8859-1"), "utf-8";
-
request常见应用
- request对象实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理
- 请求转发的应用场景:MVC设计模式
- request对象提供一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发
- request对象同时也是一个域对象,,通过request对象实现转发时,把数据通过request对象带给其他web资源处理
-
方法:
setAttribute、getAttribute、removeAttribute、getAttributeNames
-MVC设计模式:
M:model(JavaBean) V:view(JSP) C:control(Servlet)
- 转发注意事项:
- forward用于将请求转发到RequestDispatcher对象封装的资源
- 客户端只发一次请求,而服务器端有多个资源调用
- 浏览器地址栏无变化
-
include方法:
- RequestDispatcher.include方法用于将RequestDispatcher对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能
- 被包含的Servlet程序不可能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略
-
如:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String data = "this is middle text<br/>"; request.getRequestDispatcher("/page/1.jsp").include(request, response); request.setAttribute("data", data); request.getRequestDispatcher("index.jsp").include(request, response); request.getRequestDispatcher("/page/2.jsp").include(request, response); } //1.jsp <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> This is first JSP file.<br /> //index.jsp <% String data = (String)request.getAttribute("data"); out.write(data); %> //2.jsp This is Second JSP file.<br /> </body> </html>
- 防盗链
- request各种表单输入项数据的获取:
- text、password、radio、checkbox、file、select、textarea、hidden、image、button给js编程用
- 请求参数的中文乱码问题
- URL地址的编码
- 需要用到地址(path)的:
- getRequestDispatcher(path)
- response.sendRedirect(path)
- getServletContext().getRealPath(path)
- getServletContext().getResourceAsStream(path)
- form表单的action属性值
- a标签的href属性值
-
8、Cookie与Session
- 会话
- 多用户访问服务器时,产生的数据,需要保存每个用户的数据
-
保存会话数据的两种技术:
-
Cookie:
- Cookie是客户端技术,程序将每个用户的数据以Cookie的形式写给用户各自的浏览器,当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去,这就确保了web资源处理的就是用户各自的数据。
-
Cookie API
- javax.servlet.http.Cookie类用于创建一个Cookie,response接口中也定义了一个addCookie方法,用于在其响应头中增加一个相应的Set-Cookie头字段。request接口中也定义了一个getCookie方法,用于获取客户端提交的Cookie.
- Cookie类的方法:
- public Cookie(String name, String value)
- setValue与getValue
- setMaxAge与getMaxAge(方法为设置Cookie的有效期,默认客户端进程关闭)
- setPath与getPath
- setDomain与getDomain
- getName
-
Cookie应用:
public class CookieDemo1 extends HttpServlet { /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) * * 测试cookie,使用浏览器上次访问时间的例子 */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.设置响应数据的编码格式 response.setCharacterEncoding("UTF-8"); //2、设置浏览器打开的编码格式 response.setContentType("text/html;charset=UTF-8"); //3、获取响应流 PrintWriter pw = response.getWriter(); //4、获取Cookies数组 Cookie[] cookies = request.getCookies(); //5、先判断Cookie是否含有Cookie,有则遍历Cookies数组,获取相应的Cookie,否则不执行 if(cookies != null){ for(int i = 0; i <cookies.length; i++){ //6、获取相应的Cookie if(cookies[i].getName().equals("localAccessTime")){ long time =Long.parseLong(cookies[i].getValue()); //7、将long型的毫秒数转换成日期字符串 String date = new Date(time).toLocaleString(); //8、向浏览器发送的数据 String data = "上次访问 浏览器的时间: "; pw.print(data + date); } } } //9、创建Cookie对象,并封装最新的访问时间 Cookie cookie = new Cookie("localAccessTime", System.currentTimeMillis()+""); //10、设置Cookie的有效时间,默认是浏览器关闭即被删除,以秒为单位,注意:0表示删除Cookie文件 cookie.setMaxAge(5*24*60*60); //11、设置访问客户端携带Cookie的路径 cookie.setPath("/itheima"); //12.向浏览器(客户端)发送最新的Cookie response.addCookie(cookie); } }
- Cookie细节:
- 一个Cookie只能标识一种信息,至少含有一个标识该信息的名称(name)与设置值(value)
- 一个WEB站点可以给一个WEB浏览器(客户端)发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie
- 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB
- 注意:删除Cookie时,path必须保持一致,否则不会删除
-
Session:
- Session是服务端技术,利用该技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的session中取出数据为用户服务。
- 在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务
- Session和Cookie的主要区别在于:
- Cookie是把用户的数据写给用户的浏览器
- Session技术把用户的数据写到用户独占的session中
- Session对象由服务器创建,可以调用request对象的getSession方法得到session对象
-
Session是基于Cookie的,如下:
//session创建时,会创建一个相应的Cookie,并回写给客户端 HttpSession session = request.getSession(); String sessionId = session.getId(); Cookie cookie = new Cookie("JSESSIONID", sessionId); //通过session创建的Cookie的名字为JSESSIONID //Cookie可以设置有效期 cookie.setMaxAge(time); //time表示的是多少秒 response.addCookie(cookie); //回写Cookie
-
使用response的encodeURL方法可以设置url,会在url后自动添加jsessionid,如:
String url = response.encodeURL("webappurl");
- session案例:
- 用户登录
- 防止表单重复提交
- 表单页面由servlet程序生成,通过servlet为每次产生的表单页面分配一个唯一的随机标识符,并在form表单的一个隐藏字段中设置这个标识符,并将标识符保存在当前的session中
- 实现一次性验证码
- 基本的三个域对象(容器):
- request
- 当数据显示完就无用时,可以采用request
- session
- 数据除了显示,另外的一段时间内还有用,使用session
- servletContext
- 数据除了当前的servlet需要用到还需要另外的servlet用到
- request
-