http协议
http是一种网络传输协议。具体见http消息。
servlet简介
实现了servlet接口的类,都认为是一个servlet。它的作用是接收http请求,处理请求,返回结果。
servlet生命周期
服务器在启动时或者第一次请求servlet时(由配置决定,默认为负数)初始化这个servlet对象。服务器关闭时才会销毁这个servlet对象。因此在无论请求多少次Servlet,最多只有一个servlet实例。如果多个客户端并发访问,那么服务器会启动多个线程分别执行该servlet的service方法。
servlet线程不安全
如果多个用户同时请求一个servlet时,如果设计不当,会暴露出问题。如下所示,对于一个servlet的成员变量进行赋值操作。不同的用户调用时,能够对同一个servlet赋值,因此程序设计中应当谨慎设计变量。
public class FirstServlet extends HttpServlet {
String password;
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
password = (String) req.getAttribute("ps");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
...
}
servlet跳转
servlet之间可以跳转,从而可以使得一项任务可以按模块划分。比如一个servlet处理数据,一个servlet处理显示。
(1)转向 Forward
转向是通过RequestDispatcher对象的forword实现。RequestDispatcher可以通过Httpservlet的方法getRequestDispatcher获取。如下所示,如果希望跳转到secondServlet,需要先获取dispatcher。
//参数必须以/开头,表示Web应用程序的根目录
RequestDispatcher dispatcher = req.getRequestDispatcher("/secondServlet");
dispatcher.forward(req, resp);
这种转向,在客户端显示依然是之前访问地址。这种跳转对客户端而言是不可见的。
(2)Redirect
重定向是利用服务器返回的状态码实现的。客户端请求服务器,服务器返回一个状态码,如果返回的是301或302,那么浏览器会到新的网址重新请求该资源。
resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
resp.setHeader("Location", "http://www.baidu.com");
servlet具体实现
直接实现servlet接口非常不便,JDK提供了对Servlet的支持,我们在编写servlet类,直接实现HttpServlet接口即可。
编写servlet类文件后,需要让Web容器知道如何访问。在web.xml中,对servlet进行配置。
public class FirstServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException{
}
}
<servlet>
<servlet-name>1stServlet</servlet-name>
<servlet-class>servlets.FirstServlet</servlet-class>
<init-param>
<param-name>message</param-name>
<param-value>welcome to firstServlet</param-value>
</init-param>
<!--1:表示tomcat在启动时加载 0:表示有人第一次请求该servlet时,加载-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>1stServlet</servlet-name>
<url-pattern>/firstServlet</url-pattern>
</servlet-mapping>
<init-param>表示预置参数,可以通过getInitParameter("message");获取对应的参数。
servlet参数
注:init-param和context-param只能配置简单的字符串类型的参数;
env-entry只能配置java.lang中所涉及的参数类型。如果需要配置灵活的参数,应写在xml文件或者properties文件,然后编写程序去读取。
(1)初始化参数<init-param>
servlet可以在web.xml中使用<init-param>标签配置初始化参数,该参数可以被该servlet获取到
(2)上下文参数context-param
servlet可以先获取servletContext,然后使用getInitParameter获取指定名称的参数。
<context-param>
<param-name>usrname</param-name>
<param-value>dongjiajia</param-value>
</context-param>
(3)资源注射env-entry
在web.xml中使用标签<env-entry>配置资源,使用@Resource注入。
<env-entry>
<env-entry-name>password</env-entry-name>
<env-entry-type>java.lang.Integer</env-entry-type>
<env-entry-value>1</env-entry-value>
</env-entry>
@Resource(name="password")
String password;
资源注射的工作原理是JNDI(Java命名与目录接口),具体见JNDI说明。InjectionServlet实例中使用<env-entry>配置了名为password的JNDI资源,然后使用@Resource,查找JNDI可以获取到这几个资源。如果不使用@Resource,通过查找JNDI同样可以获取。
Context ct = new InitialContext();
String psd = (String)ct.lookup("password");
HttpServletRequest
客户单浏览器发出的请求被封装在HttpServletRequest对象中。请求信息都可以通过req获取。
HttpServletResponse
表示服务器的响应,封装了发送数据、发送响应头、响应状态码等。