Servlet程序处理步骤:
1) 客户端发送请求至服务器端;
2) 服务器将请求信息发送至 Servlet,若此Servlet尚未被加载,服务器将其加载到java虚拟机并执行它;
3) Servlet接收HTTP请求并生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
4) 服务器将响应返回给客户端。
Servlet生命周期:
客户端请求该 Servlet,加载 Servlet 类到内存。
1.实例化:Servlet容器创建Servlet类的实例对象;
2.初始化:容器调用init()方法初始化该 Servlet,通常会申请资源以便后续使用;
3.服务:调用service()方法响应请求(根据请求方法不同调用doGet() 或者 doPost(),此外还有doHead()、doPut()、doTrace()、doDelete()、doOptions());
4.破坏:在释放Servlet实例之前调用destroy()方法,通常会释放资源;
5.不可用:释放内存中的容器。
Servlet骨架:
package com.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("-------init()方法无参------");
super.init();
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("-------init()方法带参------");
super.init(config);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("-------service()方法------");
PrintWriter pw=resp.getWriter();
pw.print("Hello World Servlet");
//super.service(arg0, arg1);
}
@Override
public void destroy() {
System.out.println("-------destroy()方法------");
super.destroy();
}
}
web.xml配置信息
<servlet>
<servlet-name>Servlet</servlet-name><!--与mapping中的name值一致即可-->
<servlet-class>com.servlet.HelloServlet</servlet-class><!--定义包类名称-->
</servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/start</url-pattern><!--页面映射路径-->
</servlet-mapping>
在浏览器地址输入http://localhost:8080/Project/start即可执行service方法打印出“Hello World Servlet”。并且控制台会输出:
-------init()方法带参------
-------init()方法无参------
-------service()方法------
这里destroy()方法暂未未被调用,所以没有输出。
上面例子是通过浏览器直接请求,下面举例通过jsp提交请求。
login.jsp
<body>
<form action="<%=request.getContextPath() %>/log">
用户名:<input type="text" name="userName"><br>
密 码:<input type="password" name="passWord"><br>
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
</body>
web.xml配置
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/log</url-pattern>
</servlet-mapping>
LoginServlet
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String usn=req.getParameter("userName");
String psw=req.getParameter("passWord");
System.out.println("userName:"+usn);
System.out.println("passWord"+psw);
}
}
在jsp页面输入用户名密码,控制台输出.
下面模拟登录案例(尚有缺陷)
首先将LoginServlet.java修改为:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String usn=req.getParameter("userName");
String psw=req.getParameter("passWord");
System.out.println("userName:"+usn);
System.out.println("passWord:"+psw);
if(usn.equals("huge")&&psw.equals("lixiaoyao")){
resp.sendRedirect(req.getContextPath()+"/01/success.jsp");
}else{
resp.sendRedirect(req.getContextPath()+"/01/error.jsp");
}
}
web.xml配置信息与login.jsp不变;
添加success.jsp
<body>
登陆成功!<br>
您提交的信息为:<br>
用户名:<%=request.getParameter("userName")%><br>
密码:<%=request.getParameter("passWord") %><br>
<a href="login.jsp">返回登录页面</a>
</body>
添加error.jsp
<body>
登陆失败!<br>
您提交的信息为:<br>
用户名:<%=request.getParameter("userName")%><br>
密码:<%=request.getParameter("passWord") %><br>
<a href="login.jsp">返回登录页面</a>
</body>
运行后会发现无论是成功页面还是失败页面用户名与密码的值都是null。
这是因为我们用的是重定向,牵扯到两次请求,第二次请求没有传值。
完善,用请求分派代替重定向:
String forward=null;
if(usn.equals("huge")&&psw.equals("lixiaoyao")){
forward="/01/success.jsp";
RequestDispatcher rd=req.getRequestDispatcher(forward);
rd.forward(req, resp);
}else{
forward="/01/error.jsp";
RequestDispatcher rd=req.getRequestDispatcher(forward);
rd.forward(req, resp);
}
重定向与请求分派的比较:
1.请求分派只能请求转发给同一个web应用中的其他组件;而重定向还可以重定到其他站点的资源上。
2.重定向访问过程结束后浏览器地址栏的URL会发生改变;请求转发过程结束后地址栏URL地址不变。
3.请求分派的发起者和调用者共享相同的request实例和response实例,它们属于同一个“请求/响应”过程;重定向的发起者和调用者使用各自的request实例和response实例,它们各自属于独立的“请求/响应”过程。