Servlet

概念

Servlet就是一个接口,定义了Java被浏览器访问到(tomcat识别)的规则。
自定义一个类,实现Servlet接口,复写方法。

快速入门

  1. 创建JavaEE项目
  2. 定义一个类,实现Servlet接口
  3. 实现接口中的抽象方法
  4. 配置Servlet
    在web.xml中配置:
<!-- 配置servlet-->
    <servlet>
        <servlet-name>demo1</servlet-name>
        <servlet-class>nuc.servlet.ServletDemo1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>

Servlet中的生命周期:

  1. 被创建:执行init方法,只执行一次
  2. 提供服务:执行servlet方法,执行多次
  3. 被销毁:执行destroy方法,只执行一次

Servlet3.0:支持注解配置,不需要web.xml

  • 在类上使用@webServlet注解,进行配置@WebServlet("资源路径")
@WebServlet("/demo")
public class ServletDemo implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet4.0!");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

HttpServlet

HttpServlet:对http协议的一种封装,简化操作

  1. 定义类继承HttpServlet
  2. 重写doGet / doPost方法
@WebServlet("/demo")
public class ServletDemo extends HttpServlet{

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

HTTP

概念:Hyper Text Transfer Protocol 超文本传输协议

传输协议:定义了客户端和服务端通信时,发送数据的格式

特点:

  1. 基于TCP / IP 的高级协议
  2. 默认端口号:80
  3. 基于请求 / 响应模型的:一次请求对应一次响应
  4. 无状态的:每次请求之间相互独立,不能交互数据

历史版本:
1.0:每一次请求响应都会建立新的连接
1.1:复用连接

请求消息数据格式

  1. 请求行
    请求方式 请求url 请求协议/版本htmlGET / login.html HTTP/1.1
    请求方式:
    get:

    1. 请求参数在请求行中,在url后
    2. 请求的url长度是有限的
    3. 不太安全

    post:

    1. 请求参数在请求体中
    2. 请求的url长度没有限制
    3. 相对安全
  2. 请求头
    请求头名称:请求头值
    常见的请求头:

    1. user-agent:浏览器告诉服务器,我访问你使用的浏览器版本信息

      可以在服务器端获取该头的信息,解决浏览器的兼容问题

    	String agent = request.getHeader("user-agent");
        if (agent.contains("Chrome")){
            // 谷歌浏览器的操作
            System.out.println("谷歌来了...");
        } else if (agent.contains("Chrome")){
            // 火狐浏览器操作
        }
    
    1. referer:告诉服务器,我(当前请求)从哪里来

      作用:防盗链,统计工作

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<a href="/RequestDemo2"></a>

</body>
</html>

RequestDemo2.java

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String referer = request.getHeader("referer");
        response.setContentType("text/html;charset=utf-8");

        // 判断是否盗链
        if (referer != null) {
            if (referer.contains("/myapp")) {
                response.getWriter().write("来看电影~");
            } else {
                response.getWriter().write("盗链可耻!");
            }
        }
    }

  1. 请求空行
    空行,就是用于分割POST请求的请求头,和请求体的
  2. 请求体
    封装post请求消息的请求参数的

Request

request对象是来获取请求消息,response对象是来设置响应消息

