1、他是用web容器调用和执行的
2、他是java语言写de
3、按照servlet规范编写
4、功能强大,能完成所有服务器端的所有需求
5、是jsp的基础
servlet的生命周期
1、web容器首先去检查是否已经装载并创建了该servlet的实例;
2、装载并创建该servlet的一个实例
3、调用实例的init()方法;
4、创建HttpServletRequest和HttpServletResponse实例,调用servlet的service()方法,请求和响应作为service()方法的参数。
5、web应用/容器 被停止或重启,卸载之前调用Servlet的destroy()方法;
开发Servlet的3中方法:
1、实现Servlet接口(servlet-api.jar)
2、继承HttpServlet
3、继承GenericServlet
public class MyServlet implements Servlet{ //销毁实例,只调用一次 public void destroy() { System.out.println("摧毁前调用"); } public ServletConfig getServletConfig() { System.out.println("不会执行"); return null; } public String getServletInfo() { System.out.println("不会执行"); return null; } //初始化servlet,将其实例存放在内存中,只调用一次 public void init(ServletConfig arg0) throws ServletException { System.out.println("最先执行"); } //该方法在每次请求时都会调用,请求和响应作为参数 public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { System.out.println(arg0.getLocalPort()); System.out.println("再次调用"); //如何在浏览器中显示? arg1.getWriter().println("ok"); arg1.getWriter().println(arg0.getLocalPort()); } }
根据Servlet规范,需要部署Servlet,部署在web.xml文件中
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>org.nick.server.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/test1</url-pattern>
</servlet-mapping>
注:每次localhost:8182/web/test1这个请求时,都会调用org.nick.server.MyServlet里面的service()方法,第一次调用和关闭|重启web容器时,会调用init()和destroy()方法。
web容器启动时,会检查该servlet是否存在实例。
执行结果:
最先执行
8182
再次调用
8182
再次调用
信息: Stopping service Catalina
摧毁前调用
页面输出:
ok
8182
联想:一个请求需要单独写个Servlet?
使用继承GenericServlet 需要复写service()方法,也是一个请求需要一个Servlet
<servlet> <servlet-name>MyGenericServlet</servlet-name> <servlet-class>org.nick.server.MyGenericServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyGenericServlet</servlet-name> <url-pattern>/test2</url-pattern> </servlet-mapping>
public class MyGenericServlet extends GenericServlet { @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { arg1.getWriter().print("test2"); } }
使用继承HttpServlet,需要复写doGet()和doPost()方法,也是一个请求一个Servlet
<servlet> <servlet-name>MyHttpServlet</servlet-name> <servlet-class>org.nick.server.MyHttpServlet</servlet-class> </servlet>
public class MyHttpServlet extends HttpServlet{ public void doGet(HttpServletRequest req,HttpServletResponse rep){ doPost(req,rep); } public void doPost(HttpServletRequest req,HttpServletResponse rep){ try { System.out.println(req.getParameter("name")); rep.setCharacterEncoding("gbk"); rep.getWriter().print("你好"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
get与post请求的区别
1、post比较安全
2、get数据<2k,post理论无限制,最好<64k
3、get速度快
4、get保留uri地址,利于收藏
注:
1、一个servlet可以配置多个servlet-mapping
2、使用通配符*的灵活应用;
3、Servlet被加载到内存中后,直到web应用|容器重启或停止,才被释放,在内存中以单例存在
4、一个变量被多个用户操作时,应当添加同步机制 :
将其设置为成员变量
public class MyHttpServlet extends HttpServlet{
int s = 2;
doPost(req,rep){
synchronized(this){ s--;}
}
如果设置为局部变量,是没用的,每次调用方法,局部变量又恢复原来的值了。
5、<load-on-startup>配置,在web启动后,并没有直接将Servlet加载到内存中,而是有请求到该Servlet时,才将其放入内存中,配置该元素后,就是在web容器启动时,加载到内存中,j见spring的配置信息。