J2EE基础

一. servlet

1.servlet的基础

1.1 servlet的概念

  Servlet是javaWeb的三大组件之一 ,是线程不安全的组件 它属于动态资源,Servlet的作用是请求处理,服务器会把接受的请求交给servlet来处理,在servlet中通常需要:

  1. 接受请求数据
  2. 处理请求
  3. 完成响应

每个servlet都是唯一的,他们处理的请求是不同的
不同的servlet完成不同的功能

1.2 实现servlet的方式(由我们自己编写)

  1. 实现javax.servlet.Servlet接口
  2. 继承javax.servlet.GenericServlet类
  3. 继承javax.servlet.http.HttpServlet类
     通常我们会继承HttpServlet类来完成我们学习的Servlet
    Servlet的大多数方法必须由服务器(tomcat)来调用,大多数不由我们来调用servlet的对象也不由我们来创建 由服务器来创建。
1.2.1 init(ServletConfig servletConfig) 方法 :

在 Servlet 的生命期中,仅执行一次 init() 方法。它是在服务器装入 Servlet 时执行的。 可以配置服务器,以在启动服务器或客户机首次访问 Servlet 时装入 Servlet。 无论有多少客户机访问 Servlet,都不会重复执行 init()

1.2.2 service(HttpServletRequest request, HttpServletResponse response) 方法

 service() 方法是 Servlet 的核心。每当一个客户请求一个HttpServlet 对象,该对象的service() 方法就要被调用,而且传递给这个方法一个"请求"(ServletRequest)对象和一个"响应"(ServletResponse)对象作为参数。

1.2.3 destroy() 方法

destroy() 方法仅执行一次,即在服务器停止且卸装Servlet 时执行该方法。也就是在关闭服务器的时候就会自动结束

如图:
在访问servlet的时候就会自动调用init方法 和service()方法 当再次访问这个servlet的时候只会调用service()方法

1.3 如何应用浏览器调用servlet

  • 给servletz指定一个路径(让servlet与一个路径绑定在一起)servlet 3.0以后不会在web.xml中自动配置 需要自己编写或者 使用注解的方法
  • 如图:
    如 @WebServlet("/Aservlet")
    那么在浏览器访问的时候只需要
      http://localhost:8080/项目名/Aservlet使用注解:@@WebServlet("/Aservlet")
  • 或者使用web,xml来配置

web.xml

<servlet>
<servlet-name>servlet的名字</servlet-name>
<servlet-class>servlet的包名/servlet的名字</servlet-class>
</servlet>
//由两部分组成   必须成对出现
<servlet-mapping>
<servlet-name>浏览器访问的名字(也就是刚才注释的名字)</servlet-name>
<url-pattern>/浏览器访问的名字(也就是刚才注释的名字)(必须以斜杠开头  “/”)</url-pattern>
</servlet-mapping>

特性:

  1. 单例,一个类只有一个对象,可以存在多个servlet类
  2. 线程不安全,所以他的效率很高
    对象由我们创建 但是大部分由服务器调用

2. GenericServlet

2.1 GenericServlet概述:

  GenericServlet是servlet接口的实现类,我们可以通过集成GenericServlet来编写自己的Servlet。
一个servlet的配置信息与一个ServletConfig对应
在这里插入图片描述
通过ServletConfig可以获取本servlet的配置相关信息
API中:
String getServletName():获取的是中的内容
ServletContext getServletContext():获取servlet上下文对象
ServletContext是一个接口 实现类由tomcat提供
Enumeration getInitParameterNames(String name);//返回的是一个迭代器
String getInitParameter(String name);//通过名称获取指定初始化参数的值
下面通过在servlet中使用方法 来获取p1 p2的值
这是在servlet中配置的参数
使用String getInitParameter(String name);在这里插入图片描述
在这里插入图片描述

Enumeration getInitParameterNames(String name);
在这里插入图片描述
在这里插入图片描述
servlet在GenericServlet进行了包装 需要在初始的时候调用或者执行任何代码 需要在子类中重新定义 init();
注意:是无参数的 因为在GenericServlet中,进行了一个init();方法的定义 但是没有任何代码 在带有参数的public void init(ServletConfig servletConfig) 中调用了init(),这就解决了在子类中重写init会将父类的init覆盖的问题