获取请求消息

  1. 获取请求行数据
    	// 获取请求方式 GET
        String method = request.getMethod();
        System.out.println(method);
    
        // (*)获取虚拟目录 /Servlet_war_exploded
        String contextPath = request.getContextPath();
        System.out.println(contextPath);
    
        // 获取Servlet路径 /RequestDemo1
        String servletPath = request.getServletPath();
        System.out.println(servletPath);
    
        // 获取get方式请求参数 name=zhangsan
        String queryString = request.getQueryString();
        System.out.println(queryString);
    
        // (*) 获取请求URI /Servlet_war_exploded/RequestDemo1
        String requestURI = request.getRequestURI();
        System.out.println(requestURI);
    
        // 获取请求URL http://localhost:8080/Servlet_war_exploded/RequestDemo1
        StringBuffer requestURL = request.getRequestURL();
        System.out.println(requestURL);
    
        // 获取协议及版本 HTTP/1.1
        String protocol = request.getProtocol();
        System.out.println(protocol);
    
        // 获取客户机的IP地址 0:0:0:0:0:0:0:1
        String remoteAddr = request.getRemoteAddr();
        System.out.println(remoteAddr);
    
  2. 获取请求头数据
    	// 演示获取请求头数据
        Enumeration<String> headerNames = request.getHeaderNames();  // 获取所有的请求头名称
        while(headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            String value = request.getHeader(name);   // 通过请求头的名称获取请求头的值
            System.out.println(name + ":" + value);
        }
    
  3. 获取请求体数据
    请求体:只有post请求方式,才有请求体,在请求体中封装了post请求的请求参数
    步骤:
    1. 获取流对象
    2. 再从流对象中拿数据

regist.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>regist</title>
</head>
<body>
<form action="/demo" method="post">
    用户名<input type="text" name="username"><br/>
    密码<input type="text" name="password"><br/>
    <input type="submit" value="提交"><br/>
</form>
</body>
</html>

demo.java

	@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        BufferedReader br = req.getReader();
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    }
  1. 其他功能:不论还是post请求方式都可使用下列方法来获取请求参

获取请求参数通用方式

RequestDemo5.java

@WebServlet("/requestDemo5")
public class RequestDemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // post 获取请求参数
        request.setCharacterEncoding("utf-8");

        // 根据参数名称获取参数值
        String username = request.getParameter("username");
        System.out.println(username);
        System.out.println("------------------------");

        // 根据参数名称获取参数值的数组
        String[] hobbies = request.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
        System.out.println("-------------------------");

        // 获取所有请求的参数名称
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String name = parameterNames.nextElement();
            System.out.println(name);
        }
        System.out.println("-------------------------");

        // 获取所有参数的map集合
        Map<String, String[]> parameterMap = request.getParameterMap();
        // 遍历
        Set<String> keySet = parameterMap.keySet();
        for (String name : keySet) {
            // 获取键获取值
            String[] values = parameterMap.get(name);
            System.out.println(name);
            for (String value :values) {
                System.out.println(value);
            }
            System.out.println("----------------------------");
        }

    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

}

regist.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>regist</title>
</head>
<body>
<form action="/day15/requestDemo5" method="post">
    用户名<input type="text" name="username"><br/>
    密码<input type="text" name="password"><br/>

    <input type="checkbox" name="hobby" value="game">游戏
    <input type="checkbox" name="hobby" value="study">学习

    <input type="submit" value="注册"><br/>
</form>
</body>
</html>
  • 中文乱码问题:
    get:tomcat 8 已经将get方式乱码问题解决了
    pos:会乱码
    解决:在获取参数前,设置request的编码:request.setCharacterEncoding("utf-8");

请求转发

请求转发:一种在服务器内部的资源跳转方式

RequestDemo3.java

@WebServlet("/RequestDemo3")
public class RequestDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("333被访问了");

        // 转发到demo4资源
        request.getRequestDispatcher("/RequestDemo4").forward(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        this.doPost(request,response);
    }

}

RequestDemo4.java

@WebServlet("/RequestDemo4")
public class RequestDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("444被访问了");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        this.doPost(request,response);
    }

}

特点:

  1. 浏览器地址栏路径不发生变化
  2. 只能转发到当前服务器内部资源中
  3. 转发是一次请求

共享数据

域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

RequestDemo3.java

@WebServlet("/RequestDemo3")
public class RequestDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 存储数据到request域中
        request.setAttribute("msg", "hello");

        // 转发到demo4资源
        request.getRequestDispatcher("/RequestDemo4").forward(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        this.doPost(request,response);
    }

}

RequestDemo4.java

@WebServlet("/RequestDemo4")
public class RequestDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 获取数据
        Object msg = request.getAttribute("msg");
        System.out.println(msg);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        this.doPost(request,response);
    }

}

