在劫

吾生也有涯,而知也无涯 。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
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文件中,建议将此配置放在\conf\Catalina\localhost目录中

文件名任意.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:\sina\mail"/>
</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程序向浏览器输出数据),需要两个步骤:

  1. 编写一个Java类,实现servlet接口
  2. 把开发好的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>

步骤:

  1. 在tomcat中新建一个myweb应用,然后在web应用中新建一个WEB-INF文件,并新建classes和lib文件夹,web.xml配置文件
  2. 将servlet-api.jar包导入到classpath路径:set classpath=%classpath%;
  3. 编译class文件
  4. 启动服务器访问

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的完整类名。
一个元素用于映射一个已注册的Servlet的一个对外访问路径,它包含两个子元素:,分别用于指定Servlet的注册名称和Servlet的对外访问路径。

<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的注册名。
在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方法。
如果在元素中配置了一个元素,那么WEB应用程序在启动时,就会装在并创建Servlet的实例对象,以及调用Servlet实例对象的init()方法。

<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文件中找不到匹配元素的URL,他们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet不处理的访问请求。
在Tomcat的安装路径\cong\web.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配置一些初始化参数。
在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 = " \u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97
\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66
\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1
\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b
\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e
\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761
\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c
\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b
\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636
\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4
\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750
\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f
\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1
\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d
\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834
\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce
\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5
\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5
\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6";
		
		
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());

常见中文编码

 \u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97
\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66
\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1
\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b
\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e
\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761
\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c
\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b
\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636
\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4
\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750
\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f
\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1
\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d
\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834
\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce
\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5
\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5
\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6

发送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();
posted on 2017-07-20 08:34  长嘴大耳怪  阅读(396)  评论(0编辑  收藏  举报