3. HttpServlet

服务器在进行请求的时候会自动创建HttpServlet对象,HttpServlet 然后进行强转与servlet进行信息互换在这里插入图片描述

HttpServlet extends GenericServlet{
   void service(ServletRequest,ServiceResponse)--->生命周期方法
   强转两个参数为Http协议的相关类型
   调用奔雷的service(HttpServletRequset,HttpServletReponse)
}

void service(HttpServletRequset,HttpServletReponse)-->参数已经是Http协议相关的,使用起来更加方便
它会通过request得到当前请求的请求方法  例如:Post 或者  get
根据请求方式在调用doPose()   或   doGET()0

如图:
在这里插入图片描述

3.1servlet的细节

  1. Servlet与线程安全.
      因为一个类型的Servlet只有一个实例对象,那么就有可能会出现一个Servlet同时处理多个请求,Servlet不是线程安全的,这说明Servlet的工作效率会非常高,但是也存在线程安全问题。
      所以我们不应该在Servlet中随便创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作

解决的办法:

  • 不要在Servlet中创建成员,创建局部变量即可;
  • 可以创建无状态成员;
  • 可以创建有状态的成员,但是状态必须是只读的
  1. 让服务器在启动的时候就创建Servlet
    默认情况下,服务器会在某个Servlet第一次收到请求时创建它,也可以在web.xml中对servlet进行配置,使服务器启动时就创建Servlet
    在服务器启动的时候就创建Servlet 第一次创建花费的时间比较长 ------第一次代价
 <servlet>
    <description></description>
    <display-name>Bservlet</display-name>
    <servlet-name>Bservlet</servlet-name>
    <servlet-class>com.tjk.servlet.cn.Aservlet</servlet-class>
         
    <init-param>
       <param-name>p1</param-name><!--对应属性的名字  -->
       <param-value>v1</param-value><!--对应属性的值  -->
    </init-param>
    <init-param>
       <param-name>p2</param-name><!--对应属性的名字  -->
       <param-value>v2</param-value><!--对应属性的值  -->
    </init-param>
    <!--这个标签是控制服务器启动时创建servlet对象的顺序  必须是非负整数-->
    <!--小值先创建  大值后创建-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  • 中通配符的使用

 所谓的通配符就是 * 星号可以匹配任何URL前缀或后缀,使用通配符可以命名一个servlet绑定一组URL,eg:

  • "<url-pattern>/servet/*</url-pattern>" //路径匹配

  • "<url-pattern>*.do</url-pattern>" //扩展名匹配

  • "<url-pattern>/*</url-pattern> 匹配所有的URL
    匹配度越高优先级越高
    请注意:
    通配符要么为前缀,要么为后缀,不能出现在URL中间位置,也不能只有通配符
    通配符是一种模糊匹配URL的方式如果存在更具体的 url-pattern 那么匹配路径会去匹配更具体的

  • web.xml文件的继承性:(了解)
    每个完整的JavaWeb应用中都需有web.xml,且所有的web.xml有一个共同的父文件,在Tomcat的conf/web.xml
    这里面的所有内容相当于直接写入到每个项目的web.xml中了

    当servlet的请求不存在的时候,就会调用默认的这个Defaultservlet 页面显示404 优先级最低 没有任何servlet处理就会调用
    在这里插入图片描述
    当请求jsp页面的时候会自动调用jspServlet将动态资源转换为静态资源 然后通过response进行响应
    session的过期时间默认为30分钟
    在这里插入图片描述

3.2 ServletContext

与天地同寿
  当浏览器进行一个 http://localhost:8080/Day09/Bservlet请求时,后端会将路径与web.xml中的配置信息进行对比,判断应该响应哪个servlet,然后应用java反射机制classForName
一个javaWeb项目中只能有一个ServletContext对象

