Servlet

Servlet : server applet,直译服务小程序。那Servlet到底是什么呢?

Servlet说白了其实就是一个接口,接口的作用是什么?规范呗,这个接口规定了下面三个问题:

  1. 初始化时做什么
  2. 接收到请求时做什么
  3. 销毁时做什么

因此在Servlet中只添加业务逻辑,具体如何监听、用什么端口等由容器(如Tomcat)完成,servlet不关心也不需要关心。

Servlet在容器中的配置

在Tomcat中有两种方式配置Servlet,一种是在xml中配置,另一种是使用注解:

Xml配置Servlet:

<!--配置Servlet的类路径-->
<servlet>
    <servlet-name>DemoServlet</servlet-name><!--servlet名-->
    <servlet-class>com.heima.servlet.DemoServlet</servlet-class><!--类全名-->
</servlet>
<!--配置Servlet的映射路径-->
<servlet-mapping>
    <servlet-name>DemoServlet</servlet-name><!--映射Servlet名-->
    <url-pattern>/demoServlet</url-pattern><!--访问路径-->
</servlet-mapping>

servlet 3.0 注解配置:

//直接在类名上使用注解:
@WebServlet(name = "Servlet", urlPatterns = "/1")
//或者省略模式:
@WebServlet("/1")//注解默认赋值给value,即urlPatterns

xml与注解优缺点分析:
xml优缺点:

  • 优点:耦合性低,容易编辑,配置比较集中,方便修改,在大业务量的系统里面,通过xml配置会方便后人理解整个系统的架构
  • 缺点:比较繁琐,类型不安全,配置形态丑陋,配置文件过多的时候难以管理,并且IDE不能检测配置的正确性

注解优缺点:

  • 优点:方便,简洁,配置信息和 Java 代码放在一起,有助于增强程序的内聚性。
  • 耦合性高,分散到各个class文件中,所以不宜维护

xml与注解应该通过合适的场景进行选择,快速开发时优先选用注解。

Servlet生命周期

Servlet对象在第一次被访问时由Tomcat容器创建,并且一个Servlet对象只会被创建一次,创建时调用init方法,在Tomcat关闭时销毁,销毁时调用destory方法。
Servlet可以配置为在Tomcat启动时直接创建,即在xml中添加<load-on-startup>number</load-on-startup>number的大小为优先级:

  • number取值小于0或不配置:被访问时才去加载;
  • number取值为0时:最先被加载;
  • number取值大于0时:数值越小Servlet越优先加载;

Servlet的实现类还可以在构造方法中说明被创建时做什么

GenericServlet

为了简化Servlet接口,GenericServlet提供了除service方法外的平庸实现。继承GenericServlet后只需要重写service即可。

HTTPServlet

HTTPServlet继承GenericServlet,专门用来处理HTTP请求,可以区分get和post方法,并针对不同的请求作出不同的响应。

简单来说,接口定义了规则,抽象类提供了模板,子类进行具体实现。

路径映射规范

不同的匹配方式均可访问到该Servlet:

