你是Tomcat,我是Servlet,我这一生最幸福的事就是为你鞍前马后

一、HttpServlet

方法
doGet处理 GET 请求
doPost处理POST请求
doPut/Delete…处理其他方法的请求
initHttpServlet实例化后调用一次
service收到HTTP请求时调用
destoryHttpServlet对象不再使用后调用一次)
Servlet的生命周期:
  • Servlet对象是由Tomcat实例化的,并在实例化完成后调用init()方法
  • Tomcat 收到的每一个请求,都通过对应的 Servlet 的service()方法处理
  • Tomcat 在结束之前,会调用 Servlet 的 destroy 方法(直接杀死进程时(直接关闭进程),不调用;通过Tomcat的管理端口(8005)关闭时,调用

二、HttpServletRequest

Tomcat通过Socket API读取HTTP请求(字符串),按照HTTP协议的格式把字符串解析成HttpServletRequest对象

  • IDEA使用utf-8编码;浏览器默认跟随操作系统的编码方式,不一定是按照utf-8编码的;所以解析数据时会出现问题,需要声明编码方式
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

1. 获取参数

(1). 获取 queryString 中的参数(value)

// 获取程序猿传递的参数 GET方法通过queryString传递,用getParameter获取
@WebServlet("/showGetParameter")
public class showGetParameter extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        resp.getWriter().write("username = " + username + "</br>" + "password = " + password);
    }
}

(2). body 中的参数(value)

  • x-www-form-urlencode格式( 与queryString中的格式相同)
//获取程序员传递的参数 请求通过body传递参数,x-www-form-urlencoded格式,用getParameter
@WebServlet("/PostParameter")
public class PostParameter extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        resp.getWriter().write("username = " + username + "</br>" + "password = " + password);
    }
}
  • json 格式

需要使用 Jackson 第三方库了,在pom.xml中引入 Jackson 库
关键类 ObjectMapper
关键方法 readValue

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.1</version>
        </dependency>
// 此处Message的成员变量名,要和body中的key对应
class Message {
    public String username;
    public String password;
}
@WebServlet("/Json")
public class JsonParaServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf8");
        // Jackson 中的类,用于解析json
        
        ObjectMapper mapper = new ObjectMapper();
        // 一个message就是一个json对象,mapper遍历Message中成员属性,再去找到相应的body中的key,将value赋值给成员属性  
        // Message.class是类对象,告诉mapper把json转成哪个类的对象
        Message message = mapper.readValue(req.getInputStream(),Message.class);
        resp.getWriter().write("username = " + message.username + "</br>" + "password = " + message.password);
    }
}
  • readValue() 参数可以是 String(body内容组成的字符串)、InputStream(body的字节流对象)、byte[ ](body内容组成的字节数组)、
class Message {
    public String username;
    public String password;
}
@WebServlet("/Json")
public class JsonParaServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf8");
        ObjectMapper mapper = new ObjectMapper();
        Message message = mapper.readValue(readBody(req),Message.class);
        resp.getWriter().write("username = " + message.username + "</br>" + "password = " + message.password);
    }

    public String readBody(HttpServletRequest req) throws IOException {
        // 得到body的字节流对象
        InputStream inputStream = req.getInputStream();
        // 获取body的长度,单位是字节
        int len = req.getContentLength();
        // 字节数组 存放body内容
        byte[] bytes = new byte[len];
        inputStream.read(bytes);
        // 需要说明的是,此处字节数组(二进制数据)以字节为单位,字符串(文本数据)以字符为单位,要指定字符集,说明字节数组当前的编码方式,用这种编码方式来解析字节数组,转变成字符串
       // java 使用Unicode字符集编码,一个字符是两个字节;但是此处的从body中读入的字节数组可不一定是使用Unicode编码的
        String body = new String(bytes, "utf8");
        return body;
    }
}

2、获取请求中的其他内容