3.2.1. ServletContext概述:
   服务器会为每一个应用创建一个ServletContext对象
  • ServletContext对象的创建时在服务器启动时完成的
  • ServletContext对象的销毁是在服务器关闭时完成的
      ServletContext对象的作用是在整个Web应用的动态资源之间共享的数据!例如:在Aservlet中向ServletContext中保存一个值,可以在Bservlet中获取
    3.2.2 获取ServletContext

    在Servlet中获取ServletContext对象: - void init(ServletConfig config)中: ServletContext context=servletConfig.getServletContext(); 可以获取ServletContext对象 - 在GenericServlet或HttpServlet中获取ServletContext对象 GenericServlet类中有getServletContext()方法,所以可以直接用this.getServletContext()来获取; - HttpSession中的 getServletContext(); - ServletContextEvent 中getServletContext();
3.2.3 域对象的功能
<hr>
域对象:就是用来在多个servlet中传递数据的
        必须有存取数据的功能
ServletContext是JavaWeb四大域对象之一
- PageContext
- ServletRequest
- HttpSession
- ServletContext
 所有的域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储

数据。

  • void setAttribute(String name ,Object value):用来存储一个对象,也可以称之为存储一个域属性,如果多次调用该方法,并且设置同一个name值,就会覆盖上一次设置的value值。
  • Object getAttribute(String name):用来获取ServletContext中的数据,获取之前必须先进行存储
  • void removeAttribut(String name):用来溢出ServletContext中的域属性,如果name不存在,那么本方法什么都不做
  • Enumeration getAtributeNames():获取所有域属性de 名称
3.2.4 获取应用初始化参数
  • Servlet 也可以获取初始化参数,但它是局部的参数,也就是说,一个Servlet只能获取自己的初始化参数,不能获取别人的,即初始化参数只为一个Servlet准备
  • 可以配置公共的初始化参数,为所有Servlet而用,这些药ServletContext才能使用

web.xml 注意:这里的是在

<context-param>
    <param-name>name</param-name>
    <param-value>哈哈哈</param-value>
  </context-param>

servlet:如下:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		ServletContext  context=this.getServletContext();
		String value=context.getInitParameter("name");	
	    System.out.println(value);	
	}

console框如下:
在这里插入图片描述

3.2.5 利用ServletContext获取资源路径
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String ip="http://localhost:8080/Day09/Dservlet";	
		/*
		 * 获取的路径是带盘符的;
		 */
	
		String ip1=this.getServletContext().getRealPath("/index.jsp");
		//得到的是:ip1:F:\spring2\sts\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\Day09\index.jsp
		
		System.out.println("ip1:"+ip1);
		InputStream inputStream=new FileInputStream(ip1);
		//得到的是流对象: ip1转换为:java.io.FileInputStream@7e09740c
		
		System.out.println("ip1转换为:"+inputStream);
		//获取资源对象后  在创建流对象
	   InputStream input=this.getServletContext().getResourceAsStream("/index.jsp");
	   System.out.println("input:"+input);
	   
	   //获取当前路径下的所有资源的路径
	   //这里用set集合是因为java.util.HashSet强制转换为java.util.List
	    Set<String> s1=  this.getServletContext().getResourcePaths("/WEB-INF");
	    //得到的数据:[/WEB-INF/lib/, /WEB-INF/classes/, /WEB-INF/web.xml]
	    System.out.println(s1);
	}
3.2.6 页面访问次数案例

 所有的项目的资源被访问都必须给访问量进行累加
方法:
  创建一个int 类型的变量 ,用来保存访问量进行统计,然后将它保存在ServletContext域中

  • 最初时,ServletContext中没有保存访问量相关的属性,
  • 当本站第一次被访问时,创建一个变量,设置其值为1;保存在ServletContext中
  • 当以后访问时,就可以从ServletContext中获取这个变量,然后再其基础之上+1

    获取ServletContext对象,查看是否存在名为count的属性,如果存在说明不是第一次访问,如果不存在,说明是第一次访问
  • 第一次访问,调用Servletcontext的setAttribute传递一个属性,名为count值为1
  • 第二次以上访问,调用ServletContext的getAttributre方法回去原来的访问量,给访问量+1,在调用ServletContext的setAttribute方法完成设置
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		/*
		 * 网站访问量的统计案例
		 */
		 //创建servletContext对象
		ServletContext app=this.getServletContext();
		Integer count=(Integer)app.getAttribute("count");
		if(count==null) {
			app.setAttribute("count", 1);
			
		}else {
			app.setAttribute("count", count+1);
		}
		System.out.println("count:"+count);
		PrintWriter pw=response.getWriter();
		pw.print("<h1>"+count+"</h1>");
	}

页面访问如图所示:
在这里插入图片描述

4 获取类路径下的资源

获取类路径资源,类路径对一个javaWeb项目而言,就是/WEB-INF/classes和WEB-INF/lib下的每一个jar包
在这里插入图片描述

/*
有两种方法 
   第一种: 使用classLoader
         先得到class  在得到classLoader
         再调用其getResourceAsStream()得到一个inputStream
   第二种: 使用class

*/

ClassLoader c1=this.getClass().getClassLocder();//路径方式仅仅有一种  
InputStream input=c1.getResourceAsStream("路径");//(绝对路径/../....)

//使用Class
Class c=this.getClass();//路径方式有两种
//相对于当前 .class所在的目录
inputStream input=c.getResourceAsStream("相对路径");//(“a.txt”)
                                         /或者a.txt
//相对classes下!
String s=IOUtiles.toString(input);//读取输入流的内容,转换为字符串返回

二. request 和 response

服务器处理流程:
服务器每次收到请求时,都会为这个请求开辟一个新的线程
服务器会把客户端的请求数据封装到request对象中,request就是请求数据的载体
服务器还会创建response对象,这个对象与客户端连接在一起,它可以用来向客户端发送响应
在这里插入图片描述


1. response:其真实类型是**HttpServletResponse

HttpServletResponse---------->它是和http协议有关的
ServletResponse------------->它是和协议没有关系的
http协议中:包含:

  • 状态码
200成功
302重定向
404客户端错误(访问资源不存在)
500服务器出错

方法:
sendError(int sc)(发送失败状态码的方法)
sendError(int sc ,String msg)(发送失败状态码的方法+错误信息)
setStatus(int sc)(成功的方法)
头:(是一对键值对)
响应头(头名) 响应头的值(头值)
Content-Type:text/html;charset=utf-8
案例:
发送404

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	    response.sendError(404, "已经访问到_404_Practice但是不给你看滴滴滴");
	}

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200120215152726.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NzU5NjY0,size_16,color_FFFFFF,t_70

1.1 响应头 Content-Type Refresh Location等等

头就是一个键值对,可能会存在一个头(一个名称,一个值),也可能存在一个头(一个名字,多个值)

setHeader(String name, String value)适用于单值得响应头
addHeader(String name, String value)适用于多值的响应头
setIntHeader(String name, int value)适用于单值得int类型的响应头
addIntHeader(String name, int value)适用于多值int 类型的响应头
setDateHeader(name, long date)适用于单值得毫秒类型的响应头
addDateHeader(String name, long date)适用于多值的毫秒类型的响应头

eg: response.setHeader(“aaa”,“AAA”);
案例:
① 发送302,设置location头,完成重定向
② 定时刷新,设置refresh头—>可以理解为 定时的重定向
③ 禁用浏览器缓存,Cache-Control (no-cache)、pragma(no-cache)、expires(-1)
重定向:
在这里插入图片描述

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	   	response.getWriter().print("Cservlet激发了");
	   	response.setHeader("Location", "/Day10/Bservlet");//第一步:设置location  和跳转的URL
	   	response.setStatus(302);//第二部发送  响应码
	   	response.getWriter().print("激发完毕");
	}

第二种快捷的重定向(直接跟要重定向的链接URL):

response.sendRedirect("http://www.baidu.com");//直接跟要重定向的链接URL

定时刷新:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		PrintWriter printWriter=response.getWriter();
		printWriter.print("only has five seconds   ");
		response.setHeader("Refresh", "5,URL=/Day10/Eservlet");//标志头是refresh   5:五秒  URL是刷新的目的链接

	}

禁用浏览器缓存:(这个东西在html的新建标签页上有可以看到 只是设置的地方不一样)

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: 禁止缓存案例").append(request.getContextPath());
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("pragma", "no-cache");
		response.setDateHeader("expires", -1);
	}

