Servlet
1、HTTP协议
1.1、交互流程
建立连接----->请求数据------->响应数据------>关闭连接(HTTP1.1版本后不再立即关闭)
1.2、请求格式结构
请求头:请求方式、请求的地址(get方式的请求数据封装在地址栏里)和HTTP协议版本
请求行:消息报头,一般来说明客户端要使用的一些附加信息
空行:位于请求行和请求数据之间,空行是必须的
请求数据(请求主体):非必须(例如:get无)
1.3、get和post请求方式的区别和联系
注意:get和post实际上都是TCP连接,所以本质上来说是一样的
**get:**请求参数位于URL中,所以说就不安全,但由于请求地址中URL的长度是有限制的,所以get请求数据量不宜太大
**post:**请求参数位于请求数据中,安全,请求数据量大小无限制
1.4、响应格式结构
响应行(状态行):HTTP版本、状态码、状态信息
响应头:消息报头,客户端使用的附加信息
空行:响应头和响应实体之间的,必须的
响应实体:正文,服务器返回给浏览器的信息
1.5、响应状态码含义
HTTP状态码由3个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。
分类 | 描述 |
---|---|
“1” | 信息,服务器收到请求,需要操作者继续执行 |
“2” | 成功,操作被成功接收并处理 |
“3” | 重定向,需要进一步的操作以完成请求 |
”4“ | 客户端错误,请求包含语法错误或无法完成请求 |
”5“ | 服务器错误,服务器在处理请求的过程中发生了错误 |
2、Tomacat服务器
2.1、闪退问题
闪退问题一般是因为JDK环境变量配置有问题,如果重新配置正确后,还是闪退,使用:
在bin\startup.bat文件中的第一行前面加入:
SET JAVA_HOME=(JDK目录)
SET CATALINA_HOME=(解压后Tomacat的目录)
同样要正常关闭在bin\shutdown.bat第一行也添加如上内容。
2.2、server.xml文件讲解
文件核心组件结构:
热部署:默认是冷部署也就是你的项目每次更改都要重启tomacat服务器,而进行了热部署你不用每次都重启服务器!!!在Host里面配置Context进行热部署
<Context path="/Pet" reloadable="true" docBase="F:/PetWeb" /> //热部署
这句话的理解:
path:指定访问该Web应用的URL入口。
docBase:指定Web应用的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性的相对路径,如果Web应用采用开放目录结构,则指定Web应用的根目录,如果Web应用是个war文件,则指定war文件的路径。(指定项目所在地址)
reloadable:如果这个属性设为true,tomcat服务器在运行状态下会监视在WEB-INF/classes和WEB-INF/lib目录下class文件的改动,如果监测到有class文件被更新的,服务器会自动重新加载Web应用。
热部署缺点:冷部署的话,刚开始你启动的话,默认是去加载webapps目录下的项目,你即使该目录下没有项目文件,服务器也并不会报错,但是你如果进行了热部署,服务器就会按照你给定的docBase项目路径去找,如果你项目删掉了,则此时服务器会报错!!! 、
注意:进行热部署的项目如果你要删除的话,记得也要将服务器下的server.xml下的Context热部署配置一并删除。
3、Servlet
3.1、运行流程
浏览器发送请求到服务器,服务器根据请求URL地址中的URI信息在tomacat的webapps目录下找到对应的项目文件夹,然后在web.xml中检索对应的servlet,找到后调用并执行Servlet。
3.2、生命周期
(1)、servlet什么时候加载进内存:当用户发起第一次请求的时候,tomacat会根据用户请求的url路径,在webapps下找到配置文件,找到对应servlet类路径,根据servlet类路径去找,然后此时servlet加载进内存。
(2)、init方法:只有在servlet第一次被加载进内存的时候调用一次!
(3)、servlet什么时候会被销毁:服务器关闭,servlet被销毁然后自动调用destroy方法
(4)、生命周期起始有两种:1、从第一次调用(即用户第一次请求调用init)到服务器关闭
2、如果Servlet在web.xml中配置了load-on-startup,生命周期为从服务器启动到服务器关闭,即init此时在服务器启动的时候调用。
(5)、Service方法、doGet、doPost方法
Service方法:可以处理get/post方式的请求,如果servlet中有Service方法,会优先调用service方法对请求进行处理。
doGet方法: 处理get方式的请求
doPost方法:处理post方式的请求
**注意:**如果在重写的service方法中调用了父类的service方法(super.service(req,resp)),则service方法处理完后,会再次根据请求的方式响应doGet和doPost方法,这也就要求此时我们必须重写相应的doGet和doPost方法才行(否则出现405)。所以一般情况下我们是不在重写的service方法中调用父类的service方法的,避免出现405错误
3.3、request对象
作用:request对象中封存了当前请求的所有请求信息
使用:获取请求头数据
获取请求行数据
获取用户数据
//获取请求行数据
//获取指定的请求行信息
String value=req.getHeader("aaa");
System.out.println(value);
//获取所有请求行的键的枚举
Enumeration e=req.getHeaderNames();
while(e.hasMoreElements){
System.out.println(e.nextElement());
}
注意:1、request,response对象均由tomacat服务器创建,并作为实参传递给处理请求的servlet的service方法
2、getParameter获取用户提交数据(利用键值),但是对于一个键对应多值的情况(爱好fav这个键你可能有多个值)要用getParameterValues(键名)来得到一个字符串数组,遍历得到该键所有值。
3、获取所有用户请求数据的键的枚举集合------req.getParameterNames()
3.4、response对象
作用:用来响应数据到浏览器的一个对象
使用:设置响应头
resp.setHeader(String name,String value);//在响应头中添加响应信息,但是相同键会覆盖
resp.addHeader(String name,String value);//在响应头中添加响应信息,但是相同键不会覆盖
设置响应状态码
resp.sendError(405,"this Method is not supported");//自定义405响应状态码
设置响应实体
resp.getWriter().write("this is resp study");
如果响应实体中有中文,我们需要设置响应编码格式!!!在响应头中添加浏览器能够识别的键content-type
//以下两种方式效果一样的!
//第一种
resp.setHeader("content-type","text/html;charset=utf-8");
//第二种
resp.setContentType("text/html;charset=utf-8");
注意:设置如果是text/html,会将你的响应实体内容按照html方式输出(有标签会解析)
设置如果是text/plain表示普通文本输出,你响应实体的内容原样输出(标签不会解析)
3.5、请求中文乱码问题解决
方式一:String的方式进行数据重新编码,不需要管是post还是get方式提交的数据都可以用此种方式
//通过String的方式进行数据重新编码,浏览器默认iso8859-1,服务器默认utf-8
String uname=req.getParameter("uname");
uname=new String(uname.getBytes("iso8859-1"),"utf-8");//得到正确中文请求数据
缺点:假如请求参数里有很多中文,每个参数都要转编码格式获取正确数据比较麻烦
方式二:使用公共配置(分提交方式是get还是post)
//get方式
步骤一:req.setCharaterEncoding("utf-8");
步骤二:在tomacat的conf目录中修改server.xml文件,在Connecter标签中增加属性userBodyEncodingForURI="true"
//post方式
req.setCharaterEncoding("utf-8");
3.6、请求转发
作用:使用请求转发联动servlet,减少逻辑代码冗余,明确每个servlet职责
req.getRequestDispatcher("要转发的地址").forward(req,resp);
地址:相对路径,直接书写servlet的别名即可,此处地址也可是一个jsp
特点:一次请求
浏览器地址栏信息不改变,极容易造成用户不断点击刷新频繁提交数据!!!
注意:请求转发后直接return结束即可!!!
3.7、request对象作用域(一次请求内不同servlet数据共享)
作用:使用request对象的作用域,实现数据从一个servlet流转给另外一个servlet,解决了一次请求内的不同servlet的数据共享问题。
使用:在请求转发前,通过**req.setAttribute(Object name,Object value);存储数据到req,再通过请求转发将req发到另一个servlet,在另外一个servlet中使用req.getAttribute(Object name)**来获取之前的servlet封存好的数据,实现了不同servlet之间的数据共享!!!
作用域:基于请求转发,一次请求中的所有servlet共享
特点:服务器创建
每次请求都会创建
生命周期为一次请求
注意:使用Request对象进行数据流转,数据只在一次请求内有效。
3.8、重定向
重定向的引入:
如果当前的请求,Servlet无法进行处理怎么办?
如果使用请求转发,造成表单数据重复提交怎么办?
使用:
response.sendRedirect("路径");
//本地路径为:uri(地址栏中端口号和?之间的)
//网络路径:定向资源的URL信息
特点:
两次请求,即两个request对象
浏览器地址栏信息改变避免表单数据重复提交
使用重定向情况:
如果请求中有表单数据,而数据又比较重要,不能重复提交,建议使用重定向。
如果请求被servlet接收后,无法进行处理,建议使用重定向定位到可以处理的资源。
3.9、Cookie学习
作用:解决了发送的不同请求的数据共享问题
使用:
//创建Cookie对象
Cookie c=new Cookie(String key,String value);
//响应Cookie信息给客户端
resp.addCookie(c);
注意:一个Cookie对象存储一条数据。多条数据,可以创建几个Cookie对象进行存储
特点:
浏览器端的数据存储技术
存储的数据声明在服务器端
临时存储:存储在浏览器的运行内存中,浏览器关闭即失效!!
定时存储:设置了Cookie的有效期,存储在客户端的硬盘中,在有效期内符合路径要求的请求都会附带该信息!!!
eg:设置某个信息3天内有效
Cookie c=new Cookie(“key”,“bjsxt”);
c.setMaxAge(3乘24乘3600);
resp.addCookie©;
删除Cookie:可以这样设置c.setMaxAge(0);
默认cookie信息存储好之后,每次请求(访问所有servlet)都会附带,除非设置哪些请求需要带(即设置有效路径)!!
c.setPath("/test/abc");//只有此路径的请求中(request对象中)才含有c封装好的cookie信息
获取cookie信息:
Cookie[] cks=req.getCookies();
if(cks!=null){//判断避免空指针异常
for(Cookie c:cks){
String key=c.getName();
String value=c.getValue();
}
}
3.10、session技术(一个用户的不同请求处理的数据共享)
1、原理:用户第一次请求,服务器会创建一个session对象给此用户,并将该session对象的JSESSIONID使用Cookie技术存储到浏览器中,保证用户的其它请求能够获取到同一个session对象,也保证了不同请求能够获取到共享的数据。
2、特点:存储在服务器端
服务器进行创建
依赖Cookie技术
默认存储时间是30分钟(指你30分钟内未发起新的请求,如果你30分钟内发起了新的请求则重新计时)
2、使用:
创建session对象/获取session对象
HttpSession hs=req.getSession();
这句话既是创建,也是获取,当req中含有session的标识符(JSESSIONID)就是获取,当没有session的标识符也就是JSESSIONID就创建新的session对象,并将其JSESSIONID作为cookie数据存储到浏览器内存中。如果session对象失效了,也会重新创建一个session对象,并将其JSESSIONID存储在浏览器中。
//创建session对象/获取session对象
HttpSession hs=req.getSession();//既是创建,也是获取,当req中含有session的标识符(JSESSIONID)就是获取,当没有session的标识符也就是JSESSIONID就创建新的session对象,并将其JSESSIONID作为cookie数据存储到浏览器内存中
String ID=hs.getId();
注意:JSESSIONID存储在Cookie的临时存储空间中,浏览器关闭即失效。
4、设置session的存储时间:
hs.setMaxInactiveInterval(多少秒);
注意:在指定的时间内session对象没有被被使用则销毁,如果使用了则重新计时
5、设置session强制失效:
hs.invalidate();//用户点了退出的情况我们销毁session
6、存储和获取数据:
存储:hs.setAttribute(String name,Object value);
获取:hs.getAttribute(String name) 返回的数据类型为Object
注意:存储的动作和取出的动作发生在不同的请求中,但是存储要先与取出!!!
HttpSession hs=req.getSession();
//存储数据
hs.setAttribute("name",张三);
//在另外一个请求中去取session数据
HttpSession hs=req.getSession();
hs.getAttribute("name");
7、session失效处理:
方式一:
将用户请求中的JSESSIONID和后台获取到的session对象的JSESSIONID进行比对,如果一致,则session没有失效,如果不一致则证明session失效了。此时重定向到登录页面,让用户重新登录。
方式二:
当然也可以从数据的角度去判断,如果我们拿到的用户数据变为空了,那么session肯定失效了。此时重定向到登录页面,让用户重新登录。
3.11、ServletContext对象(不同用户的数据共享问题)
1、原理:
ServletContext对象由服务器进行创建,一个项目只有一个对象。不管在项目的任意位置进行获取得到的都是同一个对象,那么不同用户发起的请求也就是同一个对象了,该对象由用户共同拥有。
2、特点:
服务器进行创建
用户共享
一个项目只有一个
**3、生命周期:**服务器启动到服务器关闭
**4、应用实例:**网页访问次数计数器
3.12、ServletConfig对象(解决如何获取在web.xml中给每个servlet单独配置的数据)
1、作用:
ServletConfig对象是Servlet的专属配置对象,每个Servlet都单独拥有一个ServletConfig对象,用来获取web.xml中的配置信息。
2、使用:
获取ServletConfig对象
获取web.xml的配置信息
在web.xml中对应的servlet的servlet标签中添加
<init-param>
<param-name>config</param-name>
<param-value>utf-8</param-value>
</init-param>
//获取ServletConfig对象
ServletConfig sc=this.getServletConfig();
//获取web.xml的配置信息
String value=sc.getInitParameter("config");
System.out.println(value);//得到utf-8