获取ServletContext

		ServletContext servletContext = request.getServletContext();
        System.out.println(servletContext);

Response

HTTP协议

  1. 请求消息:客户端发送给服务器端的数据
    数据格式:
    1. 请求行
    2. 请求头
    3. 请求空行
    4. 请求体
  2. 响应消息:服务器端发送给客户端的数据
    数据格式:
    1. 响应行
      1. 组成:协议/版本 响应状态码 状态码描述
      2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
        分类:
        1. 1xx:服务器接收客户端信息,但没有接收完成,等待一段时间后,发送1xx多状态码
        2. 2xx:成功。200
        3. 3xx:重定向。302(重定向),304(访问缓存)
        4. 4xx:客户端错误。404(请求路径没有对应的资源),405(请求方式没有对应的doXxx方法)
        5. 5xx:服务器端错误。500(服务器内部出现异常)
    2. 响应头
      1. 格式:头名称:值
      2. 常见的响应头:
        1. content-type:服务器告诉客户端本次响应体数据格式以及编码格式
        2. content-disposition:服务器告诉客户端以什么格式打开响应体数据
          in-line:默认值,在当前界面内打开
          attachment;filename=xxx:以附件形式打开响应体。文件下载
    3. 响应空行
    4. 响应体

Response对象

功能:设置响应消息

  1. 设置响应行

    1. 格式:HTTP/1.1 200 ok
    2. 设置状态码:setStatus(itn sc)
  2. 设置响应头

    setHeader(String name, String value)
    
  3. 设置响应体
    步骤:

    1. 获取输出流
    2. 使用输出流,将数据输出到客户端浏览器

案例

完成重定向

重定向:资源跳转的方式

	@WebServlet("/responseDemo1")
	public class ResponseDemo1 extends HttpServlet {
   	 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        	System.out.println("demo1...");
        	// 访问ResponseDemo1,直接跳转到responseDemo2
        	// 设置状态码为302
        	/*response.setStatus(302);
        
	        // 设置响应头为location
	        response.setHeader("location", "/day15/responseDemo2");*/
        
        	// 简单的重定向方法
        	response.sendRedirect("/day15/responseDemo2");

    	}

    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

       	 this.doPost(request,response);
    	}
	}

重定向的特点:(redirect)

  1. 地址栏发生变化
  2. 重定向可以访问其他站点(服务器)的资源
  3. 重定向是两次请求

转发的特点:(forward)

  1. 转发地址栏路径不变
  2. 转发只能访问当前服务器下的资源
  3. 转发是一次请求

考点:forward 和 redirect 的区别

路径的写法

路径分类:

  1. 相对路径:通过相对路径不可以确定唯一资源
    如:./index.html
    规则:找到当前资源和目标资源之间的相对位置关系
    ./:当前目录
    ../:后退一级目录
  2. 绝对路径:通过绝对路径可以确定唯一资源
    如:http://localhost:8080/day15/responseDemo2 , /day15/responseDemo2
    规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出.
    1. 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)

      建议虚拟目录动态获取:request.getContextPath()

    2. 给服务器使用:不需要加虚拟目录(用于转发路径)

服务器输出字符数据到浏览器
	@WebServlet("/responseDemo3")
	public class ResponseDemo3 extends HttpServlet {
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	// 首先设置编码格式
        	response.setContentType("text/html;charset=utf-8");
        	// 1. 获取字符输出流
	       	 PrintWriter pw = response.getWriter();
        	// 2. 输出数据
        	pw.write("你好");
    	}

	   	 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	this.doPost(request,response);
    	}
	}

注意:乱码问题

  1. PrintWriter pw = response.getWriter(); 获取的流的默认编码是ISO-8859-1
  2. 设置该流的默认编码
  3. 告诉浏览器响应体使用的编码:response.setContentType("text/html;charset=utf-8");