匹配方式-描述
完全匹配/user/login资源路径为/user/login时可以访问
目录匹配/user/*资源路径中含有/user目录均可访问
后缀名匹配*.do资源路径中以.do结尾的均可访问
缺省路径/访问的路径找不到,就会去找缺省路径

缺省时会在项目根目录寻找index.html文件。
开发中一般使用全路径配置。

注解在xml中对应的属性:

属性名类型描述
nameString指定Servlet的name属性,等价于<servlet-name>。如果没有显示指定,则该Servlet的取值即为类的全限定名。
valueString[]该属性等价于 urlPatterns 属性,两个属性不能同时使用。
urlPatternsString[]指定一组Servlet的URL匹配模式,等价于<url-pattern>标签
loadOnStartupint指定Servlet的加载顺序,等价于<load-on-startup>标签
initParamsWebInitParam[]指定一组Servlet初始化参数,等价于<init-param>标签
asyncSupportedboolean声明Servlet是否支持异步操作模式,等价于<async-supported>标签
descriptionString该Servlet描述信息,等价于<description>标签
displayNameString该Servlet的显示名,通常配合工具使用,等价于<display-name>

HTTP协议

HTTP:无状态的应用层协议。

主要的两种请求方式:

  • Get:

    1. 没有请求体
    2. 提交数据的方式为在URL后拼接:url?name1=value1&name2=value2
  • Post:

    1. 有请求体
    2. 提交数据方式为在请求体中:name1=value1&name2=value2

HttpServletRequest

浏览器的请求信息都封装在HttpServletRequest这个对象中。

常用API:

方法说明
String getMethod()获取请求方式的类型
StringBuffer getRequestURL()获取客户端发出请求完整URL
String getRemoteAddr()获取IP地址
String getProtocol()获取当前协议的名称和版本
String getParameter(String name)获取指定name的value值
String[] getParameterValues(String name)获取指定name的value值数组(比如多选框)
Map<String, String[]> getParameterMap()获取所有的数据封装到map中

请求头信息:

方法作用
String getHeader(String name)根据请求头的k关键字获取请求头信息
Enumeration getHeaderNames()返回此请求包含的所有头信息的枚举

getHeader中的关键字:

请求头key请求头value
referer浏览器通知服务器,当前请求来自何处,如果是直接访问,则不会有这个头。常用于:防盗链
If-modified-Since浏览器通知服务器,本地缓存的最后变更时间。与另一个响应头组合控制浏览器页面的缓存。
cookie与会话有关技术,用于存放浏览器缓存的cookie信息。
user-agent浏览器通知服务器,客户端浏览器与操作系统相关信息
connection保持连接状态。Keep-Alive 连接中,close 已关闭
host请求的服务器主机名
content-length请求体的长度
content-type如果是POST请求,会有这个头,默认值为application/x-www-form-urlencoded,表示请求体内容使用url编码
accept浏览器可支持的MIME类型。文件类型的一种描述方式。
mime格式浏览器请求数据的类型,例如: text/html ,html文件 text/css,css文件 text/javascript,js文件 image/*,所有图片文件
accept-encoding浏览器通知服务器,浏览器支持的数据压缩格式。如:GZIP压缩
accept-language浏览器通知服务器,浏览器支持的语言。各国语言(国际化i18n)

POST请求提交数据乱码问题:
原因:tomcat接收post请求数据采用的编码是ISO-8859-1,而我们的整个编码环境都是UTF-8。所以会导致乱码。
Servlet中获取数据前,将request编码设置为UTF-8:request.setCharacterEncoding("UTF-8");

request生命周期

每次请求都会创建一个新对象,请求完成、响应结束后request和response对象就销毁。

request域

request实现类中使用了一个Map来存储属性:

方法说明
void setAttribute(String name, Object o)往request域中设置值
Object getAttribute(String name)从request域中取值
void removeAttribute(String name)从request域中移除值
  • request.getAttribute(name):从rquest域对象中取值
  • request.getParameter(name):从rquest中获取请求数据

作用范围:一次请求和响应之间。

请求转发

  • RequestDispatcher getRequestDispatcher(String path)获取请求转发器(request对象方法)
  • void forward(ServletRequest request, ServletResponse response)传递request和response对象(转发器方法)
  1. 转发是服务器内部的跳转行为;
  2. 从一个Servlet转发到另一个资源(静态或动态),能够实现跳转,但是浏览器地址栏地址没有发生改变。因为对浏览器来说本质上就只有一次请求;
  3. 请求转发共享request域中的数据;

一个简单的登录功能执行顺序:
类分布:

类分布

servlet类接收请求后获取用户名和密码,封装为User并调用UserService类的方法验证登录,UserService方法调用Dao层的UserDao,Dao使用数据库工具类进行查询最后一步步返回。

HttpServletResponse

常见状态码:

状态码状态码描述说明
200OK请求已成功,请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。
302Move temporarily重定向,请求的资源临时从不同的 URI响应请求。
304Not Modified从缓存中读取数据,不从服务器重新获取数据
404Not Found请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。
403Forbidden服务器已经理解请求,但是拒绝执行它
405Method Not Allowed请求行中指定的请求方法不能被用于请求相应的资源
500Internal Server Error服务器内部错误。通常程序抛异常

HttpServletResponse常用API:

API描述
setStatues(int code)设置状态码(响应行)
setHeader(key,value)设置响应头(响应方式)

常见响应方式:

响应头Key响应头value
refresh页面刷新,例如:3;url=www.baidu.com //三秒刷新页面到www.baidu.com
content-type设置响应数据的类型(MIME类型)编码格式 例如:text/html;charset=UTF-8 text/plain;charset=utf-8 (这个可以解决乱码)
location指定响应的路径,需要与状态码302配合使用,完成重定向。 (value为URL)
content-disposition通知浏览器以附件形式解析正文,例如:attachment;filename=xx.zip
  1. 转发和重定向:
    【实现原理】转发在服务器内部发送,重定向是服务器操作浏览器发送请求
    【请求次数】转发只有一次请求,重定向会有两次请求
    【地址栏地址】转发不变,重定向后地址栏地址会变为第二次请求的地址
  2. 转发和重定向的作用:
    【转发】完成跳转,共享request域对象(数据)
    【重定向】完成跳转

重定向简写方式:response.sendRedirect("url");

设置响应体:

方法说明
java.io.PrintWriter getWriter()用于向浏览器输出字符数据。【字符流--给浏览器响应数据】
ServletOutputStream getOutputStream()用于向浏览器输出二进制数据。【字节流--文件下载】

ServletContext域对象

ServletContext域的作用范围为整个web项目
常用方法:
setAttribute(key, value)
getAttribute(key, value)
removeAttribute(key, value)
getRealPath(fileName)
getMimeType(fileName)

cookie&session

cookie存储在客户端,session存储在服务器,现在一般都是联合使用,使用cookie保存JSESSIONID,然后再服务器查询session。

Cookie

常用方法

  • 构造方法:Cookie(name,value)
  • 获取name值:getName()
  • 获取value值:getValue()
  • 设置cookie值:setValue(value)
  • ========================
  • 发送cookie:response.addCookie(cookie)
  • 获取所有cookie:Cookie[] getCookies = rquest.getCookies()

如果存在中文乱码可以使用java.net包下的URLDecoder类:

//先编码
URLEncoder.encode(cookie,"utf-8");//编码后会得到类似这样的编码值:%E6%9D%8E%E5%9B%9B
//再解码
URLDecoder.decode(cookie,"utf-8");//即可得到正确的值:李四

存活时间

Cookie默认存活时间为会话级,也就是关闭浏览器后cookie消失。(如果CHrome中 启动时 设置为从上次的继续则Cookie不会消失

Cookie到期后会自动删除(浏览器行为)(服务器的时间和时区设置可能影响Cookie,对Chrome、IE而言,Cookie的有效时间段是理解为客户端的时间与服务器端时间的间隔,对于FireFox而言,Cookie的有效时间完全由服务器端的时间决定)

可以通过void setMaxAge(int seconds)设置cookie的最大存活时间。默认为-1,即会话结束后消失(关闭浏览器),设置为0时立即删除cookie。

有效路径

cookie可以通过setPath(String path)设置cookie的有效路径,设置过后,在访问该路径及其子路径的时候会带上该cookie。一般情况下设置有效路径为/或者不设置

删除Cookie

删除需要设置值为空:"",设置最大存活时间为0,设置有效路径为原路径,然后在响应中添加这个Cookie。

session

常用API:

方法使用示例说明
getSession()request.getSession()获取当前session
void setAttribute(String name,Object value)session.setAttribute("loginUser",user)将一个对象与一个名称关联之后存储到session中
Object getAttribute( String name)session.getAttribute("loginUser")通过名称获取session中的数据
void removeAttribute(String name)session.removeAttribute("loginUser")根据指定名称删除session中的数据
String getId()String sessionId = session.getId()获取session的id
invalidate()ression.invalidate()使当前session失效

session在第一次调用getSession()时由Tomcat创建,并存在三种销毁方式:

  1. session手动销毁:session.invilidate();
  2. 过期销毁:session默认存活时间--30min
  3. 非正常关闭tomcat

Servlet很重要,但本文都只是些皮毛而已


更新Filter、Listener

Web基础之Filter、Listener

Filter过滤器

作用:对请求和响应进行拦截放行增强

接口方法:

  • destroy()
  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  • init(FilterConfig filterConfig)

分别是初始化、过滤、销毁。

使用XML配置的过滤器执行顺序按照XML从上到下,使用注解配置的过滤器按照实现了的类名顺序。

执行顺序:过滤器1前 -> 过滤器2前 -> Servlet -> 过滤器2后 -> 过滤器1后

过滤器生命周期和Servlet有些不一样:

  • 当Web应用被加载时,Filter被Tomcat创建
  • 当Web应用被卸载时,Filter被Tomcat销毁
  • Filter只被创建一次,Filter线程不安全

Listener监听器

三种作用域:

作用域接口名作用范围生命周期
请求域HttpServletRequest一个用户的一次请求在服务器接收到HTTP请求时就创建了<br/>在服务器处理结束HTTP请求时就被销毁了
会话域HttpSession一个用户的所有请求在第一用户请求服务器时被创建<br/>服务器关闭、Session过期、手动销毁被销毁
上下文域ServletContext所有用户的所有请求在服务器加载时/启动时被创建<br/>在服务器卸载时/关闭时被销毁

八大监听器:

  • Servlet context events

    • Lifecycle(作用域监听) *

      上下文域创建和销毁

      javax.servlet.ServletContextListener
    • Changes to attributes(作用域内属性监听)*

      上下文域属性增删改的操作

      javax.servlet.ServletContextAttributeListener
  • HTTP session events

    • Lifecycle

      会话域创建和销毁

      javax.servlet.http.HttpSessionListener
    • Changes to attributes

      会话域属性增删改的操作

      javax.servlet.http.HttpSessionAttributeListener
    • Session migration

      javax.servlet.http.HttpSessionActivationListener
      钝化: 使对象随Session存储到硬盘中
      活化:使对象随Session活化到内存中
    • Object binding

      javax.servlet.http.HttpSessionBindingListener
      使对象感知自己被放到session中,称为绑定setAttribute("user", new User())
      使对象感知自己从session中移除,称为解绑removeAttribute("user")
  • Servlet request events

    • Lifecycle

      请求域创建和销毁

      javax.servlet.ServletRequestListener
    • Changes to attributes

      请求域属性增删改的操作

      javax.servlet.ServletRequestAttributeListener

标签: Web

添加新评论