标签可以代替响应头:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

响应体:通常是Html 也可以是图片!
response的两个流: 两个流不能同时使用

ServletOutputStream用来向客户端发送字节数据
PrintWrite:用来向客户端发送字符数据,需要设置编码

字节流是万能的,但是字符流不是的
例子:
字符流的:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//response.getWriter().append("Served at:ServletOutputStream io测试 ").append(request.getContextPath());
		ServletOutputStream output=response.getOutputStream();
		String itString="这是ServletOutputStream流的字符流对象";
		byte[] bytes=itString.getBytes();
		response.getOutputStream().write(bytes);
	}

发送图片数据 (必须是字节流的)

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException  {	
		FileInputStream input=new FileInputStream("F:/tjk.png");
		byte[] bytes=IOUtils.toByteArray(input);//(读取字符流中的数据到字符数组中去)
		response.getOutputStream().write(bytes);
	}

上面发送图片案例必须有:jar commen-io的包
链接地址:commen-io jar

2. request–>封装了客户端所有的请求数据

请求行
请求头
空行
请求体(GET没请求体)

  • 获取常用信息
    获取客户端IP 案例:封IP String getRemoteAddr();
    请求方式 request.getMethod();可能是POST 或者GET

  • 获取请求头

    String getHeader(String name)适用于单值头
    int getIntHeader(String name )适用于单值int 类型的请求头
    long getDateHeader(String name),适用于单值毫秒类型的请求头
    Enumeration getHeaders(String name),适用于多值请求头
    • 案例:
    1. 通过User-Agent识别用户浏览器类型
    2. 防盗链:如果请求不是通过本站的超链接发出的,发送错误状态码404

    案例一:

     protected void doGet(HttpServletRequest request, HttpServletResponse response)
     		throws ServletException, IOException {
     	// TODO Auto-generated method stub
     	response.getWriter().append("Served at: ").append(request.getContextPath());
     	String addrString = request.getRemoteAddr();// 获取访问的ip地址
     	System.out.println(addrString);
    
     	System.out.println("请求方式:" + request.getMethod());
    
     	System.out.println("User-gent:" + request.getHeader("User-Agent"));
     	//为了不区分大小写  但contains中必须写的书小写
     	if (request.getHeader("User-Agent").toLowerCase().contains("firefox")) {
     		System.out.println("是火狐啊");
     	} else {
     		System.out.println("不是啊");
     	}
     }
    
  • 获取请求URL

    String getScheme():获取协议
    String getServerName()获取服务器名
    String getServerPort()获取服务器端口
    String getContextPath()获取项目名
    String getServletPath()获取Servlet路径
    String getQueryString()获取参数部分,即问号后面的内容
    String getRequestURL();获取请求URL,等于项目名+Servlet路径
    String getRequestURL()获取请求URL,等于不包含参数的整个请求路径
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		System.out.println("协议名:"+ request.getScheme());
		System.out.println("获取服务器名"+ request.getServerName());
		System.out.println("获取服务器端口"+ request.getServerPort());
		System.out.println("获取项目名"+request.getContextPath());
		System.out.println("获取servlet路径"+request.getServletPath());
		System.out.println("获取参数部分"+request.getQueryString());
		System.out.println("获取请求URI"+request.getRequestURI());
		System.out.println("获取请求的URL"+request.getRequestURL());
		
	}

运行结果:
在这里插入图片描述
在这里插入图片描述

案例二:

servlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		String  referer=request.getHeader("Referer");//获取请求路径  
		    
		System.out.println("referer: "+referer);
		if(referer==null||referer.toLowerCase().contains("localhost")) {
			System.out.println("本地请求");
		}else {
			System.out.println("非本地请求" );
			
		}
		
	}

html:

<body>
<a href="/Day10/ACservlet">222</a>
</body>

3 获取请求参数

获取请求参数,请求参数是由客户端放给服务器的!有可能是在请求体(post) 有可能是在URL之后 (GET)

String getParameter(String name);获取指定名称的请求参数值,适用于单值请求参数
Enumeration getParamterName();获取所有的请求参数的名称
Map<String,String> getParameterMap()获取所有请求参数,其中Key为参数名,value为参数值

