JavaWeb学习之Servlet(1)

配置完Tomcat后就正式步入了后端JavaWeb的学习,学习servlet是JavaWeb的第一步,那下面就开始了。

先来了解HTTP事务

HTTP事务 = 请求 + 响应

通过浏览器开发者工具可以看见HTTP事务

一个完整的HTTP请求分为三部分:请求行、请求头、请求实体

1.请求行

格式为:
    请求方式 请求内容 协议名和版本

访问科大官网的请求行

请求方式最常用的有:
    GET
    POST
GET的特点是对用户可见,它在URL地址后以?开始附带数据信息,多个键值对间用&分隔;但是URL上限为2048个字节,所以对数据长度有限制
POST的特点是单独通过请求实体来向服务器发送数据,数据容量无限制
请求内容为网站的URL地址
协议和版本现在有HTTP1.0/1.1/2
其中HTTP1.1支持持久连接,在一个TCP连接上可以传送多个HTTP请求和响应,而HTTP1.0不能。

2.请求头

请求头由很多key:value组成,根据需求每次请求是不同的

这里列出一些常用的键值对:

3.请求实体

请求实体与请求头之间有一个空行分隔,并不是每次请求都带有请求实体
这里我用servlet写了一个简单的登陆界面,在这个请求头中,可以看见请求实体

HTTP响应同样分为三部分

1.响应行

格式为:
    协议版本 状态码 原因叙述
    如HTTP/1.1  200 &nbspOK
状态码及原因叙述可以在下面这个网址查询:
http://tool.oschina.net/commons?type=5

2.响应头

常用的响应头信息

3.响应实体

通常是html代码等

什么是Servlet?

Servlet是一个java类及接口,当Web应用运行在服务器上时负责接收客户端(Client)向服务器发起的HTTP请求(Request),然后再根据需要向客户端返回HTTP响应(Response)。
使用 Servlet,你可以实现通过 web 页面表单来收集用户的输入,显示从数据库或其他来源的记录,动态地创建 web页面等。

Tomcat下Servlet处理请求响应的流程
Servlet作为中间层

Servlet的生命周期

如图所示Servlet的生命周期可以被分为init()→service()→destory(),实际重写HttpServlet的方法时,我们通常要重写
init()、doGet()、doPost()方法。

init()

init 方法被设计成只调用一次。它在第一次创建 servlet 时被调用,在后续每次用户请求时不再调用。

service()

每次服务器接收到一个 servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请
求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut、doDelete 等
方法。service() 方法由容器调用,所以
对 service() 方法你什么都不需要做,只是根据你接收到的来自客户端的请求类型来重写 doGet()或 doPost()。

doGet()

GET 请求来自于一个 URL 的正常请求,或者来自于一个没有 method 指定的 html 表单,它由 doGet()处理。

doPost()

同理,处理method=post的html表单时调用。

destroy()

当你关闭servlet响应页面时执行

简单的用户登录实例,使用Servlet获取表单数据

Webapp结构

Login.html代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登陆界面Demo</title>
</head>
<link rel="stylesheet" type="text/css" href="Login.css"/>
<body><!-- 这里action中路径是在域名后直接添加的,等于127.0.0.1:8080/MyServlet/ServletStudy -->
<form action="/MyServlet/ServletStudy" method="post" id="form">
    <div class="input"><p>用户名:</p><input type="text" name="userName"/></div>
    <div class="input"><p>密码:</p><input type="password" name="userPassword"/></div>
    <div id="inputButtons"><input type="submit" value="登陆" class="button"/><input type="reset" value="清空" class="button"/></div>
</form>
</body>
</html>

Servlet.java代码

public class ServletStudy extends HttpServlet {
    private static final long serialVersionUID = 1169754202346967182L;
    @Override
    public void init() throws ServletException {
        System.out.println("===init() is called===");
        super.init();
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("===init(config) is called===");
        super.init(config);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("===doGet() is called===");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("===doPost() is called===");
        //获取请求信息
        String userName = req.getParameter("userName");
        String userPassword = req.getParameter("userPassword");
        if(userName.equals("lihaodong")&&userPassword.equals("lhd123")) {
            //转发,可以将request信息传给新页面
            RequestDispatcher rd = req.getRequestDispatcher("/userInterface.jsp");
            rd.forward(req, resp);
            //重定向,不能将requset信息发送给新页面
//          resp.sendRedirect(req.getContextPath()+"/success.jsp");
        }
        else {
        resp.sendRedirect(req.getContextPath()+"/false.jsp");
        }
    }
    @Override
    public void destroy() {
        System.out.println("===destroy() is called===");
        super.destroy();
    }
    public ServletStudy() {
        super();
    }
}

