目录


生命周期

web.xml

获取表单数据(设置请求的编码格式)

返回响应内容(设置响应的编码格式)

结合前两点,总结基本模板

获取请求协议头部信息

设置响应头部信息

使用过滤器

在web.xml中为过滤器配置参数

使用Cookie

使用Session

对字符串数据进行编码和解码

监听器


生命周期

  我们自己创建的servlet,继承自HttpServlet,就相当于有了init()、doGet()、doService()、doPost()、destroy()这几个方法,而这几个方法就可以描述Servlet的声明周期。

方法名 被调用的时刻 以及  功能
init() 只有第一次访问该servlet的时候被调用,一般用来进行数据初始化
doGet() 通过get方式访问servlet的时候被调用,响应get请求
doPost() 通过post方式访问servlet的时候被调用,响应post请求
service() 接收所有方式的请求,service会在doGet和doPost之前调用
destroy() 服务器停止的时候被调用,一般用来进行一些清理操作

  因为我们将代码部署到服务器Tomcat上面,也就是说,Tomcat是一个容器。同时,上面的那些方法都是都Tomcat服务器来调用(由容器来调用)。

web.xml

  web.xml是项目的配置文件,该文件用来配置请求路径与servlet的对应关系。

  全路径为project-root/WebContent/WEB-INF/web.xml。

  需要注意的是,servlet有多个版本,在高版本中,可以通过注解@WebServlet("url-pattern")来设置。之前的版本需要使用web.xml来配置。

  示例:

<web-app>
<display-name>tomcat</display-name>
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>lixin.gan.test.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/testServlet</url-pattern>
</servlet-mapping>
</web-app>

  Tomcat使用web.xml的步骤:  

  1. Tomcat服务器在启动的时候,会加载web.xml文件,并解析文件。
  2. 服务器收到客户端的请求时,首先会根据请求的url路径去web.xml中相同寻找匹配的url-pattern。
  3. 如果没有找到匹配的url-pattern,就表示出错了(返回404);如果存在url-pattern,那么就利用与之对应的servlet-name,去servlet标签中查找对应的servlet-class。
  4. 根据找到的servlet-class来确定调用哪一个servlet来处理请求。

获取表单数据(设置请求的编码格式)

  表单提交的方式get和post 与 servlet中的doGet和doPost方法相对应,但是可以使用service来获取get或者post请求。默认情况下,如果没有重写doPost、doGet、service,则先执行service方法,然后service方法中根据请求方式,再调用doGet或者doPost。

  获取表单数据常用的是下面三个方法:

// 获取请求参数中key对应的value
String HttpServletRequest.getParameter(String key) // 用于获取checkbox这种有多个同名的key参数
String[] HttpServletRequest.getParameterValues(String key) // 获取所有参数,并以map形式保存
Map<String, String[]> HttpServletRequest.getParameterMap()

  上面的所有方法接收到的数据,传输过程中都是经过编码,如果请求中的数据全是英文,那么不会出现问题;但是如果有其他字符(比如中文字符),此时打印获取的数据,会出现乱码,可以通过getBytes("utf-8")来解码,也可以直接设置请求的编码格式:

request.setCharacterEncoding("utf-8");

  如果通过req.setCharacterEncoding("utf-8"),只能对post提交的数据进行字符集编码,而不能对get方式进行编码。因为get方式传递的参数是在URL中,进行的是URL编码。

  但是可以在tomcat的配置文件中,增加一个配置项即可:useBodyEncodingForUri="true"

<Connector
connectionTimeout="200000"
port="80"
protocol="HTTP/1.1"
redirectPort="8443"
useBodyEncodingForUri="true"
/>

  

 

返回响应内容(设置响应的编码格式)

  要想发回响应给请求方,可以通过下面的格式来进行:

PrintWriter writer = response.getWriter();
writer.append("hello 你好\n");
writer.flush();

  上面的代码是简单的返回一些文本内容给客户端,但是有两个需要注意的地方:

  1、此时并没有告诉客户端这个内容是什么格式(XML? JSON?MP4?),所以客户端接收到数据之后,会原封不动的显示出来。

  2、响应回来的内容是使用了什么编码格式,注意编码格式和内容格式不一样,编码格式决定着客户端能否正确无误地解析文件内容。

  鉴于以上面个注意点,可以通过两个方法来解决:

// 只设置响应内容的编码格式,而没有设置响应内容的数据格式
response.setCharacterEncoding("utf-8"); // 设置响应内容的数据格式,同时也设置了响应内容的编码格式
response.setContentType("text/html; charset=utf-8");

  

结合前两点,总结基本模板

  以doGet为例子:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 首先设置请求数据的字符编码
req.setCharacterEncoding("utf-8"); // 设置响应内容的数据格式以及编码格式
resp.setContentType("text/html; charset=utf-8"); // 然后是自己的业务代码 }

  上面这个模板其实并不好,因为,这样做之后,每一个方法都需要加这两行代码,一旦字符编码或者响应格式改变,就要修改很多地方。

  后期可以使用拦截器来完成设置 字符编码 以及 响应数据格式 的功能。

获取请求协议头部信息

  获取请求协议中的头部信息,有三个方法,但通常使用最多的是下面这个方法

String req.getHeader(String key)

  使用方式很简单,需要注意的是,请求中key和value都是要经过编码的(不能直接传输中文字符)。

设置响应头部信息

  设置响应头信息,也很简单,最常用的是下面这个方法:

void resp.setHeader(String key, String value)

  注意,如果value包含中文字符,需要先经过编码才能作为参数。

  如果要设置响应状态码,可以使用setStatus()方法来设置:

void resp.setStatus(int statusCode);

  如果还要设置状态码的信息,可以使用sendError()

void resp.sendError(int statusCode, String msg);

  

使用过滤器

  过滤器是一种特殊的工具,功能如下:

  1、在请求到达服务器的时候先于servlet处理请求。

  2、在返回给客户端响应之前,对Servlet的响应再进行一次加工,之后在返回给客户端。

  使用过滤器,可以在web.xml中进行配置,也可以使用注解@WebFilter("url-pattern")来设置,下面是在web.xml中的配置:

<filter>
<filter-name>testFilter</filter-name>
<filter-class>lixin.gan.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>testFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

  filter中的三个主要的方法:

public void init(FilterConfig fConfig)

  filter中的init(),功能和servlet中的init()一样,用于数据的初始化,第一次调用是在服务器启动的时候

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

  调用doFilter()进行过滤操作。三个参数的意义以及作用:

  1、第1个参数request是客户端的请求(还没有被servlet处理),此时可以修改请求中的数据。

  2、第2个参数response是由servlet处理之后的返回的response,此时可以修改响应中的数据。

  3、filter对request进行一些处理之后,调用第3个参数chain的doFilter(request, response)方法,来将请求转发给对应的servlet处理,表示通过了过滤。

public void destroy()

  服务器关闭的时候被调用。

  结合前面servlet中的service()、doPost()、doGet()中对于所有请求,都要设置请求的编码格式以及相应内容的数据格式和编码格式,有了过滤器,可以将这些操作都单独地写在过滤器中,可以消除冗余,同时维护起来也方便。

  比如:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws Exception {

	// 统一设置字符集编码以及响应内容格式
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8"); // 放行,执行真正的servlet
chain.doFilter(request, response);
}

  

在web.xml中为过滤器配置参数

  前面已经介绍了过滤器怎么使用,这里增加一点内容:从web.xml中读取过滤器的配置参数。过滤器的init()方法使用来对过滤器进行一些初始化工作,再进行初始化的时候,可能会有这种情况:有一些(配置)参数的值在程序代码中写死,这样的话,一旦要修改配置参数的话,就需要修改代码。

  其实,完全可以在web.xml中配置,然后在init方法中,利用FilterConfig类来获取web.xml中的配置项。在web.xml中添加配置项的方法如下:

<filter>
<filter-name>testFilter</filter-name>
<filter-class>lixin.gan.filter.MyFilter</filter-class>
<init-param>
<param-name>token</param-name>
<param-value>123456abc</param-value>
</init-param>
<init-param>
<param-name>code</param-name>
<param-value>9999</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>testFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

  在Filter的init方法中这样使用:

public void init(FilterConfig fConfig) throws ServletException {
System.out.println(fConfig.getInitParameter("code"));
System.out.println(fConfig.getInitParameter("token"));
}

  

  

使用Cookie

  设置响应cookie(通过response对象返回客户端)

Cookie cookie = new Cookie("key", "value");

// 不设置过期时间(临时cookie),默认在浏览器窗口关闭之前有效。
cookie.setMaxAge(100); // 若设置cookie的过期时间,单位为秒,0表示删除该cookie。
cookie.setMaxAge(0) cookie.setValue("value2") cookie.setDomain("www.baidu.com");
cookie.setPath("/demo/test"); // 将cookie放入response对象中,返回给客户端。
response.addCookie(cookie);

  

  获取请求中的cookie(通过request对象来获取)