ADservlet:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		String  name=request.getParameter("name");
		String password=request.getParameter("password");
		String[] hobby=request.getParameterValues("hobby");
		System.out.println(name+"--"+password+"---"+hobby);
	}

B.html

<h2>请求参数</h2>
<form action="/Day10/ADservlet" method="post">
 姓名:<input type="text" name="name">
密码:<input type="text" name="password">
爱好:<input type="checkbox" name="hobby" value="篮球">篮球
    <input type="checkbox" name="hobby" value="足球">足球
    <input type="checkbox" name="hobby" value="羽毛球">羽毛球
    <input type="submit" value="提交">
</form>

4.请求转发和响应重定向

在这个过程中实际只创建了一个request和response对象
在这里插入图片描述

RequestDispatcher rd=request.getRequestDispatcher("/AAservlet");参数是被转发或被包含的servlet路径
rd.forward(request, response);//请求转发
rd.include(request, response);//请求包括

有时一个请需要多个Servlet写作才能完成 ,所以需要在一个servlet跳转到另一个servlet

  • 一个请求夸多个servlet,需要使用转发和包含
  • 请求转发:由下一个servlet完成响应体,当前servlet可以设置响应头(留头不留体)
  • 请求包含:由两个servlet共同完成响应体(都留)
  • 无论是请求转发还是请求包含,都在一个请求范围内!使用同一个request和response

请求转发:
OneServlet

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("这是oneServlet");
		response.setHeader("AAA", "你妹啊"); //设置响应头
		response.getWriter().print("Hello OneServlet");//设置响应体  响应体的最大容量24K内部缓存机制限定的    这个响应体会被覆盖   不会出现
		request.getRequestDispatcher("/TwoServlet").forward(request, response);//请求转发
		
	}

TwoServlet

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//response.getWriter().append("Served at: ").append(request.getContextPath());
		response.getWriter().print("TwoServlet---xixi");
        String s1=	response.getHeader("AAA");//这个东西放到哪个对象中就从那个对象去出来
         System.out.println(s1);
		}

请求包含:
IncludeOneServlet

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("这是oneIncludeServlet");
		response.setHeader("AAA", "你妹啊"); //设置响应头
		response.getWriter().print("Hello OneServlet");//设置响应体  响应体的最大容量24K   此处的响应体不会被覆盖
		request.getRequestDispatcher("/IncludeTwoServlet").include(request, response);//请求转发
	}

IncludeTwoServlet

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().print("IncludeTwoServlet---xixi");
        String s1=	response.getHeader("AAA");
         System.out.println(s1);
	}

请求包含中第一个servlet的响应体不会被覆盖掉 都会显示出来
请求转发第一个servlet的响应体会被覆盖

5. request 域

有三个域:request session application 都有如下所有的方法:
void setAttribute(String name,Object value)
Object getAttribute(String name)
void removeAttribute(String name)
同一个请求范围内使用 requset.setAttribute() request.getAttribuye()来传值
在这里插入图片描述
请求转发和重定向的区别 :

  • 请求转发是一个请求一次响应,而重定向是两次请求,两次响应
  • 请求转发地址链不发生变化,而重定向会显示后一个请求的地址
  • 请求转发只能转发到本项目其他servlet,而重定向不只能重定向到本项目的其他servlet,还能重定向到其他Servlet
  • 请求转发是服务端行为,只需给转发的servlet路径,而重定向需要给出requestURI,即包含项目名

6. 路径

在这里插入图片描述

三. jsp基础

1. jsp的作用:

  • Servlet:
    缺点: 不适合设置html响应体,需要戴昂的response.getWrite().print(“html”)
    优点:动态资源,可以编程
  • html:
    缺点:html是静态页面,不能包含动态信息
    优点:不用为输出html标签而发愁
  • jsp
    优点:在原有的html的基础上添加java脚本,构成jsp页面

2. jsp和servlet的分工

  • jsp:
    作为请求发起页面:例如显示表单 超链接
    作为请求结束页面,例如显示数据
  • servlet
    作为请求中处理数据的环节