通过HttpServletRequest对象我们可以调用以下方法:
request.getParameter(key) 获取表单参数的值。
request.getParameterValues(key)如果获取的参数出现不止一次,那么调用该方法并返回多个值,例如复选框。
request.getParameterNames()得到一个当前请求的所有参数的完整列表。
其余方法,通过查相关文档可以了解具体用法,这里不再解释。

web.xml代码

写好了servlet,我们需要在部署描述符中配置servlet

  <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.lhd.servlet.ServletStudy</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/ServletStudy</url-pattern>
  </servlet-mapping>

其中servlet-name的值可以任意定,servlet-class需要输入servlet.java的完全限定名,在servlet-mapping中url-pattern声明了servlet的虚拟目录映射通过servlet-name与物理地址联系上。这样我们就可以使用127.0.0.1:8080/项目名称/servlet虚拟目录来访问servlet。

登陆成功.jsp代码

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>用户界面</title>
</head>
<body>
    <div id="mainContainer">
        <div id="info">
            <img src="" alt="" />
            <p>欢迎回来,亲爱的<%=request.getParameter("userName") %>用户</p>
            <a href="Login.html" id="logout">注销</a>
        </div>
        <div id="search">
            <form action="/MyServlet/userSearch" method="get" id="search">
                <input type="text" name="searchUser" id="searchUser"/>
                <input type="submit" value="搜索用户" id="searchButton"/>
            </form>
        </div>
    </div>
</body>
</html>

失败的jsp页面

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>你失败了大哥</title>
</head>
<style>
    #info{
        width:300px;
        height:200px;
        position:absolute;
        top:calc(50% - 100px);
        left:calc(50% - 150px);
        display:flex;
        flex-direction:column;
        align-items:center;
        justify-content:space-around;
    }
    #info>p:nth-child(1){
        font-size:30px;
        color:red;
    }
    #info>p:nth-child(2){
        font-size:18px;
    }
    #info>a{
        text-decoration:none;
    }
</style>
<body>
<div id="info">
    <p>登陆失败</p>
    <p>来自<%=request.getRemoteHost() %>的请求</p>
    <a href="Login.html">返回登陆页面</a>
</div>
</body>
</html>

这样我们就搭建好了一个基本的客户端-服务器请求相应框架
输入用户名lihaodong,密码lhd123进行登录

成功页面
失败页面

实例,使用过滤器Filter过滤不雅词汇

在上文登陆成功页面中

<div id="search">
    <form action="/MyServlet/userSearch" method="get" id="search">
        <input type="text" name="searchUser" id="searchUser"/>
        <input type="submit" value="搜索用户" id="searchButton"/>
    </form>
</div>

表示我们的搜索框会向/userSearch所映射的servlet发送搜索请求,我们为/userSearch写一个过滤器,过滤掉dashabi这个用户名,dashabi在Filter配置文件中提前声明好,也可以用其他方式。

Filter.java代码

public class FilterOne implements Filter {
    public String initParam = null;
    public FilterOne() {
    }
    public void init(FilterConfig fConfig) throws ServletException {
        System.out.println("===FilterOne init(fConfig) is called===");
        initParam = fConfig.getInitParameter("userName");
    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        System.out.println("===FilterOne doFilter() is called===");
        if(req.getParameter("searchUser").equals(initParam)) {
            req.setAttribute("alter", "您要搜索的词汇包含非法字符");
        }
        chain.doFilter(req, resp);
    }
    public void destroy() {
        System.out.println("===FilterOne destroy() is called===");
    }
}

Filter过滤器也是一个Java 类,可用于下述目的:
•在请求访问后端资源之前,拦截这些来自客户端的请求。
•在响应发送回客户端之前,处理这些来自服务器端的响应。
也就是说Filter会在servlet实例化之前init,在servlet返回响应之后init。
在这里我们使用Filter来过滤掉用户搜索的不雅词汇(雾)

web.xml代码

  <filter>
    <filter-name>FilterOne</filter-name>
    <filter-class>com.lhd.filter.FilterOne</filter-class>
    <init-param>
      <param-name>userName</param-name>
      <param-value>dashabi</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>FilterOne</filter-name>
    <url-pattern>/userSearch</url-pattern>
  </filter-mapping>

filter的配置与servlet类似,filer中可以设置初始化参数init-param,filter-mapping中url-pattern设置过滤的url路径,通常是servlet的虚拟目录

UserSearchServlet.java代码

public class UserSearchServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public UserSearchServlet() {
        super();
    }
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter pw = resp.getWriter();
        if(req.getAttribute("alter")!=null) {
            pw.println(req.getAttribute("alter").toString());
        }
        else {
            pw.println("您要寻找的"+req.getParameter("searchUser")+"用户搜索结果如下"+"<br/><br/>");
        }
        pw.close();
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

对应的配置文件略过

当我们输入dashabi时

Filter过滤

当输入haha时,不会被Filter过滤

小结:
课外学习真的不容易,我要写作业了。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容