JavaEE学习笔记day2
理解Servlet的编写和访问过程
掌握Servlet父子类之间的继承关系
理解Servlet处理、解析请求以及返回响应的过程
Servlet页面跳转
Servlet的编写和访问过程
servlet的运行过程
servlet程序是由web服务器调用,web服务器收到客户端的发起的http访问请求后:
- HTTP服务器(Apache)收到HTTP请求以后,转发给Web容器(Tomcat),此时Web容器会解析HTTP请求的内容,web容器通过请求的URL来选择需要用哪个Servlet来处理请求(这个就是web.xml中配置的或者@webServlet注解的作用了)
- web服务器首先检查是否已经装载并创建了该servlet的实例对象。如果是,则执行第5步,否则执行第3步
- 装载并创建给servlet的一个实例对象
- 调用servlet实例对象的init()方法。
- 创建一个用于封装HTTP请求的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和和响应对象作为参数传递出去。
- web应用程序被停止或重启之前Servlet引擎将卸载Servlet,并在卸载之前的调用Servlet的destory()方法。
在整个servlet程序中最重要的是Servelt接口,在此接口下定义了一个GenericServlet的子类,但一般不会直接继承此类,而是根据所使用的协议选项GenericServlet的子类继承。(后面会介绍几个servlet的区别)
例如:采用HTTP协议处理,一般而言需要使用HTTP协议操作,用户自定义的Servlet类要继承HttpServlet类。
开发一个可以处理Http请求的Servlet类,则肯定需要继承HttpServlet类,该类提供了不同的方法用于响应客户端请求,常见的方法有:
- doGet(HttpServletRequest req, HttpServletResponse resp)
- doPost(HttpServletRequest req, HttpServletResponse resp)
- service(HttpServletRequest req, HttpServletResponse resp)
在自定义的Servlet类中,根据实际需要重写HttpServlet类中提供的方法,Servlet程序本身也是按照请求响应的方式进行的,所以在方法中定义了两个参数,即HttpServletRequest ,HttpServletResponse ,用来接收和回应用户的请求。
servlet的编写
- 实现Servlet接口,然后实现接口中的五个方法
- init(ServletConfig parm1) //该函数用于初始化servlet,类似于类的构造函数,该函数只会被调用一次
- getServletConfig()
- service(ServletRequest req, ServletResponse res) //这个函数用于处理业务逻辑
//当用户每访问servlet时,都会调用
//req:用于获得客户端(浏览器)信息
//res:用于向客户端(浏览器)返回信息 - getServletInfo()
- destroy() //销毁,释放内存,三种方式会触发destroy
//1. reload该servlet(webApps) 2. 关闭tomcat 3.关机
- 继承GenericServlet,只需要实现一个方法:service
- 继承HttpServlet,复写doGet和doPost方法
Servlet父子类之间的继承关系
三种访问方式的区别
- 可以看到Servlet接口是定义在javax.servlet包中,该接口定义了5个方法。
- init() :在Servlet实例化之后,Servlet容器会调用init()方法,来初始化该对象,主要是为了让Servlet对象在处理客户请求之前可以完成一些初始化工作,比如:建立数据库的连接,获取配置信息。
- service():容器调用service()方法来处理客户端的请求。
- destroy():当容器检测到一个Servlet对象应该从服务器中被移除的时候,容器会调用该对象的destroy方法,以便让Servlet对象可以释放它所使用的资源,保存数据到持久化存储设备中,例如:将内存中的数据保存到数据库中,关闭数据库的连接。
- GenericServlet
直接通过实现Servlet接口来编写一个Servlet类,就需要实现Servlet接口中定义的5种方法,为了简化Servlet的编写,在javax.servlet包中,给我们提供了一个抽象的类GenericServlet,它提供了除service()方法外的其他4种方法的简单实现。GenericServlet类定义了一个通用的,不依赖具体协议的Servlet - HttpServlet 由于大多数网络应用中,都是浏览器通过HTTP协议去访问服务器资源,而通常编写的Servlet也主要是应用于HTTP协议的请求和响应,为了快速开发应用于HTTP协议的Servlet,Sun公司在javax.servlet.http包中给我们提供了一个抽象的类HttpServlet,他继承自GenericServlet类,用于创建适合Web站点的HTTP Servlet。
比如,doPost() doGet()这些方法,从request解析请求信息开始,将根据http协议的格式进行解析,分发到不同的请求方法处理中,doPost() doGet()也肯定是被service方法调用的。
Servlet中的请求与响应
get请求和post请求的异同
- 生成方式:
- get方式有四种: 1)直接在URL地址栏中输入URL。2)网页中的超链接。3)form中method为get。4)form中method为空时,默认是get提交。
- post方式:form中method属性为post。
- 数据传送方式
- get方式:表单数据存放在URL地址后面。所有get方式提交时HTTP中没有消息体。表单数据存放在URL地址后面。所有get方式提交时HTTP中没有消息体。
- post方式:表单数据存放在HTTP协议的消息体中以实体的方式传送到服务器。表单数据存放在HTTP协议的消息体中以实体的方式传送到服务器。
- 服务器获取数据方式
- GET方式:服务器采用request.QueryString来获取变量的。
- POST方式:服务器采用request.Form来获取数据。
- 传送的数据量
- GET方式:数据量长度有限制,一般不超过2kb。因为是参数传递,且在地址栏中,故数据量有限制。
- POST方式:适合大规模的数据传送。因为是以实体的方式传送的。
- 安全性
- GET方式:安全性差。因为是直接将数据显示在地址栏中,浏览器有缓冲,可记录用户信息。所以安全性低。
- POST方式:安全性高。因为post方式提交数据时是采用的HTTP post机制,是将表单中的字段与值放置在HTTP HEADER内一起传送到ACTION所指的URL中,用户是看不见的。
servlet请求处理过程
- Web Client 向Servlet容器(Tomcat)发出Http请求;
- Servlet容器接收Web Client的请求;
- Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中;
- Servlet容器创建一个HttpResponse对象;
- Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象
- 为参数传给 HttpServlet对象;
- HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息;
- HttpServlet调用HttpResponse对象的有关方法,生成响应数据;
- Servlet容器把HttpServlet的响应结果传给Web Client;
servlet处理请求
处理get请求
- HelloForm servlet代码(只修改doGet方法其他不需要动):
public class HelloForm extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// response.getWriter().append("Served at: ").append(request.getContextPath());
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String title = "使用 GET 方法读取表单数据";
// 处理中文
String name =new String(request.getParameter("name").getBytes("ISO8859-1"),"UTF-8");
String docType = " \n";
out.println(docType +
"\n" +
"" + title + " \n" +
"\n" +
"" + title + "
\n" +
"\n" +
" - 站点名:"
+ name + "\n" +
"
- 网址:"
+ request.getParameter("url") + "\n" +
"
\n" +
"");
}
}
- 浏览器输入 http://localhost:8080/test/helloform?name=testdoGet&url=localhost
- servlet获取name和url参数并展示
使用表单的 POST 方法实例
- HelloPostForm servlet代码(只展示doGet和都Post方法其他不需要动):
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String title = "使用 POST 方法读取表单数据";
// 处理中文
String name =new String(request.getParameter("name").getBytes("ISO8859-1"),"UTF-8");
String docType = " \n";
out.println(docType +
"\n" +
"" + title + " \n" +
"\n" +
"" + title + "
\n" +
"\n" +
" - 站点名:"
+ name + "\n" +
"
- 网址:"
+ request.getParameter("url") + "\n" +
"
\n" +
"");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
- 在WebContent下创建post.html代码如下:
post
- 运行post。html并输入点击提交可观察到 servlet处理结果;
HttpServletResponse 响应
- getWriter()方法,返回的是一个输出流
- response.setContentType("text/html");
- 编码:response.setCharacterEncoding("UTF-8");
form表单提交到servlet的两种方法(action= “”)
-
相对路径
- action="servlet/helloform"输入web中配置的相对路径 (注意:开头没有/)
- action="HelloForm"输入servlet中注解的相对路径 (注意:开头没有/)
- action="servlet/helloform"输入web中配置的相对路径 (注意:开头没有/)
绝对路径 :action="test/servlet/helloform" 即:/项目名/相对路径
Servlet中请求数据的传递、请求转发与页面跳转
request的转向
-
RequestDispatcher.forward()方法:
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
服务方(如:servlet)将请求转发到同一个WEB应用程序中另一个Servlet(或:JSP)--第三方 进行处理(该过程浏览器方-客户方并不知道),让这个第三方直接将结果返回给浏览器方。
通常在servlet中使用的代码是:
request.getRequestDispatcher(跳转页面的Url).foward(request,response);
-
有三种方法可以得到Request Dispatcher对象。
javax.servlet.ServletRequest的getRequestDispatcher(String path)方法;
其中path可以是相对路径,但不能越出当前Servlet上下文。如果path以“/”开头,则解析为相对于当前上下文的根。javax.servlet.ServletContext的getRequestDispatcher(String path)方法,其中path必须以“/”开头,路径相对于当前的Servlet上下文。
可以调用ServletContext的getContext(String uripath)得到另一个Servlet上下文,并可以转向到外部上下文的一个服务器资源链接。使用javax.servlet. ServletContext的getNamedDispatcher(String name)得到名为name的一个Web资源,包括Servlet和JSP页面。这个资源的名字在Web应用部署描述文件web.xml中指定。
使用:
下面是一个应用的配置文件web.xml:
其中定义了两个Servlet,名字分别为FirstServlet和SecondServlet,对应的类分别为org.javaresearch. redirecttest.ServletOne和org. javaresearch.redirecttest.ServletTwo。可以在浏览器中通过类似于下面的链接访问:
http://localhost:8080/servlet/firstservlet/
使用1中方法,例如在firstservlet可以写入下面的代码:
RequestDispatcher rd = request.getRequestDispatcher("secondservlet");
rd.forward(request, response);
此时控制权将转向到第二个Servlet了。
使用2中的方法,可以从Servlet Context中得到RequestDispatcher代码如下:
RequestDispatcher rd = getServletContext().getRequest
Dispatcher("/servlet/secondservlet");
rd.forward(request, response);
使用3中的方法,从上面的web. xml配置文件可以看到定义了两个Servlet,名字分别为FirstServlet和SecondServlet,所以可以得到命名的Dispatcher:
RequestDispatcher rd = getServletContext().getNamedDispatcher("SecondServlet");
rd.forward(request, response);
这样也可以重定向到SecondServlet了。
- sendRedirect()方法:
- response.sendRedirect(跳转页面URL)
就是服务端根据逻辑,发送一个状态码(Location ,状态码320),告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。
服务方(如:servlet)直接将目标URL发回浏览器,让浏览器自己自动重新向目标URL发出HTTP请求。
重定向是作为不同请求来看待的。
- 区别比较:
RequestDispatcher.forward()方法和HttpServletResponse.sendRedirect()方法的区别是:
前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。
所以,前者更加高效,在前者可以满足需要时,尽量使用Request Dispatcher.forward()方法,并且,这样也有助于隐藏实际的链接。
在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用HttpServletResponse.sendRequest()方法。
servlet数据传递
静态变量
HttpServletResponse的sendRedirect()方法
HttpServletRequest的getRequestDispatch()方法
HttpServletRequest的getSession()方法
HttpServletRequest的setAttribute()方法
- 静态变量
通过建立一个数据类来进行传递。
案例:
public class MyData{
public static String data; //通过使用该类来实现数据传递
}
HttpServletResponse的sendRedirect()方法
基本语法:
response.sendRedirect("/Web应用名/资源名?uname="+username+"&pwd="+password);
response.sendRedirect(“servlet的地址?参数名=参数值&参数名=参数值...”);HttpServletRequest的getRequestDispatch()方法
getRequestDispatch()方法是使WEB服务器从当前Servlet转发到当前应用下的另一个Servlet。
基本语法:
request.getRequestDispatcher(资源地址).forward(request,response);HttpServletRequest的getSession()方法
基本语法:
1、放入session:request.getSession.setAttribute("loginUser",username);
2、取出session:request.getSession.getAttribute("loginUser");
PS:该方法可以传递对象