3. jsp的组成

  • jsp=html+java脚本+jsp标签(指令)
  • jsp中无需创建即可使用的对象一共有九个,被称之为九大内置对象,例如request对象,out对象
  • java脚本:
    <%…%>:java 代码片段,用于定义java语句 方法里面些什么这里就可以写什么
    <%=…%>:java表达式,用于输出,用于输出一条表达式(或变量)的结果

    <%!..%>声明:用来创建类的成员变量和成员方法(基本不用,但容易被考)

在这里插入图片描述

4. jsp原理

jsp其实是一种特殊的Servlet

  • 当jsp页面第一次被访问时,服务器会把jsp编译成java文件(这个java文件其实是一个Servlet类)

  • 然后再把Java编译成.class文件然后创建该类对象

  • 最后调用它的service()方法第二次氢气统一jsp时,直接调用service方法

    1. 在tomcat的work目录下可以找到哦啊jsp 对象的java源代码
    2. 查看jsp对象的java文件

      java脚本
      html

    在jsp页面上java代码编译后还是原样,但是 html代码会变为字符串用 out.write(“…”)输出
    在这里插入图片描述

    • jsp注释
      <%-- …–%>当服务器把jsp编译成java文件时已经忽略了注释部分
      <%–…--%>这个标签在查看源代码时不会显示
      <!- -->这个标签会在查看源代码的时候进行显示 并且会执行其中的代码 只是不进行显示而已

四. Cookie

cookie不能跨浏览器

1. Http协议与Cookie

  • Cookie是HTTP协议制定的 ,先由夫妻保存Cookie到浏览器,再下次浏览器请求服务器时把上一次请求得到Cookie再归还给服务器
  • 由服务器创建保存到哭护端浏览器的一个键值对,服务器保存Cookie的响应头:Set-Cookie:aaa=AAA; Set-Cookie:bbb=BBB;
  • 当浏览器请求服务器时,会把该服务器保存的Cookie随请求发送给服务器,浏览器归还Cookie的请求头 Cookie:aaa=AAA;bbb=BBB
  • Http协议规定(保证不给浏览器太大压力)
    1. 一个Cookie最大是4KB
    2. 一个服务器最多向一个浏览器保存20个Cookie
    3. 1个浏览器最多可以保存300个Cookie
    • 浏览器大战:因为浏览器竞争很激烈,所以很多浏览器都会在一定范围内违反HTTP的对顶,但是也不会让一个Cookie的值为4GB

2. Cookie的用途:

  • 服务器使用Cookir来追踪客户端状态
  • 保存购物车(购物车中商品不能使用request保存,因为他是一个用户想服务器发送的多个请求信息)
  • 显示上次登录名(也是一个用户多个请求)

3. JavaWeb中使用Cookie

  • 原始方式
    使用response发送Set-Cookie响应头
    使用request获取Cookie请求头
    • 便捷方式(精通)
      使用response.addCookie()方法想浏览器保存Cookie
      使用request.getCookies()方法获取浏览器会还Cookie

      设置Cookie
      在这里插入图片描述
      得到Cookie
      在这里插入图片描述

4. Cookie详解

  • Cookie不只有name和value两个属性
  • Cookie的maxAge:Cookie可保存的最大时长,以秒为单位,例如cookie.setMaxAge(60)表示这个cookie会被浏览器保存到硬盘上
    1. maxAge>0 浏览器会把Cookie保存到客户机硬盘上,有效时长为maxAge的值决定
    2. maxAge<0 Cookie 只在浏览器内存中存在,当用户关闭浏览器时,浏览器进程结束 相应的Cookie也就死亡
    3. maxAge=0 浏览器会马上删除这个Cookie
    • Cookie的path
      1. Cookie的path并不是设置这个Cookie在客户端的保存路径
      2. Cookie的path由服务器创建Cookie时设置
      3. 当浏览器访问服务器的某个路径时,需要归还那些Cookie给服务器呢?这由Cookie的path决定
      4. 浏览器访问服务器的路径,如果包含 Cookie的路径,那么就会归还那个Cookie
      • Cooke 的path默认值,当前访问路径的父路径 降一级
        例如: /day10/jsp/a.jsp响应Cookie那么这个cookie的路径就为/day10/jsp/
      • Cookie的domain(域)
        domain用来指定Cookie的域名,当多个二级域中共享Cookie时才有用
        例如:www.baidu.com zhidao.baidu.com tjk.baidu.com 之前共享Cookie值可以使用domain
        1. 设置domain为 cookie.setDomain(".baidu.com")
        2. 设置path为cookie.setPath("/");

