Java编写的服务器端程序

Servlet

Servlet(Server Applet),全称Java Servlet,是用Java编写的服务器端程序。Servlet介于客户请求和服务器响应之间,用于处理客户请求和服务器响应,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口(规范),广义的Servlet是指任何实现了这个Servlet接口的类,通常将Servlet理解为后者。1

实现Servlet

Servlet配置

<!-- 配置一个Servlet -->
<!-- Servlet的配置 -->
<servlet>
    <!-- 指定Servlet的内部名称,自定义,尽量有意义 -->
    <servlet-name>RequestServlet</servlet-name>
    <!-- Servlet的类路径 -->
    <servlet-class>com.ldy.servlet.RequestServlet</servlet-class>
</servlet>
<!-- Servlet的映射配置 -->
<servlet-mapping>
    <!-- Servlet的内部名称,和servlet标签的内部名称一致 -->
    <servlet-name>RequestServlet</servlet-name>
    <!-- Servlet的映射路径 -->
    <url-pattern>/servlet/request</url-pattern>
</servlet-mapping>

访问http://localhost:8080/项目名/资源名过程,Tomcat启动时,先加载webapps中每个应用的web.xml配置文件;通过Ip和端口找到Tomcat;通过项目名找到webapps下的目录;通过资源名,在web.xml中查找是否有匹配的url-pattern,如果有则通过servlet-name找到对应的servlet配置,如果找到则去除servlet-class,再通过反射构造相应对象并调用对应方法。

Servlet映射路径url-pattern,servlet-mapping可以配置多个url-pattern,以“/”字符开头,并以“/”结尾的字符串用于路径匹配,以“.”开头的字符串被用于扩展名匹配,不能同时使用两种匹配,如/user/*.action是非法的,当输入的URL被多个servlet标签匹配的时候,精确匹配优先,扩展名匹配优先级最低。2

Servlet缺省路径<url-pattern>/</url-pattern>是在tomcat服务器内置的一个路径,在${CATALINA_HOME}\conf\web.xml中配置的,该路径对应DefaultServlet(缺省Servlet),用于解析web应用的静态资源文件。

Servlet自动加载,默认情况下,服务器在第一次访问Servlet时创建它,如果Servlet的构造方法或init方法中执行了较多的逻辑代码,将导致用户第一次访问Sevrlet的时候较慢,可以在web.xml中对Servlet配置load-on-startup,使服务器启动时就创建Servlet。

<servlet>
    <servlet-name>RequestServlet</servlet-name>
    <servlet-class>com.ldy.servlet.RequestServlet</servlet-class>
    <!-- 让Servlet对象自动加载 -->
    <load-on-startup>0</load-on-startup>
</servlet>

load-on-startup元素标记容器是否在启动的时候就加载这个Servlet;值是一个整数,表示Servlet应该被载入的顺序;当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个Servlet;当值小于0或者没有指定时,则表示容器在该Servlet被选择时才会去加载;正数的值越小,该Servlet的优先级越高,应用启动时就越先加载;当值相同时,容器就会自己选择顺序来加载。3

Servlet生命周期

Servlet类由开发者编写,但对象由服务器创建,并且由服务器调用相应的方法。

Servlet对象在Tomcat服务器是单实例多线程的,一个Servlet同时处理多个请求时,线程不安全效率高。因为Servlet是多线程的,所以当多个Servlet的线程同时访问了Servlet的共享数据,如成员变量,可能会引发线程安全问题,需要把使用到共享数据的代码块进行同步(synchronized关键字),而且尽量缩小同步代码块的范围,避免因为同步而导致并发效率降低,建议在Servlet类中尽量不要使用成员变量5

HttpServletRequest对象

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息6

请求行:request.getMethod()、request.getRequestURI/getRequestURL()、request.getProtocol()

请求头:request.getHeader(“name”)、request.getHeaderNames()

请求体:request.getInputStream()

URL参数:request.getQueryString()

通用获取参数数据(GET或POST):request.getParameter(“name”)、request.getParameterValues(“name”)、request.getParameterNames()7

请求参数乱码:request.setCharacterEncoding(“utf-8”),只对Post请求有效。Get请求需要手动转码,但Tomcat8以后默认编码格式是utf-8,7之前的都是iso8859-1。8

HttpServletResponse对象

HttpServletResponse对象代表服务器的响应,这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法6

响应行:response.setStatus()、response.sendError(404)

响应头:response.setHeader(“name”,”value”)

响应体:getOutputStream和getWriter方法分别用于得到输出二进制数据、输出文本数据的ServletOuputStream、Printwriter对象。这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。

Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。

Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象。

getWriter是PrintWriter类型,所以它有缓冲区,缓冲区的默认大小为8KB。在响应数据没有输出8KB之前,数据都是存放在缓冲区中,而不会立刻发送到客户端。当Servlet执行结束后,服务器才会去刷新流,使缓冲区中的数据发送到客户端。如果希望响应数据马上发送给客户端,可以向流中写入大于8KB的数据或者调用response.flushBuffer()方法手动刷新缓冲区。

响应参数乱码:response.setContentType(“text/html;chartset=utf-8”)

ServletConfig

ServletConfig配置对象对应web.xml中元素,主要是用于加载Servlet的初始化参数,一个Web应用可以存在多个ServletConfig对象(一个Servlet对应一个ServletConfig对象)[^6]。

包含getInitParameter(String name)、getInitParameterNames()、getServletContext()、getServletName()等接口。

ServletContext

Servlet上下文对象,一个Web应用中只有一个ServletContext对象,用于在Servlet之间传递数据,在Tomcat启动时创建,Tomcat关闭时销毁6

包含getContextPath()、getInitParameter(String name)、getInitParameterNames()、setAttribute(String name, Object object)、getAttribute(String name)、removeAttribute(String name)、getRequestDispatcher(String path)、getRealPath(String path)、getResourceAsStream(String path)等接口。

转发、重定向、包含

转发,context.getRequestDispatcher(context.getContextPath() + "/servlet/request").forward(req, resp);9

重定向,resp.sendRedirect(contextPath + "/servlet/request?name=eric&age=21");

包含,context.getRequestDispatcher(context.getContextPath() + "/servlet/request").include(req, resp);,转发不允许输出响应体,但包含可以,转发仍然可以设置响应头

web.xml详解

在${CATALINA_HOME}\conf\web.xml中的内容,相当于写到了每个项目的web.xml中,它是所有web.xml的父文件,定义了DefaultServlet、JspServlet、MIME类型、welcome-file-list等10

Javaweb四大域对象、三大组件

四大域对象,PageContext、ServletRequest、HttpSession、ServletContext;三大组件,Servlet、Filter、Listener。

JCP、JSR与Servlet规范

JCP(Java Community Process),是一个由Oracle(曾经是sun)领导的,负责管理Java和接收各种Java Specification Requests的组织11

JSP(Java Specification Request),是Java的spec,JSR由加入JCP的那些大佬们投票决定,例如Servlet4.0 对应jsr369。

Servlet3.1规范:https://pan.baidu.com/s/11QOoYZW5Ly_0QRqmkAF-YQ,支持通过注解配置Servlet、Filter、Listener,简化web.xml配置,此外还支持异步请求处理,文件上传。12131415

在JSP官网中寻址Servlet3.1规范: