第一个Servlet程序
编写步骤:
建立FirstSerlvet并继承HttpServlet
覆盖doGet或doPost方法
public class FirstServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.getWriter().print(“HelloWorld");
}
}
将建立好的FirstServlet程序编译后,拷贝到web application中的classes目录中
在web.xml配置文件中进行配置
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/servlet/FirstServlet</url-pattern>
</servlet-mapping>
Servlet是单实例多线程的,如果存在可以修改的成员变量将会出现线程安全问题
使用Servlet最好保证Servlet是无状态的,也就是没有可以修改的成员变量
1, Servlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。 它担当客户请求(Web浏览器或其他HTTP客户程序)与服务器响应(HTTP服务器上的数据库或应用程序)的中间层。
Servlet是位于Web 服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机。
2,
1,当输入用户名和密码后,点击登录:就把这次请求提交到服务器里,服务器再到数据库里面查看后,做处理。Servlet就是运作在服务器上,Servlet来解析浏览器传过来的信息,(也就是来解析Http协议)而这些信息是通过协议传过来的,也就是Http协议。
这个Servlet是HttpServlet,从而可以解析Http协议。
(1)是通过HttpServletRequest拿到客户端的数据,
(2)而HttpServletResponse可以往浏览器上写数据。调用getWrite()方法而在写之前,要告诉浏览器写什么类型的数据,调用setContentType()方法,因为HttpServletResponse可以写很多类型的数据。
3,
Servlet的特点
Servlet是一个供Servlet引擎调用的java类,他不能独立运行,它的运行完全是由Servlet引擎来控制和调度。Servlet引擎是一种容器程序,他负责管理和维护所有Servlet对象的生命周期,Servlet的加载,执行流程,以及如何接收客户端发送的数据和如何将数据传输到客户端等具体的底层事务,都是由Servlet引擎来实现的。Servlet引擎负责将客户端的请求信息转交给Servlet和将Servlet生成的响应信息返回给客户端。
Servlet是一种插件,它是一个提供了一些约定方法供容器去调用的类,它只负责在自身的方法中接受并处理容器传递进来的数据,以及生成并返回给容器去使用的数据和状态信息。
Servlet最常见的应用在于读取Web浏览器传递给web服务器的参数和生成web服务器返回个web浏览器的动态网页文档内容,Servlet也能获取web浏览器发送的http请求行信息,以及生成用于web服务器发送的http响应消息中的状态行和响应头信息,Servlet还能获取web服务器和Servlet引擎自身的一些环境和状态信息。
Servlet程序的运行过程就是它与Servlet引擎的交互过程,Servlet程序只与Servlet引擎打交道,他并不与web服务器和客户端进行任何直接的交互。
Servlet本身是一个Java语言的应用,能完成普通Java程序所能完成的所有功能。可以访问本地文件系统,访问数据库,调用其他的Java类等,在Servlet中还可以将http请求/响应的状态信息保存到Servlet引擎中,从而实现web浏览器web服务器之间有状态的会话。
web服务器上可以布置多个功能个不相同的Servlet,每个Servlet都应设置它可以处理何种样式的url请求,当符合的url请求到达时,Servlet引擎调用相应的Servlet进行处理。
Servlet的运行过程
Servlet引擎按照这样的过程来调用一个Servlet程序,
1,接受到访问某个Servlet的http请求之后,Servlet引擎首先检查是否已经装载并创建了该Servlet的实例对象,如果已经转载并创建了该Servlet的实例对象,Servlet引擎则直接执行第4步,否则实现第2步。
2,装载并创建Servlet的一个实例对象。
3,调用Servlet实例对象的init()方法,执行Servlet的一些初始化程序。
4,创建一个用于封装Servlet请求消息的HttpServletRequest对象和一个代表Servlet响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
5 ,web应用程序停止或重启之前,Servlet引擎将卸载其中运行的Servlet。在卸载Servlet之前,Servlet引擎将调用Servlet的destroy()方法,以便在这个方法中执行Servlet的一些清尾工作,例如释放占用的资源。Servlet被Servlet引擎卸载后,将变成垃圾,等待java虚拟机垃圾收集器将其彻底从内存中清除。
对这个运行过程的一些说明:
1,在<servlet>元素中嵌套一个<load-on-startup>子元素,web应用程序在启动时就可以转载并创建Servlet的实例对象,以及调用Servlet实例对象的init()方法。<load-on-startup>中的内容设置为0或一个正整数,这个数字越小,Servlet被加载的时间就越早。
2,在Servlet的整个生命周期内,它的init方法只被调用一次,而对一个Servlet的每次访问请求都导致Servlet引擎调用一次Servlet的service()方法,对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象。
3 ,tomcat也提供了是否自动重新装载被修改的Servlet的配置选项,在<tomcat安装目录>/conf/server.xml文件中,可以将<context>元素的reloadable属性设置为TRUE,这样Tomcat就能自动重新装载该web应用程序的/WEB-INF/classes和/WEB-INF/lib目录下的发生了改变的类。
-----------------------------------------------------------------------------------------
Servlet的运行过程
首先Servlet被部署到Web容器中,当客户端发送调用这个Servlet的请求到达Web容器时,Web容器会先判断所调用的Servlet实例是否存在。
如果不存在,就装载当前所调用的Servlet并调用构造方法生成这个Servlet的实例,其次再调用这个实例的init()方法(init()这个方法只会在Servlet初始化的时候调用一次,除非这个Servlet被重新部署)进行初始化,然后新创建一个线程,并在新建线程中调用这个实例的service()方法,service()方法再根据请求的具体类型调用doGet()、doPost()等方法,然后生成动态的回复内容,最后服务器发送回复内容给客户端的浏览器。
如果存在,就直接新创建一个线程,并在新建线程中调用这个实例的service()方法,service()方法再根据请求的具体类型调用doGet()、doPost()等方法,然后生成动态的回复内容,最后服务器发送回复内容给客户端的浏览器。
当Servlet不再需要使用的时候,比如其所在的Web应用被卸载或Web服务器关闭时,它就会被卸载掉,卸载前调用destory()方法,完成所有相关资源的释放。
forward() 与redirect()的区别 请求重定向与请求转发的区别:
forward() 与redirect()的区别
HttpServletResponse.sendRedirect方法实现请求重定向,RequestDispatcher.forward方法实现请求转发
forward()仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出重定向后的地址;redirect()则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。forward()更加高效,在其可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,需要跳转到一个其它服务器上的资源,则用sendRedirect()方法。
sendRedirect()方法可以重定向到:当前应用程序中的其他资源,同一站点的其他应用程序中的资源,甚至其他站点的资源。
他们都能使浏览器获得另一个URL所指向的资源。
1.如果传递给HttpServletResponse.sendRedirect方法的相对Url以"/"开头,它是相对于整个web站点的根目录;
如果创建RequestDispatcher对象是指定的Url以”/“开头,他是相对于当前web应用程序的根目
2.HttpServletResponse.sendRedirect方法对浏览器的请求做出响应,响应的结果是让浏览器去重新发出对另外一个URL的访问请求。
RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只显示响应结果,并不知道在服务器内部发生了转发行为。
3,RequestDispatcher.forward方法的调用者和被调用者之间共享相同的request对象和response对象,他们属于同一个访问请求和响应过程;HttpServletResponse.sendRedirect方法调用者和被调用者使用各自不同的request对象和response对象,他们属于两个独立的访问请求和响应过程。
4,这两个方法调用之前都不能有内容已经被输出到客户端,如果缓冲区已有了一些内容,将被清除。
=====================================================================================================
HttpServletRequest的getInputStream方法与getReader方法
1.getInputStream方法返回一个代表实体内容的输入流对象,类型为javax.servlet.ServletInputStream,可以读取HTTP请求消息中的实体内容。如果实体内容中包含二进制数据,那么就只能使用此方法返回的输入流对象来读取。
2getReader方法用于返回一个代表实体内容的BufferReader对象,返回的BufferReader对象将实体内容中的字节数据按照请求消息中指定的字符集编码转换成文本字符串。
3,当请求消息中的实体内容全部是文本数据,并且在Servlet程序中也需要以文本方式来处理这些内容时,适于使用getReader方法。如果Servlet程序不对他们进行处理,而只是存储到服务器的文件系统或数据库中,这适于使用
getInputStream方法。
4对于要处理文件上传的Servlet程序来说,只能调用getInputStream方法返回的ServletInputStream字节流对象去读取实体内容,而不能调用getReader方法。因为从ServletInputStream流对象中读取的数据是每个字节的原始内容,而从BufferedReader流对象中读取的数据是原始的内容按某种编码转换成的字符文本。
重定向时getWriter()方法对网页字符集编码的影响
1.调用者程序中没有使用PrintWriter out=response.getWriter();语句,被调用者程序中设置的字符集编码将覆盖调用者程序中设置的字符集编码。
2.调用者程序中使用类了PrintWriter out=response.getWriter();语句,被调用者程序中设置的字符集编码将不再起作用。因为只有在第一次调用当前HttpServletResponse对象的getWriter方法之前,调用那些设置字符集编码的方法(即调用者程序使用的setContentType()方法),才会对PrintWriter对象起作用,而在getWriter方法之后调用将对PrintWriter对象无效。
================================================================================================================================
1.Http协议规定浏览器向Web服务器传递的参数信息中不能出现某些特殊字符,而必须对这些字符进行URL编码后再传送。web服务器端程序接到参数信息后,先从中分离出每个参数的名称和值部分,在对他们进行URL解码,最后将URL解码得到的字节数组按照某种字符集编码转换成Unicode字符串。
2。Url编码是对字符所对应的字符集编码进行URL编码,例如“中”所对应的gb2312编码是0xD6D0.然后对0xD6D0进行URL编码传送给服务器。
3,url解码过程:unicode码-->字符集编码字节数组-->对字节数组进行URL解码-->得到字节数组-->按字符集编码转换成unicode字符编码的字符串。
4,要解决URL解码造成的中文乱码问题要做到两点,
一,在服务器程序中加入request.setCharacterEncoding("gb2312"); 用于设置请求消息实体的字符集编码。
二,在<tomcat安装目录>/conf/server.xml 中<Connector .../>里加入
useBodyEncodingForURI="true"/>
这样,url地址后的参数的字符集编码也通过request.setCharacterEncoding("gb2312");语句设置为gb2312.
由于某些原因 服务器响应缓慢的时候,用户提交FORM表单后没有立即看到服务器端的响应,他们很有可能再次单击一次或多次“提交”按钮,这就发生了同一份表单的重复提交,这在有些情况下是不允许的,例如金融交易。下面是两种解决方法。
利用Session防止表单重复提交,通过服务器端程序来阻止用户故意重复提交表单的行为,原理如下
(1)包含有form表单的页面由一个服务器程序动态产生,服务器程序为每次产生的页面中form表单都分配一个唯一的随机标识号,并在Form表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号
2.用户提交form表单时,服务器程序比较form表单隐藏字段中的标识号与存储在当前用户的Session域中标识号是否相同,如果相同则处理表单数据,然后清除当前Session域中存储的表单标识号。当用户重复提交原来得到的form表单时,当前用户的Session域中已不存在相应的表单标识号,服务器将忽略提交的表单请求。
3.浏览器只有重新向web服务器请求包含form表单的页面时,服务器程序才会产生另外一个随机标识号,并将这个标识号保存在Session域中和作为新返回的form表单的隐藏字段值。
使用客户端的JavaScript程序,可以防止用户这种非故意的表单重复提交问题。代码如下:
<script language="javascript">
var isCommitted=false;
function checkPost()
{
if(!isCommitted)
{
isCommitted=true;
return true;
}
else
{
alert("不能重复提交表单");
return false;
}
}
</script>
在<form>中加入 onsubmit="return checkPost()" 即可
这样就可以防止在用户看到服务器端响应之前,进行重复提交。
=====================================================================================================
jsp与Servlet的选择
1.JSP是一种以产生网页显示内容为中心的web开发技术,可以使用模板元素来产生网页文档的内容,如果使用Servlet来输出大量的网页文档内容,则必须使用大量的out.println语句
2.JSP的源文件和开发过程都要比Servlet简单,Servlet源程序需要手工编译和在web部署描述符文件中进行设置后才能执行,而jsp不用,JSP引擎可以完成这些工作。
3.在JSP中使用javabean和自定义标签,可以分离用于表现外观的HTML文本内容和用于处理业务逻辑的java代码。
尽管JSP有许多优点,对于用户的一次请的响应过程,它的主要优势在于输出网页文档内容,如果需要用java代码完成大量的流程控制和业务逻辑处理,那么就应该使用Servlet。
如果用户的一次请求的响应过程需要完成大量的流程控制和业务逻辑处理,同时还要输出丰富的网页文档内容,这样就需要结合使用Servlet和JSP来共同完成这种请求的响应过程,由servlet完成流程控制和业务处理,并将结果存储到request或Session中,然后将请求转发到JSP页面,再有JSP页面从request或Session中取出结果数据并完成响应内容的输出。