五. HttpSession

1. HttpSession概述:

  • HttpSession是由JavaWeb提供的,用来会话跟踪的类,Session是服务器对象,保存在服务器端
  • HttpSession是servlet三大域对象之一,所以他也是Setttribute getAttribute removeAttribute
  • HttpSession底层依赖Cookie 或是url重写

2. HttpSession的作用

  • 会话范围:会话范围是某个用户从首次访问服务器开始,到该用户关闭浏览器结束
    会话:一个用户对服务器的多次连贯性请求!所谓连贯性请求,就是该要不过户多次请求中间没有关闭浏览器
    • 服务器会对每个客户端创建一个session对象,session就好比客户在服务器端的账户,他们被服务器保存到一个Map中,这个Map被称为session缓存
    1. Servlet中得到session对象:HttpSession session=request.getSession();
    2. jsp中的得到session对象:session是jsp内置对象,不用创建就可以直接使用
  • session域相关方法
    1. void setAttribute(String name,Object value);
    2. Object getAttribute(String name)
    3. void removeAttribute(String name)

3. HttpSession原理

  • request.getSession()方法:
    1. 获取Cookie中的sessionId;
      a. 如果sessionId不存在,创建session,把session保存起来,把新创建的sessionId保存在Cookie中
      b. 如果sessionId存在,通过sessionId查找session对象,如果没哟查找到,创建session把session保存起来,把创建的sessionId保存到Cookie中
      c.如果sessionId存在,通过sessionId查找到了session对象,那么就不会在创建session对象
    • 返回session
      如果创建了新的session,浏览器会得到一个包含sessionId的cookie,这个cookie的生命为-1,即只在浏览器内存中存在,如果不关闭浏览器,那么Cookie一直存在
      如果在服务器不关闭的情况下,将浏览器关闭了 那么将会创建新的session 以前的那个sessionId 在最大有效时间过去后自动销毁
      下次请求时,再次执行request.getSession()方法时,因为可以通过Cookie中的sessionId找到session对象,所以与上一次请求时获取的session是一个对象
      服务器不会马上给你创建session,在第一次获取session时,才会创建!
      request.getSession(flase); 如果session缓存中(如cookie不存在),不存在session,那么返回null,而不会创建session对象
      request.getSession(true);//会返回session对象
      request.getSession();//会返回session对象

4. HttpSession其他方法

  • String getId(),获取sessionId;
  • int getMaxInactiveInterval();获取session可以是最大不会动时间(秒),默认为30分钟,当session在30分钟内没有使用,那么Tomcat会在session池中移除
  • void invalidate(),让session失效
  • boolean isNew();查看session是否为新的

5. web.xml中配置session的的最大不活动时间

<session-config>
  <session-timeout>30</session-timeout>
  </session-config>

6. URL重写

就是把所有的页面的路径都使用response.encodeURL("…")处理一下;
原理是:将Cookie变为参数传递

  • session依赖于Cookie,目的是让客户端发出请求时归还sessionId,这样才能找到对应的session
  • 如果客户端禁用了Cookie,那么就无法得到sessionId,那么session也就无用了
  • 也可以使用URL重写替代Cookie
  1. 让网站的所有超链接,表单中添加一个特殊的请求参数,即sessionId
  2. 这样服务器就可以通过获取请求桉树得到sessionId,从而找到sessionId对象
  3. response.encodeURL(String url)
<a  href="/Asession;JSESSIONID=<%=session.getId() %>">点击这里</a>
<a  href="/Asession;JSESSIONID=<%=session.getId() %>">点击这里</a>
<a  href="/Asession;JSESSIONID=<%=session.getId() %>">点击这里</a>
<%=response.encodeURL("/Asession") %>>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值