zoukankan      html  css  js  c++  java
  • Servlet、Cookie、Session

    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程序向浏览器输出数据),需要两个步骤:

    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的安装路径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配置一些初始化参数。
    在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();
    
  • 相关阅读:
    Spring MVC学习03页面跳转
    Spring Boot学习07配置加载顺序
    Spring MVC学习01从空白Maven项目搭建环境
    Spring MVC学习05JSON序列化
    剑指Offer 44 数字序列中某一位的数字
    Spring MVC学习06异常解析器
    MSSQL·查看DB中所有表及列的相关信息
    MSSQL·查询数据库中所有索引的相关信息
    MSSQL·最长输出长度限制之解决方案
    .Net Core·热加载的实现及测试
  • 原文地址:https://www.cnblogs.com/changzuidaerguai/p/7209209.html
Copyright © 2011-2022 走看看