@WebServlet("/showRequest")
public class showRequest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charser=utf-8");
        StringBuilder html = new StringBuilder();
        //获取方法
        html.append(req.getMethod());
        html.append("</br>");
        //获取URL
        html.append(req.getRequestURI());
        html.append("</br>");
        //获取协议名
        html.append(req.getProtocol());
        html.append("</br>");
        //获取ContextPath
        html.append(req.getContextPath());
        html.append("</br>");
        //获取queryString
        html.append(req.getQueryString());
        html.append("</br>");
        html.append("</br>");
        html.append("</br>");
        html.append("</br>");
        //将请求头的key放到一个枚举数组
        Enumeration<String> headers = req.getHeaderNames();
        while(headers.hasMoreElements()){
            String headerName = headers.nextElement();
            html.append(headerName);
            html.append(": ");
            //获取相对应的value
            String value = req.getHeader(headerName);
            html.append(value);
            html.append("</br>");
        }
        resp.getWriter().write(html.toString());
    }

在这里插入图片描述

三、HttpServletResponse

  1. doXXX方法根据请求,计算得到响应,把响应的数据涉及到HttpServletResponse中
  2. Tomcat 把这个对象按照HTTP协议的格式,转成一个字符串,通过Socket写给服务器
@WebServlet("/status")
public class statusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        // 设计一个header,key相同会覆盖旧值
        resp.setHeader("qust","rubbish");
        // 设计一个header,key相同不会覆盖旧值
        resp.addHeader("qust","strong");
       // 重定向,页面自动跳转到 百度界面
        resp.sendRedirect("http://www.baidu.com");
        //设置状态码
        resp.setStatus(404);
        resp.getWriter().write("状态码不影响body的内容d");
    }
}

1、自动刷新
页面每隔1s刷新一次,设置响应头

@WebServlet("/autoRefresh")
public class autoRefresh extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        resp.setHeader("Refresh","1");
        resp.getWriter().write("时间是:  " + System.currentTimeMillis());
    }
}
  • 设置响应的body 为json格式,此时前端的响应对象data就是一个数组,里面的每一个对象就是一个json信息

注意设置ContentType,即设置 body内容的类型,为 application/json

class Message {
    public String from;
    public String to;
    public String mes;
}

@WebServlet("/MessageWail")
public class MessageWail extends HttpServlet {
    private List<Message> messages = new ArrayList<Message>();
   
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf-8");
        ObjectMapper objectMapper = new ObjectMapper();
        // 将messages数组中的消息对象都转变成 json形式的内容
        String jsonString = objectMapper.writeValueAsString(messages);
        resp.getWriter().write(jsonString);
    }

四、在Servlet程序中同时部署静态页面

将HTML文件放到webapps目录下面,可通过静态页面向服务器发送请求
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    //此处是相对路径,HTML和PosTParameter同在一个ContextPath下
    <form action="PostParameter" method="POST">
        <input type="text" name="username">
        <input type="text" name="password">
        <input type="submit" value="提交">
    </form>
</body>
</html>

六、Session 和 Cookie

第一次登录CSDN后,后面在登录的时候直接跳转到博客主页面,而不是登录页面;此处就是应用了 Session和Cookie 共同存储用户信息

  • Session(会话)是服务器存储数据的一种机制,键值对结构,主要用于存储用户的各种信息
  • Cookie 是浏览器(客户端)存储数据的一种机制,键值对结构,主要用于存储用户的各种信息
  • HttpSession是存储在服务器内存中的,当服务器重启之后,内存中的数据就没有了,原来的HttpSession也就没有了