// 获取所有cookie
Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) {
System.out.println("name --> " + cookie.getName());
System.out.println("value --> " + cookie.getValue());
System.out.println("maxAge --> " + cookie.getMaxAge());
System.out.println("-----------------------------------");
if (cookie.getName().equals("id")) {
cookie.setMaxAge(0); // 销毁cookie
}
}

  

使用Session

  session基于cookie。

// 如果请求中携带有session,那么就会返回请求中的session
// 如果没有携带session,那么就创建一个session,并返回。
HttpSession session = request.getSession(); // 获取session_id,即JSESSION
String session_id = session.getId(); // 设置过期时间,不设置的话,默认是30分钟
// session失效了之后,下一次访问,服务器会重新创建一个session,并返回。
// 失效是指 指定时间端内,如果用户都没有发起请求,那么时间一到就失效
session.setMaxInactiveInterval(60); // 设置session项
session.setAttribute("name", "小强");
session.setAttribute("age", 99); // 移除session中的某一项,即使key不存在也不报错
session.removeAttribute("key"); // 获取session值,如果不包含key对应的session项,则返回null
String name = (String)session.getAttribute("name");
int age = (int)session.getAttribute("age"); // 强制session失效
session.invalidate();

  

  

对字符串数据进行编码和解码

  前面有几个地方需要注意字符编码:

  1、设置header的时候,如果设置的值包含中文,客户端接收到之后是乱码。

  2、是指cookie和session的时候,value如果包含中文,则会出现错误。

  这两种情况需要进行手动编码,使用的是java.net.URLEncoder.encode()方法,

  使用方式如下:

// 将msg按照操作系统默认的字符编码格式进行编码,然后再进行url编码
String java.net.URLEncoder.encode(String msg) // 将msg按照charset进行编码,然后再进行url编码
String java.net.URLEncoder.encode(String msg, String charset)

  

  对于请求中的header、cookie、session数据,与编码对应的是解码,使用的是java.net.URLDecoder.decode()方法:

// 将内容进行URL解码之后,再按照charset编码
java.net.URLDecoder.decode(String msg, String charset)

  

  注意上面的编码和解码方式都是:URL编码。

监听器

  监听器可以用于对request、session、servlet被创建、修改、销毁时,触发的事件处理程序。

  配置监听器有两种方式:

  1、使用注解@WebListener来标明为监听器。

  2、在web.xml中配置,格式如下:

<listener>
<listener-class>lixin.gan.listener.MyListener</listener-class>
</listener>

  

  监听器的分类如下:

  

  

  监听器可以对servlet context、session、request进行监听,监听的时候,分为两类:

  1、对初始化和销毁的监听器(XxxListener)

  2、对属性进行修改时触发的监听器(XxxAttributeListener)

  

  监听器在javax.servlet包里面。

监听器分类 监听器 方法
servlet context ServletContextListener contextInitialized(ServletContextEvent arg0)
contextDestroyed(ServletContextEvent arg0)
ServletContextAttributeListener attributeAdded(ServletContextAttributeEvent arg0)
attributeRemoved(ServletContextAttributeEvent arg0)
attributeReplaced(ServletContextAttributeEvent arg0)
     
Session HttpSessionListener sessionCreated(HttpSessionEvent arg0)
sessionDestroyed(HttpSessionEvent arg0)
HttpSessionAttributeListener attributeAdded(HttpSessionBindingEvent arg0)
attributeRemoved(HttpSessionBindingEvent arg0)
attributeReplaced(HttpSessionBindingEvent arg0)
     
request ServletRequestListener requestInitialized(ServletRequestEvent arg0)
requestDestroyed(ServletRequestEvent arg0)
ServletRequestAttributeListener attributeAdded(ServletRequestAttributeEvent arg0)
attributeRemoved(ServletRequestAttributeEvent arg0)
attributeReplaced(ServletRequestAttributeEvent arg0)

  

