Web基础之Servlet

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中对应的属性:

属性名 类型 描述
name String 指定Servlet的name属性,等价于<servlet-name>。如果没有显示指定,则该Servlet的取值即为类的全限定名。
value String[] 该属性等价于 urlPatterns 属性,两个属性不能同时使用。
urlPatterns String[] 指定一组Servlet的URL匹配模式,等价于<url-pattern>标签
loadOnStartup int 指定Servlet的加载顺序,等价于<load-on-startup>标签
initParams WebInitParam[] 指定一组Servlet初始化参数,等价于<init-param>标签
asyncSupported boolean 声明Servlet是否支持异步操作模式,等价于<async-supported>标签
description String 该Servlet描述信息,等价于<description>标签
displayName String 该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

常见状态码:

状态码 状态码描述 说明
200 OK 请求已成功,请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。
302 Move temporarily 重定向,请求的资源临时从不同的 URI响应请求。
304 Not Modified 从缓存中读取数据,不从服务器重新获取数据
404 Not Found 请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。
403 Forbidden 服务器已经理解请求,但是拒绝执行它
405 Method Not Allowed 请求行中指定的请求方法不能被用于请求相应的资源
500 Internal 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(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请求时就创建了
在服务器处理结束HTTP请求时就被销毁了
会话域 HttpSession 一个用户的所有请求 在第一用户请求服务器时被创建
服务器关闭、Session过期、手动销毁被销毁
上下文域 ServletContext 所有用户的所有请求 在服务器加载时/启动时被创建
在服务器卸载时/关闭时被销毁

八大监听器:

  • 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
      
posted @ 2019-07-26 16:55  code-blog  阅读(249)  评论(0编辑  收藏  举报