使用Session和Cookie共同存储用户信息

  • 可以使客户端轻量;客户端和服务器传输的资源减少,节约网络带宽;数据都在服务器,客户端出现问题,数据不会有损害
  • 用户第一次登录webapp(网站)时,服务器生成一个会话(键值对),key是sessionId,value是HttpSession对象,HttpSession对象也是一个键值对结构,存储用户信息;将sessionId通过Set-Cookie返回给浏览器存储;再次登录时,客户端通过Cookie传送sessionId(Cookie中所有的东西都传),服务器找到相应的用户信息
  • sessionId是唯一的,每一个用户都有一个唯一的sessionId
  • Httpsession中的信息是程序员自定义的

在这里插入图片描述

方法

  • HttpServletRequest类的方法
  • HttpSession getSession()
  • 参数是true
    根据请求传来的sessionId,如果找到对应的HttpSession对象,返回此对象
    如果没有找到,新建一个键值对(sessionId + HttpSession)
  • 参数是false
    根据请求传来的sessionId,如果找到对应的HttpSession对象,返回此对象
    如果没有找到,直接返回
  • Cookie [ ] getCookie()
    每一个Cookie对象就是一个键值对
  • HttpSession类的方法
  • Object getAttribute(String key)
    根据key获取value
  • void setAttribute(String key, Object value)
    设置一个键值对

七、登录程序的实现

  1. 读取用户名和密码
  2. 校验用户名和密码
  3. 判断是否登录成功
  4. 创建会话,保存自定义信息
  5. 重定向界面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登入页面</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text" name="username">
        <input type="text" name="password">
        <input type="submit" value="提交">
    </form>
</body>
</html>
//登入流程 固定套路
@WebServlet("/login")
public class SessionServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        // 1.读取用户的用户名和密码
        // form标签body中的参数是 queryString的形式,通过getParameter()获取参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");


        // 2.校验用户名和密码
        if(username == null || username.equals("") || password == null || password.equals("")){
            resp.getWriter().write("<h3>用户名或密码为空</h3>");
            return;
        }
        // 3. 判断是否登入成功
        // 此处规定用户名为 Guo, 密码是 123456, 正常情况下,用户名和密码是存储在数据库中的
        if(!username.equals("Guo") || !password.equals("123456")){
            resp.getWriter().write("<h3>用户名或密码错误<h3>");
            return;
        }

        // 4.创建会话,保存自定义信息
        HttpSession httpSession =  req.getSession(true);
        // 添加一个登入次数
        httpSession.setAttribute("visited",0);

        // 5.重定向页面,页面名称就是index,重定向的请求是GET方法
        resp.sendRedirect("index");
    }
}

在这里插入图片描述

@WebServlet("/index")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        // 获取 HttpSession 对象,参数是false,如果没有 对应的sessionID 不会创建 HttpSession对象
        HttpSession session = req.getSession(false);
        if(session == null){
            resp.getWriter().write("<h3>当前未登录,兄弟</h3>");
            return;
        }
        // 获取访问次数
        Integer count = (Integer) session.getAttribute("visited");
        count++;
        // 将新的访问次数返回到 HttpSession 对象中
        session.setAttribute("visited",count);
        // 显示访问次数
        resp.getWriter().write("visited =   " + count);
    }
}

在这里插入图片描述

八、下载文件

  • webapp目录下的 upload.html
    ebctype就是设置body的格式,默认是 x-www-from-urlencode
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="upload" method="post" enctype="multipart/form-data">
        <input type="file" name="MyFile">
        <input type="submit" value="提交">
    </form>
</body>
</html>

在这里插入图片描述

  • Java文件必须添加注解 @MultipartConfig
  • 通过getPart()方法获得文件
//只有添加这个注解,才能使用getPart方法
@MultipartConfig
@WebServlet("/upload")
public class FileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.通过 getPart() 获取前端传来的文件
        Part part = req.getPart("MyFile");
        System.out.println(part.getSubmittedFileName());
        System.out.println(part.getSize());
        System.out.println(part.getContentType());
        // 2.把传来的文件放到指定位置
        part.write("C://user");
        resp.getWriter().write("upload ok");
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

威少总冠军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值