Servlet 快速概览的更多相关文章

  1. Servlet快速入门

    servlet是运行在服务端的java小程序,用来处理客户端请求,响应给浏览器的动态资源 servlet规范:包含3个技术点 1.servlet技术 2.filter技术 3.listener技术 s ...

  2. 【servlet】Servlet快速入门&使用Eclipse发布web项目

    创建时间:6.15 1.什么是Servlet Servlet 运行在服务端的Java小程序,是sun公司提供一套规范(接口),用来处理客户端请求.响应给浏览器的动态资源.但servlet的实质就是ja ...

  3. Servlet快速入门及运行流程

    一.Servlet快速入门 1.创建一个web工程 2.在JavaResource中src下创建一个包名称为com.myxq.servlet 3.在创建的servlet包当中创建一个class文件起名 ...

  4. Solon Cloud 分布式开发套件清单与快速概览

    Solon Cloud 是一系列的接口标准和配置规范.Solon Cloud 为常见的分布式系统模式提供了一种简单且方便的编程模式,帮助开发人员构建有弹性的.可靠的.协调的应用程序.Solon Clo ...

  5. HTTP和Servlet快速入门

    目录 1.HTTP 1.1 请求数据格式 1.2 相应数据格式 2.Servlet 3.Servlert的xml配置 1.HTTP 1.1 请求数据格式 请求行:请求数据的第一行 包含三个内容,按顺序 ...

  6. Servlet快速入门:第一个Servlet程序

    Servlet是整个JavaWeb开发的核心,同时也是一套规范,即公共接口.用于处理客户端发来的请求并作出响应.通常情况下我们会发送不同的请求并交由不同的处理程序来处理,例如处理用户信息和处理订单信息 ...

  7. Servlet 快速开始 表单中文字段

    req.getParameter | getParameterValue 一大特点是 返回null表示没有. [web.xml] <servlet> <serlvlet-mappin ...

  8. Scala快速概览

    IDEA工具安装及scala基本操作 目录 一. 1. 2. 3. 4. 二. 1. 2. 3. 三. 1. 2. 3. 4. 5. 6. 7. 四. 1. (1) (2) (3) (4) (5) ( ...

  9. 用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览

    #目录 前文列表 扩展阅读 Jinja 变量名 注释 控制语句 if 语句 循环 过滤器 无参数调用 带参数调用 宏 定义宏 调用宏 结果 兼容 JavaScript 前文列表 用 Flask 来写个 ...

随机推荐

  1. LeetCode算法题-Path Sum(Java实现)

    这是悦乐书的第169次更新,第171篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第28题(顺位题号是112).给定二叉树和整数sum,确定树是否具有根到叶路径,使得沿路 ...

  2. C语言 统计一篇英文短文中单词的个数

    //凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ #include<stdio.h> #define N 1000 void main(){ ] ...

  3. Java strictfp

    strictfp关键字 用于强制Java中的浮点计算(float或double)的精度符合IEEE 754标准. 不使用strictfp:浮点精度取决于目标平台的硬件,即CPU的浮点处理能力. 使用s ...

  4. python 时间模块(time ,datetime,calendar)

    Python中提供了时间相关的内置模块,我们主要用的是:time模块.datetime模块和calendar模块 ⽇期格式化的标准: %y 两位数的年份表示(00-99) %Y 四位数的年份表示(00 ...

  5. mongodb初级

    上班第一天,先玩玩mongdb! 1:下载安装就不说了 2:启动服务  mongod 通常会报错: 原因:mongodb会使用默认的数据库存储路径是data/db,刚安装好的mongodb是不存在该路 ...

  6. postgreSQL 应用case when的例子

    selectname,md5(indvl_id_nbr) as indvl_id_nbr,case when char_length(indvl_id_nbr)=18 or char_length(i ...

  7. redis的过期时间和过期删除机制

    一:设置过期时间 redis有四种命令可以用于设置键的生存时间和过期时间: EXPIRE <KEY> <TTL> : 将键的生存时间设为 ttl 秒 PEXPIRE <K ...

  8. dep包安装与依赖库

    安装 点击下载 .deb 包:使用sudo dpkg -i xxx.deb 命令安装 依赖库问题 用sudo apt-get install -f解决依赖问题,解决后重新运行dpkg -i安装命令 验 ...

  9. [HAOI2018]染色

    嘟嘟嘟 这题当时没想出来(因为本人实在不太擅长计数),然后又被luogu的第一篇题解吓怕了,就咕了一小段时间再写. 其实这题不是很难. 做法就是基础容斥+NTT. 首先出现\(S\)次的颜色最多有\( ...

  10. Spring事务嵌套

    学习一下Spring的事务嵌套:https://blog.csdn.net/zmx729618/article/details/77976793 重点句子: Juergen Hoeller 的话:   ...