服务器输出字节数据到浏览器
	@WebServlet("/responseDemo4")
	public class ResponseDemo4 extends HttpServlet {
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	response.setContentType("text/html;charset=utf-8");
        	// 1. 获取字节输出流
        	ServletOutputStream sos = response.getOutputStream();
        	// 2. 输出数据
        	sos.write("你好".getBytes("utf-8"));

    	}

    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	this.doPost(request,response);
    	}
	}
验证码

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        /**
         * 分析:
         * 1. 给图片绑定单击事件
         * 2. 重新设置图片的src属性值
         */
        window.onload = function () {
            var img = document.getElementById("checkCode");
            img.onclick = function () {
                // 加时间戳
                var date = new Date().getTime();
                img.src = "/day15/checkCodeServlet?"+date;
            }
        }
    </script>
</head>
<body>
<img id="checkCode" src="/day15/checkCodeServlet"/>
</body>
</html>

CheckCodeServlet.java

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int width = 100;
        int height = 50;

        // 1. 创建一对象,在内存中图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 2. 美化图片
        // 2.1 填充背景色
        Graphics g = image.getGraphics();
        g.setColor(Color.PINK);
        g.fillRect(0,0,width,height);

        // 2.2 画边框
        g.setColor(Color.BLUE);
        g.drawRect(0,0,width - 1, height - 1);

        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        // 生成随机坐标
        Random random = new Random();

        for (int i = 1; i <=4 ; i++) {
            int index = random.nextInt(str.length());
            // 获取字符
            char ch = str.charAt(index);
            // 2.3 写验证码
            g.drawString(ch + "", width / 5 * i, height / 2);
        }

        // 2.4 画干扰线
        g.setColor(Color.GREEN);

        // 随机生成坐标点
        for (int i = 0; i < 10; i++) {
            int x1 = random.nextInt(width);
            int x2 = random.nextInt(width);

            int y1 = random.nextInt(height);
            int y2 = random.nextInt(height);

            g.drawLine(x1,y1,x2,y2);

        }

        // 3. 将图片输出到页面展示
        ImageIO.write(image,"jpg", response.getOutputStream());

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        this.doPost(request, response);
    }
}

ServletContext对象

概念:代表整个web应用,可以和程序的容器(服务器)来通信

获取:

		// 1. 通过request对象获取
        ServletContext context1 = request.getServletContext();
        // 2. 通过HttpServlet获取
        ServletContext context2 = this.getServletContext();

功能:

  1. 获取MIME类型
    1. MIME类型:在互联网通信过程中定义的一种文件数据类型
    2. 格式: 大类型 / 小类型 text/html , image/jpeg
    3. 获取:
		// 定义文件名称
        String filename = "a.jpg";
        // 获取MIME类型
        String mimeType = context2.getMimeType(filename);
        System.out.println(mimeType);  // image/jpeg
  1. 域对象:共享数据

ServletContextDemo2.java

@WebServlet("/servletContextDemo2")
public class ServletContextDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 通过HttpServlet获取
        ServletContext context = this.getServletContext();
        // 设置数据
        context.setAttribute("msg", "haHa");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

ServletContextDemo3.java

@WebServlet("/servletContextDemo3")
public class ServletContextDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 通过HttpServlet获取
        ServletContext context = this.getServletContext();
        // 获取数据
        Object msg = context.getAttribute("msg");
        System.out.println(msg);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • ServletContext对象范围:所有用户所有请求的数据
  1. 获取文件的真实(服务器)路径
		// 通过HttpServlet获取
        ServletContext context = this.getServletContext();

        // 获取文件的服务器路径
        String realPath = context.getRealPath("/b.txt");  // web目录下资源访问
        System.out.println(realPath);

        String realPath1 = context.getRealPath("/WEB-INF/c.txt");  // WEB-INF目录下的资源访问
        System.out.println(realPath1);

        String realPath2 = context.getRealPath("/WEB-INF/classes/a.txt");  // src目录下的资源访问
        System.out.println(realPath2);

以上为个人学习笔记,参考自黑马教程,若有雷同,纯属巧合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值