Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
即是:
就像其他普通的网页一样,您的浏览器发送一个HTTP请求给服务器。
Web服务器识别出这是一个对JSP网页的请求,并且将该请求传递给JSP引擎。通过使用URL或者.jsp文件来完成。
JSP引擎从磁盘中载入JSP文件,然后将它们转化为servlet。这种转化只是简单地将所有模板文本改用println()语句,并且将所有的JSP元素转化成Java代码。
JSP引擎将servlet编译成可执行类,并且将原始请求传递给servlet引擎。
Web服务器的某组件将会调用servlet引擎,然后载入并执行servlet类。在执行过程中,servlet产生HTML格式的输出并将其内嵌于HTTP response中上交给Web服务器。
Web服务器以静态HTML网页的形式将HTTP response返回到您的浏览器中。
最终,Web浏览器处理HTTP response中动态产生的HTML网页,就好像在处理静态网页一样。
发起疑问:先有JSP还是先有Servlet?(当然是先有Servlet了-手动滑稽)
回忆JSP 执行过程,然后说明JSP被翻译成.JAVA,这个.JAVA到底是什么样子呢?
打开环境,新建一个JSP,运行后,再观看此.java文件上,如Test.jsp在运行时首先解析成一个Java类Test_jsp.java,
而这个Test_jsp.java继承于org.apache.jasper.runtime.HttpJspBase类,
而HttpJspBase又是继承自HttpServlet的类,
由此可以得出一个结论,就是JSP在运行时会被Web容器翻译为一个Servlet
请求处理:当有请求到达容器时,容器会调用servlet对象的service方法。HttpServlet的service方法,它会根据用户的请求方式来调用doGet()或doPost().
但是,这两个do方法默认情况下会抛出异常,所以需要子类去重写(override)
public HelloServlet() { //1.只有首次会执行 System.out.println("创建HelloServlet对象"); }
@Override public void init(ServletConfig config) throws ServletException { //2.只有首次会执行 System.out.println("开始初始化"); super.init(config); }
@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //3.每次刷新都执行 System.out.println("service方法执行"); super.service(req, resp); }
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。
service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //4.由service方法决定是调用doGet方法还是doPost等方法 System.out.println("doGet方法执行"); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { }
@Override public void destroy() { //销毁时,执行 System.out.println("destroy方法执行"); super.destroy(); }
GET和POST的区别
GET | POST |
---|---|
从服务器上获取数据 | 向服务器传送数据 |
把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一 一对应,在URL中可以看到 | 通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程 |
传送的数据量较小,不能大于2KB | 传送的数据量较大,一般被默认不受限制(但跟服务器有关) |
安全性非常低,但执行效率高 | 安全性较高,但执行效率低 |
建议:
get方式的安全性较Post方式要差些,包含机密信息的话,建议用post数据提交方式。
在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式。
Servlet代码:
package cn.ebuy.servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class HelloServlet extends HttpServlet { public HelloServlet() { //1.只有首次会执行 System.out.println("创建HelloServlet对象"); } @Override public void init(ServletConfig config) throws ServletException { //2.只有首次会执行 System.out.println("开始初始化"); //获取上下文参数 System.out.println(config.getServletContext().getInitParameter("deltools")); //获取初始化参数 System.out.println(config.getInitParameter("dbtype")); System.out.println(config.getInitParameter("className")); super.init(config); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //3.每次刷新都执行 System.out.println("service方法执行"); super.service(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //4.由service方法决定是调用doGet方法还是doPost方法 System.out.println("doGet方法执行"); PrintWriter out=resp.getWriter(); out.println("HelloServlet"); //打印上下文参数 out.println(this.getServletContext().getInitParameter("deltools")); //打印初始化参数 out.println(this.getInitParameter("dbtype")); } @Override public void destroy() { //销毁时,执行 System.out.println("destroy方法执行"); super.destroy(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
web.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <context-param> <param-name>deltools</param-name> <param-value>idea</param-value> </context-param> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>cn.ebuy.servlet.HelloServlet</servlet-class> <!--配置初始化参数--> <init-param> <param-name>dbtype</param-name> <param-value>mysql</param-value> </init-param> <init-param> <param-name>className</param-name> <param-value>HelloServlet</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/helloServlet</url-pattern> </servlet-mapping> </web-app>
怎么启动时,就自动实例并初始化Servlet,而不是第一次访问时再创建呢?
在xml文件中<servlet>
标签内加上 <load-on-startup>0</load-on-startup>
(注意位置,不能在<init-param>
前面)
在servlet的配置当中,1的含义是:
标记容器是否在启动的时候就加载这个servlet。
当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。
正数的值越小,启动该servlet的优先级越高。
如果我们在web.xml中设置了多个servlet的时候,可以使用load-on-startup来指定servlet的加载顺序,服务器会根据load-on-startup的大小依次对servlet进行初始化。不过即使我们将load-on-startup设置重复也不会出现异常,服务器会自己决定初始化顺序。
版权声明:本文为CSDN博主「xuke6677」的原创文章
原文链接
首先有可能你不能使用WebServlet这个注解,接下来有解决方法:
类代码:
package cn.ebuy.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * 测试注解配置Servlet */ //配置注解属性 @WebServlet(name = "roleServlet",urlPatterns = {"/roleServlet","/role"},loadOnStartup = 1,initParams = {@WebInitParam(name = "deltool",value = "idea"), @WebInitParam(name = "dbtype",value = "mysql") } ) public class RoleServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out= resp.getWriter(); //获取初始化属性deltool out.println(this.getInitParameter("deltool")); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
测试1 单例:
package cn.ebuy.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/testServlet1") public class TestServlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out= resp.getWriter(); out.println(this); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
页面显示:
测试2:
类代码:
package cn.ebuy.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/testServlet1") public class TestServlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out= resp.getWriter(); String op= req.getParameter("op"); if (op.equals("read")){ out.println(i); }else if (op.equals("add")){ this.add(); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } int i; public void add(){ this.i++; } }
效果:
之后
由此得出结论:Servlet慎用全局变量
至此便结束了