import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//运行这个类,打开浏览器地址:http://localhost:9999/就可以打开指定网页
public class ServletSocket {
public static void main(String[] args) throws Exception {
//创建绑定到特定端口的服务器套接字。
ServerSocket ss = new ServerSocket(9999);
//Socket accept() 侦听并接受到此套接字的连接。
Socket soc = ss.accept();
//输入流
FileInputStream fin = new FileInputStream("D:\Html\html\Untitled-2.html");
//输出流
OutputStream out = soc.getOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while((len = fin.read(buffer)) > 0){
//读取到输出流
out.write(buffer,0,len);
}
out.close();
fin.close();
soc.close();
ss.close();
}
}
互联网常用协议的端口:
web:80
smtp:25
pop3: 110
ftp:23
https:443
Tomcat端口配置在conf/servet.xml文件下
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
Tomcat的目录层次:
- bin 存放启动和关闭Tomcat的脚本文件
- conf 存放Tomcat服务器的各种配置文件
- lib 存放Tomcat服务器的支撑jar包
- logs 存放Tomcat的日志文件
- temp 存放Tomcat运行时产生的临时文件
- webapps web应用所在目录,即供外界访问的web资源存放目录
- work Tomcat的工作目录
WEB应用程序指供浏览器访问的程序,通常也成为web应用。
一个web应用由多个静态web资源和动态web资源组成:
- html、css、js文件
- Jsp文件、java程序、支持jar包
- 配置文件等等
- 组成web应用的这些文件通常我们会使用一个目录组织,这个目录组织成为web应用所在目录
Web应用开发好后,若想供外界访问,需要把web应用所在目录交给web服务器管理,这个过程称之为虚拟目录的映射。
新建web应用之后需要配置web应用
server.xml
<Context path="对外访问路径" donBase="web应用地址" />
上面这种方式需要重启web服务器。
从Tomcat 6开始不建议将Context放在server.xml文件中,建议将此配置放在confCatalinalocalhost目录中
文件名任意.xml
<Context donBase="web应用地址">
这种方式不需要重启。
多级目录
文件名:a#b#c 代表a目录下的b目录下的c目录
配置缺省web应用:
将配置文件命名为:ROOT.xml
web应用的组成结构:不同类型的文件有严格的存放规则,否则不仅可能会是web应用无法访问,还会导致web服务器报错
- main web应用所在目录
-
- HTML、jsp、js文件等
-
- WEB-INF目录
-
- -classes目录 Java类
-
- -lib目录 java类运行需要的jar包
-
- -web.xml文件 web配置文件
web.xml:
//配置首页文件
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
配置虚拟主机
在WEB服务器中配置一个网站,需要用Host元素进行配置,例如:
server.xml:
<Host name="www.sina.com" appBase="c:sina">
<Context path="/mail" docBase="c:sinamail"/>
</Host>
path=""代表缺省
配置主机要想被外界访问,必须在DNS服务器或windows系统中注册
在windows中配置
winwos目录下system32/drivers/etc/Hosts文件:
IP地址 域名
如何配置文件:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Https连接加密
私钥 公钥:私钥的加密公钥解,公钥的加密私钥给。
Tomcat的体系结构和配置https连接器 java
- keytool -genkey -alias tomcat -keyalg RSA
客户链接上服务器后,向服务器请求某个web资源,称之为客户端向服务器发送一个HTTP请求,一个完整的HTTP请求包括:
一个请求行(客户端请求方式、请求资源名称以及HTTP协议版本号)、若干请求头、以及实体内容。
请求行中的GET称之为请求方式,请求方式有:
POST GET HEAD OPTIONS DELETE TRACE PUT
常用的:GET POST
如果没有设置默认GET请求方式,如果需要改变可以通过表单的方式改变请求方式。
不管是POST还是GET,都用于向服务器请求某个WEB资源,这两种方式区别在:
如请求为GET方式,则可以在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间用&分隔
GET方式的特点:在URL地址后附加带的数据是有限制的,气数据容量通常不能超过1K
如请求是POST方式,则可以在请求的实体内容中向服务器发送数据,POST的特点:传送的数据量无限制。
Servlet
开发一个web资源(开发一个Java程序向浏览器输出数据),需要两个步骤:
- 编写一个Java类,实现servlet接口
- 把开发好的Java类部署到web服务器中
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<servlet>
<!-- 给servlet取名,这个名字是任意的,不要用汉字-->
<servlet-name>hello</servlet-name>
<!-- 指明servlet的路径(包名+类名)-->
<servlet-class>EclipseWorkSpace.javastudy.src.servletDemo.ServletTest</servlet-class>
</servlet>
<servlet-mapping>
<!--要映射的servlet名-->
<servlet-name>hello</servlet-name>
<!--这是在浏览器中输入的访问该servlet的url-->
<url-pattern>/sp</url-pattern>
</servlet-mapping>
</web-app>
步骤:
- 在tomcat中新建一个myweb应用,然后在web应用中新建一个WEB-INF文件,并新建classes和lib文件夹,web.xml配置文件
- 将servlet-api.jar包导入到classpath路径:set classpath=%classpath%;
- 编译class文件
- 启动服务器访问
escplise导入tomcat,要想让服务器可用,一定要选择enable,选择debug模式。
Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet和HttpServlet
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet的接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大,因此开发人员在编写Servlet时,通常应继承这个类,避免直接实现Servlet接口
HttpServlet在实现Srevlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不是去覆写service方法。
处理字符:
public class HttpServletTest extends HttpServlet{
//处理get请求
public void doGet(HttpServletRequest req, HttpServletResponse res){
//业务逻辑
try{
PrintWriter pw = res.getWriter();
pw.println("hello");
}catch(Exception e){
e.printStackTrace();
}
}
//处理post请求
public void doPost(HttpServletRequest req, HttpServletResponse res){
this.doGet(req, res);
}
}
处理字节:
public class HttpServletTest extends HttpServlet{
/**
* @throws IOException
*
*/
//处理get请求
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException{
//业务逻辑
res.getOutputStream().write("hello".getBytes());
}
//处理post请求
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException{
this.doGet(req, res);
}
}
Servlet的一些细节:
由于客户端是访问URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到URL地址上,这个工作在web.xml文件中使用
一个
<servlet>
<!-- 给servlet取名,这个名字是任意的,不要用汉字-->
<servlet-name>hello</servlet-name>
<!-- 指明servlet的路径(包名+类名)-->
<servlet-class>EclipseWorkSpace.javastudy.src.servletDemo.ServletTest</servlet-class>
</servlet>
<servlet-mapping>
<!--给你的servlet取名,任意的-->
<servlet-name>hello</servlet-name>
<!--这是在浏览器中输入的访问该servlet的url-->
<url-pattern></url-pattern>
</servlet-mapping>
同一个Servlet可以被映射到多个URL上,即多个
在Servlet映射到URL中可以使用通配符,但只能有两种固定的格式:一种格式是:“.扩展名”,另一种是正斜杠(/)开头并以"/*"结尾。
*.扩展名:匹配所有相同扩展名文件 优先级高
/*:匹配所有文件 优先级低
Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其他请求服务,直到web容器退出,servlet实例对象才会销毁。
在Servlet的整个生命周期内,Servlet的init方法只会被调用一次。而对一个Servlet的每次调用请求都会导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse相应请求,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
如果在
<servlet>
<servlet-name>...</servlet-name>
<servlet-class>...</servlet-class>
<load-on-startup>2</load-on-startup>
<!--这个2代表启动顺序,数字越小,越早启动。-->
</servlet>
为web应用写一个InitServlet,这个servlet配置为启动时装在,为整个web应用创建必要的数据库表和数据。
如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet
凡是在web.xml文件中找不到匹配
在Tomcat的安装路径congweb.xml文件中,注册了一个org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为缺省Servlet。
当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。
线程安全
当多个客户端访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问同一个资源的话,就可能引发线程安全问题
如果某个Servlet实现了SingleThreadModel接口,nameServlet引擎将以单线程模式来调用起service方法
SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。
对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。
实现SingleThreadModl接口并不能真正解决Servlet的线程安全问题。因为Servlet殷勤会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为过时了。
子类覆盖父类方法,不能抛出比父类更多的异常。
ServletConfig对象
在Servlet的配置文件中,可以使用一个或多个
在servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息了。
覆写init()方法,会吧ServletConfig对象放在这个方法中操作。
doGet(){
//获取初始化参数信息
this.getServletConfig().getInitParameter("参数名字");
//得到所有的的初始化参数名称,获得的是枚举值
this.getServletConfig().getInitParameterNames();
//再通过参数名称得到参数值
}
在实际开发中,不适合在程序中写死的,可以通过配置文件配给servlet,例如:servlet采用哪个码表,servlet链接哪个库,servlet哪个配置文件。
WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象类实现通讯。ServletContext对象通常也被称之为context域对象。
利用ServletContext对象读取资源文件
1、得到文件路径
//多个servlet实现数据共享:比如:聊天室...
String data = "aaa";
this.getServpetContext()setAttribute("data", data); //往data中传入字符串aaa
servletContext域:
- 1、这是一个容器,servletContet域这句话说明这个容器作用范围,整个应用程序。
- 2、实现servlet的转发
//转发servlet
RequestDispathcher rd = this.getServletContext().getRequestDispatcher(path);
//操作转发到的servlet
rd.forward(request, respone);
2、读取资源文件的三种方式
3、.properties文件(属性文件)
在软件开发中,数据有关系用xml文件,没有关系用properties文件。
InputStream ins = this.getServletContext().getResourceAsStream(path); // WEB-INF/classes/db.properties,不是src中的,配置信息在classes文件中,path要用相对虚拟机的启动目录,web服务器和java虚拟机在bin目录下启动。
Properties prop = new Properties();
prop.load(ins);
//获取配置文件
String url = prop.getProperty("url
");
//*************************************************************************
//建议采用servletContext去读
//得到资源的绝对路径,再用上面的方式去读
String path = this.getServletContext().getPath();
InputStream ins = this.getServletContext().getResourceAsStream(path);
Properties prop = new Properties();
prop.load(ins);
//获取配置文件
String url = prop.getProperty("url");
如果读取资源文件的程序不是servlet的话,就只能通过类装载器去读了。
//非servlet获读取资源,这个文件不能太大,太大可能导致内存溢出
InputStream in = UserDao.class.getClassLoader().getResourceAsStream();
Properties prop = new Properties();
prop.load(in);
//获取配置文件
String url = prop.getProperty("url");
类加载器只加载一次,如果数据更新,读到的数据还是旧的数据,要读到更新的数据
//得到路径
String path = UserDao.class.getClassLoader().getResource("db.properties").getPath();
//再用传统的方式读
InputStream ins = this.getServletContext().getResourceAsStream(path);
Properties prop = new Properties();
prop.load(ins);
//获取配置文件
String url = prop.getProperty("url");
WEB服务器在收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象,和代表响应的response对象。
request和response对象既然代表请求和响应,name我们要获取客户机提交过来的数据,只需要找request对象就可以。要向客户机输出数据,只需要找response对象就可以。
HttpServletPesponse对象服务器的响应,这个对象封装了向客户端发送数据、发送响应头,发送响应状态码的方法。
setStatus(int sc)
setHeader(java.lang.String name, java.lang.String value)
//程序以什么码表输出,程序就一定要控制浏览器以什么码表打开
response.setHeader("Context-type","text/html;charset=utf-8");//设置页面编码为utf-8
String data = '';
OutputStream out = response.getOutputStream.weite(data.getBytes("UTF-8"));
getWriter()
getOutputStream()
//--------------------------------
//下面写错了,浏览器提示下载
response.setHeader("Context-type","text/html,charset=utf-8");
response常见应用:
向客户端输出中文数据:
- 分别以OutputStream和PrintWriter输出
- 使用HTML语言里面的标签来控制浏览器行为
<meta标签模拟http响应头来控制浏览器行为>
OutputStream out = response.getOutputStream.write("<meta http-equiv='context-type' content='text/html;charset=utf-8'>".getBytes());
out.write(data.getBytes());
out.write(1);//输出的是码表对应的字符,而不是数字1。如果想要数字1,输出字符1。
文件和中文文件的下载
this.getSerlvetContext().getRealPath("/down/1.jpg");//资源目录
String filename = path.sunString(path.lastIndexOf("\"+ 1);
//如果下载的文件是中文文件名,则文件名需要经过url编码
//通过URLEncoder.encode(filename, "UTF-8");得到url编码
response.setHeader("context-disposition", "attachment;filename=" + filename);
InputStream in = null;
OutputSTream out = null;
输出随机图片
//输出一张随机图片 bufferedimage imageIO
public static final int WIDTH = 120;
public static final int HEIGTH = 25;
BufferedImage image = new BufferedImage(WIDTH, HEIGTH,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
//设置背景色
setBackGround(g){
g.setColor(color.WHITE);
g.fillRece(0,0,WIDTH,HEIGHT);
}
//设置边框
serBorder(g){
g.serColor(Color.BLUE);
g.drawRect(1,1,WIDTH-2,HEIGTH-2);
};
//画干扰线
drawRandomLine(g){
g.setColor(Color.GREEN);
//画四条干扰线
for(int i = 0; i < 4; i++){
//干扰线坐标
int x1 = newRandom().nextInt(WIDTH);
int y1 = newRandom().nextInt(HEIGTH);
int x2 = newRandom().nextInt(WIDTH);
int y2 = newRandom().nextInt(HEIGTH);
g.drawLine(x1, y1, x2, y2);
}
};
//写随机数
String base = " u7684u4e00u4e86u662fu6211u4e0du5728u4ebau4eecu6709u6765u4ed6u8fd9u4e0au7740u4e2au5730u5230u5927u91ccu8bf4u5c31u53bbu5b50u5f97
u4e5fu548cu90a3u8981u4e0bu770bu5929u65f6u8fc7u51fau5c0fu4e48u8d77u4f60u90fdu628au597du8fd8u591au6ca1u4e3au53c8u53efu5bb6u5b66
u53eau4ee5u4e3bu4f1au6837u5e74u60f3u751fu540cu8001u4e2du5341u4eceu81eau9762u524du5934u9053u5b83u540eu7136u8d70u5f88u50cfu89c1
u4e24u7528u5979u56fdu52a8u8fdbu6210u56deu4ec0u8fb9u4f5cu5bf9u5f00u800cu5df1u4e9bu73b0u5c71u6c11u5019u7ecfu53d1u5de5u5411u4e8b
u547du7ed9u957fu6c34u51e0u4e49u4e09u58f0u4e8eu9ad8u624bu77e5u7406u773cu5fd7u70b9u5fc3u6218u4e8cu95eeu4f46u8eabu65b9u5b9e
u5403u505au53ebu5f53u4f4fu542cu9769u6253u5462u771fu5168u624du56dbu5df2u6240u654cu4e4bu6700u5149u4ea7u60c5u8defu5206u603bu6761
u767du8bddu4e1cu5e2du6b21u4eb2u5982u88abu82b1u53e3u653eu513fu5e38u6c14u4e94u7b2cu4f7fu5199u519bu5427u6587u8fd0u518du679c
u600eu5b9au8bb8u5febu660eu884cu56e0u522bu98deu5916u6811u7269u6d3bu90e8u95e8u65e0u5f80u8239u671bu65b0u5e26u961fu5148u529b
u5b8cu5374u7ad9u4ee3u5458u673au66f4u4e5du60a8u6bcfu98ceu7ea7u8ddfu7b11u554au5b69u4e07u5c11u76f4u610fu591cu6bd4u9636
u8fdeu8f66u91cdu4fbfu6597u9a6cu54eau5316u592au6307u53d8u793eu4f3cu58ebu8005u5e72u77f3u6ee1u65e5u51b3u767eu539fu62ffu7fa4
u7a76u5404u516du672cu601du89e3u7acbu6cb3u6751u516bu96beu65e9u8bbau5417u6839u5171u8ba9u76f8u7814u4ecau5176u4e66u5750
u63a5u5e94u5173u4fe1u89c9u6b65u53cdu5904u8bb0u5c06u5343u627eu4e89u9886u6216u5e08u7ed3u5757u8dd1u8c01u8349u8d8au5b57u52a0u811au7d27u7231u7b49u4e60u9635u6015u6708u9752u534au706bu6cd5u9898u5efau8d76u4f4du5531u6d77u4e03u5973u4efbu4ef6u611f
u51c6u5f20u56e2u5c4bu79bbu8272u8138u7247u79d1u5012u775bu5229u4e16u521au4e14u7531u9001u5207u661fu5bfcu665au8868u591fu6574u8ba4u54cdu96eau6d41u672au573au8be5u5e76u5e95u6df1u523bu5e73u4f1fu5fd9u63d0u786eu8fd1u4eaeu8f7bu8bb2u519cu53e4u9ed1
u544au754cu62c9u540du5440u571fu6e05u9633u7167u529eu53f2u6539u5386u8f6cu753bu9020u5634u6b64u6cbbu5317u5fc5u670d
u96e8u7a7fu5185u8bc6u9a8cu4f20u4e1au83dcu722cu7761u5174u5f62u91cfu54b1u89c2u82e6u4f53u4f17u901au51b2u5408u7834
u53cbu5ea6u672fu996du516cu65c1u623fu6781u5357u67aau8bfbu6c99u5c81u7ebfu91ceu575au7a7au6536u7b97u81f3u653fu57ce
u52b3u843du94b1u7279u56f4u5f1fu80dcu6559u70edu5c55u5305u6b4cu7c7bu6e10u5f3au6570u4e61u547cu6027u97f3u7b54u54e5
u9645u65e7u795eu5ea7u7ae0u5e2eu5566u53d7u7cfbu4ee4u8df3u975eu4f55u725bu53d6u5165u5cb8u6562u6389u5ffdu79cdu88c5
u9876u6025u6797u505cu606fu53e5u533au8863u822cu62a5u53f6u538bu6162u53d4u80ccu7ec6";
drawRandomNum(g){
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.BOLD, 20));
int x = 5;
for(int i = 0; i < 4; i++){
//汉字区间[u4e00-u9fa5] uncode编码从4e00到9fa5之间
//实际上取常用的汉字
String ch = base.charAt(new Rondom().nextInt(base.length()));
g.drawString(ch, x ,20);
x += 30;
}
};
//如果想让图片旋转,将传入的Graphic改为传入Graphic2D
// 30*3.14/180代表旋转30度
drawRandomNum(Graphic2D g2){
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.BOLD, 20));
int x = 5;
for(int i = 0; i < 4; i++){
//设置旋转
//int degree = new Random().nextInt(30); //0-30
int degree = new Random().nextInt()%30; //-30 到 30的区间值
g.rotate(degree*Math.PI/180,x,20);
g.drawString(ch, x ,20);
//传入完一个字符,要设置旋转回来,接着传入下一字符
g.rotate(-degree*Math.PI/180,x,20);
x += 30;
}
};
//图形写给浏览器
response.setContentType("image/jpg");
//控制浏览器不要缓存
reponse.setDateHeader("expries", -1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
ImageIO.write(image,"jpg",response.getOutputStream());
常见中文编码
u7684u4e00u4e86u662fu6211u4e0du5728u4ebau4eecu6709u6765u4ed6u8fd9u4e0au7740u4e2au5730u5230u5927u91ccu8bf4u5c31u53bbu5b50u5f97
u4e5fu548cu90a3u8981u4e0bu770bu5929u65f6u8fc7u51fau5c0fu4e48u8d77u4f60u90fdu628au597du8fd8u591au6ca1u4e3au53c8u53efu5bb6u5b66
u53eau4ee5u4e3bu4f1au6837u5e74u60f3u751fu540cu8001u4e2du5341u4eceu81eau9762u524du5934u9053u5b83u540eu7136u8d70u5f88u50cfu89c1
u4e24u7528u5979u56fdu52a8u8fdbu6210u56deu4ec0u8fb9u4f5cu5bf9u5f00u800cu5df1u4e9bu73b0u5c71u6c11u5019u7ecfu53d1u5de5u5411u4e8b
u547du7ed9u957fu6c34u51e0u4e49u4e09u58f0u4e8eu9ad8u624bu77e5u7406u773cu5fd7u70b9u5fc3u6218u4e8cu95eeu4f46u8eabu65b9u5b9e
u5403u505au53ebu5f53u4f4fu542cu9769u6253u5462u771fu5168u624du56dbu5df2u6240u654cu4e4bu6700u5149u4ea7u60c5u8defu5206u603bu6761
u767du8bddu4e1cu5e2du6b21u4eb2u5982u88abu82b1u53e3u653eu513fu5e38u6c14u4e94u7b2cu4f7fu5199u519bu5427u6587u8fd0u518du679c
u600eu5b9au8bb8u5febu660eu884cu56e0u522bu98deu5916u6811u7269u6d3bu90e8u95e8u65e0u5f80u8239u671bu65b0u5e26u961fu5148u529b
u5b8cu5374u7ad9u4ee3u5458u673au66f4u4e5du60a8u6bcfu98ceu7ea7u8ddfu7b11u554au5b69u4e07u5c11u76f4u610fu591cu6bd4u9636
u8fdeu8f66u91cdu4fbfu6597u9a6cu54eau5316u592au6307u53d8u793eu4f3cu58ebu8005u5e72u77f3u6ee1u65e5u51b3u767eu539fu62ffu7fa4
u7a76u5404u516du672cu601du89e3u7acbu6cb3u6751u516bu96beu65e9u8bbau5417u6839u5171u8ba9u76f8u7814u4ecau5176u4e66u5750
u63a5u5e94u5173u4fe1u89c9u6b65u53cdu5904u8bb0u5c06u5343u627eu4e89u9886u6216u5e08u7ed3u5757u8dd1u8c01u8349u8d8au5b57u52a0u811au7d27u7231u7b49u4e60u9635u6015u6708u9752u534au706bu6cd5u9898u5efau8d76u4f4du5531u6d77u4e03u5973u4efbu4ef6u611f
u51c6u5f20u56e2u5c4bu79bbu8272u8138u7247u79d1u5012u775bu5229u4e16u521au4e14u7531u9001u5207u661fu5bfcu665au8868u591fu6574u8ba4u54cdu96eau6d41u672au573au8be5u5e76u5e95u6df1u523bu5e73u4f1fu5fd9u63d0u786eu8fd1u4eaeu8f7bu8bb2u519cu53e4u9ed1
u544au754cu62c9u540du5440u571fu6e05u9633u7167u529eu53f2u6539u5386u8f6cu753bu9020u5634u6b64u6cbbu5317u5fc5u670d
u96e8u7a7fu5185u8bc6u9a8cu4f20u4e1au83dcu722cu7761u5174u5f62u91cfu54b1u89c2u82e6u4f53u4f17u901au51b2u5408u7834
u53cbu5ea6u672fu996du516cu65c1u623fu6781u5357u67aau8bfbu6c99u5c81u7ebfu91ceu575au7a7au6536u7b97u81f3u653fu57ce
u52b3u843du94b1u7279u56f4u5f1fu80dcu6559u70edu5c55u5305u6b4cu7c7bu6e10u5f3au6570u4e61u547cu6027u97f3u7b54u54e5
u9645u65e7u795eu5ea7u7ae0u5e2eu5566u53d7u7cfbu4ee4u8df3u975eu4f55u725bu53d6u5165u5cb8u6562u6389u5ffdu79cdu88c5
u9876u6025u6797u505cu606fu53e5u533au8863u822cu62a5u53f6u538bu6162u53d4u80ccu7ec6
发送http头,控制浏览器定时刷新网页
//控制浏览器定时刷新
response.setHeader("refresh", "3");//每3秒访问一次
String data = new Random().nextInt(1000000) +"";
response.getWriter().write(data);
//-----------------使用下面这种方式-----------------------------
String message = "<meta http-equiv='refresh' content='3;url=/dya/intdex.jsp'>登录成功,将在3秒后跳转,如果没有跳转请点击<a href="">链接</a></meta>";
this.getServletContext().setAttribute("message", message);
this.getServletContext().getRequestDispatcher("/message.jsp").forward(requext,response);
发送http头,控制浏览器禁止缓存当前文档内容
response.setCharacterEncoding("UTF-8");//设置response使用的码表,控制response以什么码表向浏览器写什么数据、response.setHeader("Context-type","text/html;charset=utf-8");//控制浏览器以什么码表打开
reponse.setCpntentTypr("text/html;charset=utf-8");//这句可以同时设置上面两行的数据信息
控制浏览器缓存
//控制浏览器缓存
response.setHeader("expries", 1000*3600);//错误
response.setHeader("expries", System.currentTimeMillis() +1000*3600);//当前时间加上缓存时间
String data = "aaaaaaaaaaaa";
response.getWriter().write(data);
response常见应用
通过response实现请求重定向
请求重定向指:一个web资源受到客户端请求后通知客户端访问另外一个web资源,这称之为请求重定向
通过response.sendRedirect();
response.setStatus(302);
response.setHeader("location","/day/index.jsp");
//重定向方法
response.sendRedirect("/day.index.jsp"); //这句相当于上面两句
请求重定向能不用尽量不同,导致服务器会处理两次请求。
重定向特点:
1、浏览器会向服务器发送两次,意味着就有两个request和response
2、用重定向技术,地址栏会发生改变
同时调用getOutputStream和getWriter方法,会抛出异常。
Request
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户的这些信息。
getRequestURI();//返回请求行中的资源名部分
getRequestURL();//网络地址 http://开头
getQueryString()://放回请求行中的参数部分
getRemoteAddr();//返回发出请求的客户机的IP地址
getRemoteHost();//返回发出请求的客户机的完整主机名
getRemotePort();//返回客户机所使用的网络端口号
getLocalName();//返回WEB服务器的主机名
getLocalAddr();//返回WEB服务器的IP地址
getMethod();//得到客户机的请求方式
获取请求头
String headValue = request.getHeader("Accept-Encoding");
//request.getHeader("头名");
Enumeration e = request.getHeaders("Accept-Encoding");
//获取头名称
e = request.getHeaderNames();
获取数据
//获取数据,请求数据的时候,一般都要先检查再使用。
if(value != null && value.trim().equals("")){
//判断是否为空
}
//方式一:
request.getParameter(“变量名”);
//方式二:
Enumeration e = request.getParameterNames();
//再根据名得到数据
//方式三
String[] s = request.getParameterValues("变量名");//获取所有的值
//方式四
Map map<String,String[]> = request.getParameterMap();
//BeanUtils.populate(user, map);
//方式五
InputStream in = request.getInputStream();
//...
url后面跟中文字符,要先编码再提交。
request对象实现请求转发
应用场景:MVC设计模式
request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法啊可以实现请求转发
request对象同时 也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其他web资源处理。
setAttribute方法
getAttribute方法
removeAttribute方法
getAttributeNames方法
//mvc model javabean view(jsp) cotroller(servlet)
//请求转发,以及使用request域对象把数据带给转发资源
String data = "aaaaa";
request.getServletContext().setAttribute("data", data);
//request实现转发
request.getRequestDispatcher("/message.jsp").forward(request, response);
forward方法用于将请求转发到RequesDispatcher对象封装的资源。
如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常。
如果在调用forward方法之前向Servlet引擎的缓冲区写入内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区的内容将被情况。但是已经写入到HttpServletResponse对象中的响应头字段信息保持有效。
web工程中的各类地址(最好以斜杠("/")开头)
防盗链:
String referer = request.getHeader("referer");
if(referer == null || referer.startWith("http://localhost")){
response.sendRedirect("/day/index.jsp");
return;
}
Cookie
用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
会话过程中要解决的一些问题:每个而用户与服务器进行交互的过程中,各自回有一些数据,程序要想办法保存每个用户的数据;
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的session中取出为用户服务。
javax.setvlet.http.Cookie类用于创建一个Cookie,response接口也定义了addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。同样,request接口也定义了一个getCookies方法,它用于获取客户端提交的Cookie。
Cookie类的主要方法:
public Cookie(String name, String value)
setValue与getValue
SetMaxAge与getMaxAge //设置获取cookie的有效期,不调用这个方法默认有效期是浏览器的进程
setPath与getPath //设置获取cookie有效目录
setDomain与getDomain //设置域
getName
显示用户上次的访问时间
//获取用户的Cookie
Cookie[] cookies = request.getCookies();
for(int i = 0; cookies != null && i < cookies.length; i++){
if(cookies[i].getName().equals("lastAccessTime")){
long cookieValue = Long.parseLong(cookies[i].getValue());
Date date = new Date(cookieValue);
out.print(data.toLocaleString());
}
}
//给用户回送最新的访问时间
Cookie cookie = new Cookie("laseAccessTime",System.currentTimeMillis() + "");
cookie.setMaxAge(1 * 30 * 24 * 3600);//一个月
cookie.setPath("/day"); //设置cookie路径
reponse.addCookie(cookie); //回写cookie
一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)
一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie
浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB
如果创建一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储到磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大失效设为0则是命令浏览器删除该cookie。
注意:删除cookie时,path必须一致,否则不会删除。
Session
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象,注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问它其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
Session和Cookie的区别:Cookie是把用户的数据写给用户的浏览器,Session技术是把用户的数据写到用户独占的session。
Session对象由服务器创建,开发人员可以调用request对象的getSesion方法得到session对象。
//采用配置的方式摧毁session
<session-config>
<session-timeout>10</session-timeout>
</session-config>
//用代码的方式摧毁session
session.invalidate();
服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。
package xdp.gacl.session;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class SessionDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF=8");
response.setContentType("text/html;charset=UTF-8");
//使用request对象的getSession()获取session,如果session不存在则创建一个
HttpSession session = request.getSession();
//将数据存储到session中
session.setAttribute("data", "孤傲苍狼");
//获取session的Id
String sessionId = session.getId();
//判断session是不是新创建的
if (session.isNew()) {
response.getWriter().print("session创建成功,session的id是:"+sessionId);
}else {
response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
浏览器禁用Cookie后的session处理
解决方案:URL重写
response.encodeRedirectURL(java.lang.String url) 用于对sendRedirect方法后的url地址进行重写。
response.encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写
package xdp.gacl.session;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//首页:列出所有书
public class IndexServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
//创建Session
request.getSession();
out.write("本网站有如下书:<br/>");
Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();
for(Map.Entry<String,Book> me : set){
Book book = me.getValue();
String url =request.getContextPath()+ "/servlet/BuyServlet?id=" + book.getId();
//response. encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写
url = response.encodeURL(url);//将超链接的url地址进行重写
out.println(book.getName() + " <a href='"+url+"'>购买</a><br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
/**
* @author gacl
* 模拟数据库
*/
class DB{
private static Map<String,Book> map = new LinkedHashMap<String,Book>();
static{
map.put("1", new Book("1","javaweb开发"));
map.put("2", new Book("2","spring开发"));
map.put("3", new Book("3","hibernate开发"));
map.put("4", new Book("4","struts开发"));
map.put("5", new Book("5","ajax开发"));
}
public static Map<String,Book> getAll(){
return map;
}
}
class Book{
private String id;
private String name;
public Book() {
super();
}
public Book(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
BuyServlet
package xdp.gacl.session;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class BuyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
Book book = DB.getAll().get(id); //得到用户想买的书
HttpSession session = request.getSession();
List<Book> list = (List) session.getAttribute("list"); //得到用户用于保存所有书的容器
if(list==null){
list = new ArrayList<Book>();
session.setAttribute("list", list);
}
list.add(book);
//response. encodeRedirectURL(java.lang.String url)用于对sendRedirect方法后的url地址进行重写
String url = response.encodeRedirectURL(request.getContextPath()+"/servlet/ListCartServlet");
System.out.println(url);
response.sendRedirect(url);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ListCartServlet
package xdp.gacl.session;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class ListCartServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
List<Book> list = (List) session.getAttribute("list");
if(list==null || list.size()==0){
out.write("对不起,您还没有购买任何商品!!");
return;
}
//显示用户买过的商品
out.write("您买过如下商品:<br>");
for(Book book : list){
out.write(book.getName() + "<br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
浏览器第一次访问时,服务器创建Session,然后将Session的Id以Cookie的形式发送回给浏览器,response. encodeURL(java.lang.String url)方法也将URL进行了重写,当点击刷新按钮第二次访问,由于火狐浏览器没有禁用cookie,所以第二次访问时带上了cookie,此时服务器就可以知道当前的客户端浏览器并没有禁用cookie,那么就通知response. encodeURL(java.lang.String url)方法不用将URL进行重写了。
session对象的创建和销毁时机
session对象的创建时机
在程序中第一次调用request.getSession()方法时就会创建一个新的Session,可以用isNew()方法来判断Session是不是新创建的
//使用request对象的getSession()获取session,如果session不存在则创建一个
HttpSession session = request.getSession();
//获取session的Id
String sessionId = session.getId();
//判断session是不是新创建的
if (session.isNew()) {
response.getWriter().print("session创建成功,session的id是:"+sessionId);
}else {
response.getWriter().print("服务器已经存在session,session的id是:"+sessionId);
}
session对象的销毁时机
session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 设置Session的有效时间:以分钟为单位-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session
HttpSession session = request.getSession();
//手工调用session.invalidate方法,摧毁session
session.invalidate();