《JavaEE初阶》Servlet

《JavaEE初阶》Servlet

文章目录

  • 《JavaEE初阶》Servlet
    • 编写一个Servlet的helloworld
      • 1. 认识Maven并创建maven项目:
      • 2. 引入依赖:
      • 3.创建目录:
      • 4. 编写代码:
      • 5. 打包
      • 6. 部署
      • 7.验证
    • 优化打包部署操作.
      • 常见的错误:
    • ServletAPI:
      • 利用ajax构造请求.
      • 使用第三方工具postman构造请求
      • HttpServlet:
      • HttpServletRequest
      • Jackson
      • HttpServletResponse
      • 代码案例:
        • 自我刷新页面
        • 重定向
    • 实现一个表白墙网页
      • 准备工作:
      • 确定前后端交互信息:
      • 实现提交数据:
      • 实现返回数据
      • 实现数据库版本
      • 完整代码:
    • cookie与session
      • Servlet中相关类与方法.
        • HttpServletRequest
        • HttpServletResponse
        • HttpSession
      • 实现一个登录页面
    • 使用Servlet上传文件.
      • 相关方法与类
        • HttpServletRequest
        • Part类方法
      • 实现一个上传文件页面

编写一个Servlet的helloworld

1. 认识Maven并创建maven项目:

Maven是一个"构造工具",它能针对代码进行依赖管理,编译,打包,验证,部署等功能.

在我们之前学习的代码较为简单,并不需要进行打包.

而在一个复杂的项目中,依赖许多的第三方库,并且可能有多个模块,模块与模块之间存在依赖关系,这个时候就可以将Maven作为一个针对复杂项目进行管理的解决方案.

在Java中,也有其他构建工具,但Maven是当下最主流的构建工具.当然其他语言也有自己的构建工具.

我们使用Maven主要是以下两个功能

  • 管理依赖: 使用maven将第三方库下载并导入项目.

  • 打包: 将代码编译好并且将.class文件压缩为.jar或者.war文件

典型的Maven项目文件结构:

《JavaEE初阶》Servlet_第1张图片

src:

  • main : 放业务代码

    • java : 存放java代码

    • resources: 存放代码依赖的资源:图片,HTML,CSS等等.

  • test: 放测试代码

  • prm.xml: maven 项目中 最核心的文件,描述这个项目的属性信息.

使用IDEA创建一个maven文件

2. 引入依赖:

我们在maven项目中写servlet程序,这需要引入依赖(servlet的jar包).

在网站中下载servlet 3.1

Maven Repository: javax.servlet » javax.servlet-api » 3.1.0 (mvnrepository.com)

《JavaEE初阶》Servlet_第2张图片

使用 dependency 标签将代码复制进pom.xml中,等待IDEA自动下载.

3.创建目录:

这里的创建目录必须严格按照以下格式,因为这是tomcat的硬性要求,为了让我们的程序被tomcat识别,不可自己修改.

在main目录下创建以下文件

《JavaEE初阶》Servlet_第3张图片

并且在web.xml中复制粘贴:

DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Archetype Created Web Applicationdisplay-name>
web-app>

4. 编写代码:

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.io.IOException;
@WebServlet("/hello")
public class Helloservlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello world");
        resp.getWriter().write("hello world");
    }
}

代码解析:

  • HttpServlet来自于我们之前引入的Servlet jar包的.如果我们之前maven引入Servlet失败,这里就会报错.

  • 对于这个代码,是不需要我们写main方法的,main方法在tomcat 中, 由tomcat 在适当的时机调用.

  • HttpServletRequest req, HttpServletResponse resp分别对应HTTP请求和HTTP响应.

    HttpServletRequest req 在执行doget会解析 HTTP 请求并写入req.

    HttpServletResponse resp 在执行doget会先是一个空对象, 当服务器返回响应后再写入resp.

  • System.out.println(“hello world”); 并不会打印到浏览器页面上,会作为tomcat的运行日志并打印在控制台

  • resp.getWriter().write(“hello world”); 打印在浏览器页面.

  • @WebServlet(“/hello”) 这个注解约定了HTTP请求上的URL是什么path.

5. 打包

这个较为简单,我们直接点击maven,按下package,就会将package以及上述操作执行完毕.
《JavaEE初阶》Servlet_第4张图片

但是这里得到的是jar包,而Tomcat能识别的却是war包,所以我们需要在maven的pom.xml增加以下信息

    <packaging>warpackaging>

    <build>
        <finalName>hello_servletfinalName>
    build>

第一句可以控制我们打包后生成的压缩包是一个war包

第二句可以控制我们打包后生成的压缩包名字.

6. 部署

将我们生成的war包复制粘贴到我们的webapps目录下

7.验证

尝试去利用回环ip的path访问这个网页.

优化打包部署操作.

我们已经在写出上面的代码过程中,我们可以发现1 2 3 是每次项目创建时都必不可少的,我们无法进行更加简单的优化让这个更加便捷,4 是我们自己编写的代码,也不能优化,对于7 是我们的自行测试,

而如果不进行优化打包部署操作,我们每一次修改代码,就需要再一次打包,复制粘贴去tomcat并重启tomcat,这个 操作是非常不方便我们进行开发的.

所以我们需要利用一个IDEA插件来帮助我们完成这个操作.

《JavaEE初阶》Servlet_第5张图片
《JavaEE初阶》Servlet_第6张图片

常见的错误:

  • 404 : 大概率是URL写错了.或者web.xml写错了

  • 405: method not allow, 如果这个请求是post请求,但是只实现了doget方法.

  • 500 : 服务器挂了,一般就是代码报错导致启动失败.

  • 返回空白页面: 应该是忘记写write了

  • 无法访问此网站: tomacat没有正确启动.

ServletAPI:

我们在之前已经学习了使用from和ajax构造HTTP请求,

利用ajax构造请求.

在这个目录下创建tset.html写我们的ajax请求

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>Documenttitle>
head>
<body>
<script src="https://code.jquery.com/jquery-3.6.1.min.js">script>
<script>

     <script src="jquery.min.js">script>
<script>
    $.ajax({
        type:'GET',
        url: 'hello',
        success: function(body){

             console.log(body);
          }
        })

 script>
body>
html>

使用第三方工具postman构造请求

我们虽然可以使用ajax来构造我们的HTTP请求,但每一次构造请求都显得过于复杂,需要我们每一次都手写ajax代码来构造.

而使用postman则不需要这么复杂了.

下载postman

https://www.postman.com

使用postman构造HTTP请求:
《JavaEE初阶》Servlet_第7张图片
《JavaEE初阶》Servlet_第8张图片

HttpServlet:

  1. init

    在 HttpServlet 实例化之后被调用一次

  2. destory

    在 HttpServlet 实例不再使用的时候调用一次

  3. service

    收到 HTTP 请求的时候调用

  4. doGet

    收到 GET 请求的时候调用(由 service 方法调用)

  5. doPost

    收到 POST 请求的时候调用(由 service 方法调用)

  6. doPut/doDelete/doOptions/…

    收到其他请求的时候调用(由 service 方法调用)

我们一般只重写doxxx方法,对于不同方法的HTTP请求会调用对应的doxxx方法.

HttpServlet的生命周期:

HttpServlet实例化之后先调用一次init,在收到HTTP请求之后会调用service,在service内部调用对应请求的doxxx方法,当HttpServlet实例不再使用再调用destroy.

《JavaEE初阶》Servlet_第9张图片

HttpServletRequest

表示一个HTTP请求,我们可以通过它的方法来获得HTTP请求的各种信息(方法,URL,版本号,header,body)

方法 简介
String getProtocol() 获取请求协议的版本和名称
String getMethod() 获取请求协议的方法
String getRequestURI() 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。
String getContextPath() 返回指示请求上下文的请求 URI 部分。
String getQueryString() 返回包含在路径后的请求 URL 中的查询字符串。
Enumeration
getParameterNames() 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。
String getParameter(String
name) 以字符串形式返回请求参数的值,或者如果参数不存在则返回null。
String[]
getParameterValues(String
name) 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null.
Enumeration
getHeaderNames() 返回一个枚举,包含在该请求中包含的所有的头名。
String getHeader(String
name) 以字符串形式返回指定的请求头的值。
String getCharacterEncoding() 返回请求主体中使用的字符编码的名称。
String getContentType() 返回请求主体的 MIME 类型,如果不知道类型则返回 null。
int getContentLength() 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。
InputStream getInputStream() 用于读取请求的 body 内容. 返回一个InputStream 对象.
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/testreq")
public class testreq extends Helloservlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //设置返回响应的字符集,使得br能被正确解析.
        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write(req.getMethod());
        resp.getWriter().write("
"
); resp.getWriter().write(req.getProtocol()); resp.getWriter().write("
"
); resp.getWriter().write(req.getContextPath()); resp.getWriter().write("
"
); resp.getWriter().write(req.getRequestURI()); resp.getWriter().write("
"
); resp.getWriter().write(req.getQueryString()); resp.getWriter().write("
"
); Enumeration<String> enumeration = req.getHeaderNames(); while(enumeration.hasMoreElements()){ String headernanme = enumeration.nextElement(); resp.getWriter().write(req.getParameter(headernanme)); resp.getWriter().write("
"
); } resp.getWriter().write("这里结束"); } }

如果我们发送的是post请求,这需要使用dopost方法:

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write("Studentid = " +  req.getParameter("Studentid"));
        resp.getWriter().write("
"
); resp.getWriter().write("Classid = " + req.getParameter("Classid")); }

我们在之前的学习就已经知道post是利用body来传送数据, 在body中的数据一般以这两种数据来组织格式:

  • application/x-www-from-urlencode

  • application/json

而application/x-www-from-urlencode 就是一些简单的键值对,是比较好解析,我们可以直接利用 req.getParameter () 直接解析

而对于json,java并不能很好的解析出内容,所以我们需要使用第三方库:

Jackson

Maven Repository: com.fasterxml.jackson.core » jackson-databind » 2.13.4 (mvnrepository.com)

跟我们之前一样的进行引入依赖.即可

Jackson的使用也比较简单:需要两步:

  • 将json格式的字符串转成java对象.

  • 把java对象转成json字符串

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
class Student{
    public String Studentid;
    public String Classid;
}
@WebServlet("/jacksontest")
public class jacksontest extends Helloservlet{
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        Student student = objectMapper.readValue(req.getInputStream(),Student.class);
        resp.getWriter().write(student.Classid+","+student.Studentid);
        resp.getWriter().write(objectMapper.writeValueAsString(student));
    }
}

利用ObjectMapper的实例化对象中的实例方法readValue可以将HTTP请求的body内容解析成对应的java对象(注意java对象中的属性名需要与body中的键值对键保持一致)

而writeValueAsString可以将java对象重新转成json数据.

HttpServletResponse

方法 简介
void setStatus(int sc) 为该响应设置状态码
void setHeader(String name,String value) 设置一个带有给定的名称和值的 header. 如果 name 已经存在,则覆盖旧的值
void addHeader(String name, String value) 添加一个带有给定的名称和值的 header. 如果 name 已经存在,不覆盖旧的值, 并列添加新的键值对
void setContentType(String type) 设置被发送到客户端的响应的内容类型。
void setCharacterEncoding(String charset) 设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8
void sendRedirect(String location) 使用指定的重定向位置 URL 发送临时重定向响应到客户端
PrintWriter getWriter() 用于往 body 中写入文本格式数据.
OutputStream getOutputStream() 用于往 body 中写入二进制格式数据.

代码案例:

自我刷新页面

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/example")
public class eample extends Helloservlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType("text/html; charset=utf8");
        resp.setHeader("Refresh","1");
        resp.getWriter().write("当前时间"+System.currentTimeMillis());

    }
}

设置响应报文的header内容 :

设置键值对: Refresh + 时间.

重定向

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/example")
public class eample extends Helloservlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType("text/html; charset=utf8");


        //第一种方式
        resp.setStatus(302);
        resp.setHeader("Location","http://www.sougou.com");
        //第二种方式
        resp.sendRedirect("http://www.sougou.com");
    }
}

这样在header 中设置状态码写入Location 即可完成重定向

直接使用sendRedirect也可以实现.

实现一个表白墙网页

准备工作:

  • 创建项目

  • 创建目录

  • 引入依赖

  • 将表白墙前端页面拷贝到项目中

    前端代码:

    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>
        <style>
            * {
                padding: 0;
                margin: 0;
                box-sizing: border-box;
            }
    
            .container {
                width: 800px;
                margin: 10px auto;
            }
    
            .container h2 {
                text-align: center;
                margin: 30px 0px;
            }
    
            .row {
                height: 50px;
                display: flex;
                justify-content: center;
                margin-top: 5px;
                line-height: 50px;
            }
    
            .row span {
                height: 50px;
                width: 100px;
                line-height: 50px;
            }
    
            .row input {
                height: 50px;
                width: 300px;
                line-height: 50px;
            }
    
            .row button {
                width: 400px;
                height: 50px;
                color: white;
                background-color: orange;
                border: none;
                border-radius: 10px;
            }
    
            .row button:active {
                background-color: grey;
            }
        style>
    head>
    <body>
        
        <div class="container">
            <h2>表白墙h2>
            <div class="row">
                <span>span>
                <input type="text" id="from">
            div>
    
            <div class="row">
                <span>对谁span>
                <input type="text" id="to">
            div>
    
            <div class="row">
                <span>说什么span>
                <input type="text" id="message">
            div>
    
            <div class="row">
                <button>提交button>
            div>
        div>
    
        <script src="https://code.jquery.com/jquery-3.6.1.min.js">script>
        <script>
            let container = document.querySelector('.container');
            let fromInput = document.querySelector('#from');
            let toInput = document.querySelector('#to');
            let messageInput = document.querySelector('#message');
            let button = document.querySelector('button');
            button.onclick = function() {
                // 1. 把用户输入的内容获取到. 
                let from = fromInput.value;
                let to = toInput.value;
                let message = messageInput.value;
                if (from == '' || to == '' || message == '') {
                    return;
                }
                // 2. 构造一个 div, 把这个 div 插入到 .container 的末尾
                let newDiv = document.createElement('div');
                newDiv.className = 'row';
                newDiv.innerHTML = from + " 对 " + to + " 说: " + message;
                // 3. 把 div 挂在 container 里面
                container.appendChild(newDiv);
                // 4. 把之前的输入框内容进行清空
                fromInput.value = '';
                toInput.value = '';
                messageInput.value = '';
            }
        script>
    body>
    html>
    

确定前后端交互信息:

我们在写后端代码之前,需要约定好,后端给前端的数据是什么样的,前端返回给后端的数据是什么样的.

我们的表白墙需要保证:

用户加载页面时,前端从后端拿到数据,我们可以约定

请求为: GET/message

响应我们使用json组织.

{
    {
        "from" : "狗",
        "to" : "猫",
        "sad" : "汪汪汪"
    }
    {   
        "from" : "猫",
        "to" : "狗",
        "sad" : "喵喵喵"
    }
}

用户点击提交后,后端从前端页面拿到数据:我们约定

请求为: POST/message

使用json组织

{
    {
        "from" : "狗",
        "to" : "猫",
        "sad" : "汪汪汪"
    }
    {   
        "from" : "猫",
        "to" : "狗",
        "sad" : "喵喵喵"
    }
}

响应使用标记来表示拿取成功与否:

{
    "ok": 1  //使用1表示成功,0表示失败
}

实现提交数据:

前端构造请求:

我们需要实现,点击提交按钮之后,后端为我们的前端能保存数据,下次刷新页面时,数据还存在.

        let messageexample = {
            "from" : from,
            "to" : to,
            "message" : message
        };
        $.ajax({
            type:'post',
            url:'message',
            contentType: 'application/json;charset=utf8',
            data:JSON.stringify(messageexample),
            success: function(body){
                alert("提交成功");
            },
            error : function(body){
                alert("提交失败");

            }
        })   

后端保存数据:

    ObjectMapper objectMapper = new ObjectMapper();
    List<Message> list = new ArrayList<>();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        Message message1 = objectMapper.readValue(req.getInputStream(),Message.class);
        list.add(message1);
        System.out.println("message: " + message1);
        resp.setContentType("application/json;charset:uft8");
        resp.getWriter().write("{\"ok\" : 1}");

    }

实现返回数据

我们再每一次刷新或者提交数据之后,页面都能保存下我们的数据.这个时候需要后端向前端返回我们之前保存的数据.

前端构造请求:

     function load(){
        $.ajax({
            type:'get',
            url:'message',
            success: function(body){
                let container = document.querySelector('.container');
                for(let message of body){
                    let newDiv = document.createElement('div');
                    newDiv.className = 'row';
                    newDiv.innerHTML = message.from + "对" + message.to + "说" + message.message;
                    container.appendChild(newDiv);
                }
            }
        })

    };
    load();

后端返回数据:

 @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        //拿到数据并返回给前端
        String str = objectMapper.writeValueAsString(list);
        System.out.println(str);
        resp.getWriter().write(str);

    }

实现数据库版本

我们上面这个网站,如果把我们的服务器关闭,数据也就不见了.要想永久保留数据,就要将数据保存到数据库中.

引入数据库依赖:

        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.17version>
        dependency>

在数据库中创建对应的数据库.这里自己在mysql创建即可,不多赘述了.

create database messagewall;
create table message('from' varchar(100),'to' varchar(100),message varchar(100));

实现JDBC 连接数据库,(这里使用单例模式实现)

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DButil {
    private static DataSource dataSource = null;
    public  static DataSource getDataSource(){
        if(dataSource==null){
            dataSource = new MysqlDataSource();
            ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/MessageWall?characterEncoding=utf8&useSSL=false");
            ((MysqlDataSource)dataSource).setUrl("root");
            ((MysqlDataSource)dataSource).setPassword("123456");
        }
        return dataSource;
    }
    public static Connection getConnection() throws SQLException {
        return (Connection) getDataSource().getConnection();
    }
    public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
        if(resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (preparedStatement!=null){
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

在后端实现从数据库拿到数据并且返回给前端.

    public void save(Message message){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = DButil.getConnection();
            String sql = "insert into message values(?,?,?)";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,message.form);
            preparedStatement.setString(2,message.to);
            preparedStatement.setString(3,message.message);
            int ret = preparedStatement.executeUpdate();
            if(ret == 1){
                System.out.println("执行成功");
            }else{
                System.out.println("执行失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            DButil.close(connection,preparedStatement,null);
        }

    }
    public List<Message> load(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Message> list = new ArrayList<>();
        try{
            connection = DButil.getConnection();
            String sql = "select * from Message";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){
                Message message = new Message();
                message.form = resultSet.getString("form");
                message.to = resultSet.getString("to");
                message.message = resultSet.getString("message");
                list.add(message);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DButil.close(connection,preparedStatement,resultSet);
        }
        return list;
    }
}

完整代码:

JavaEE-初阶: javaee初阶学习 - Gitee.com

cookie与session

我们在上文就已经得知,cookie是HTTP协议提供的一种维持数据持久化的机制,

cookie按照域名来分类,并且只能存储简单的键值对.

cookie的数据不是由浏览器来决定的,而是由服务器决定,当服务器返回的响应中有set-cookie时,浏览器才会给网页设置cookie.

设置玩cookie之后,浏览器每一次访问服务器,都会将cookie一并发送给服务器.

最典型的应用就是存储网页的个人用户信息.来做到避免需要多次重复输入登录.

而存储个人用户信息,我们并不好直接把用户信息存入到cookie中去,这样会导致信息泄露与不安全.

所以服务器实现了session,session也是键值对,其中sessionId为键,用户的个人信息为值.

当客户端向服务器发送登录请求(账号+密码) ,服务器会对身份进行校验,校验成功之后再进一步分配session,并且生成一个随机的sessionId作为key,将用户的信息作为value来构成键值对.完成以上工作之后,将sessionId返回给客户端作为cookie.

下一次客户端访问服务器时,会将sessionid一并发送给服务器,服务器通过sessionid即可在数据库中找到用户的个人信息.

cookie和seesion的区别:

  • cookie 是客户端的机制, session 是服务器的机制

  • cookie 和 seesion是经常搭配使用的,但也可以不搭配

    例如cookie可以只用来存储数据,不一定存储seesionid等服务器校验数据.

    seesion中的sessionid也并不一定就得通过cookie来传递.

《JavaEE初阶》Servlet_第10张图片

Servlet中相关类与方法.

HttpServletRequest

  • HttpSession getSession()

    在服务器中获取会话,如果参数为true,则不存在会话时,创建新的会话(即创建新的HttpSession作为value,生成一个随机的sessionid作为键,保存在服务器的哈希表中).如果参数为false,则不存在会话时,直接返回null.

  • Cookie[] getCookie()

    返回一个cookie数组,包含客户端发送该请求的所有cookie值,并且将cookie中的值全部解析为键值对的方式.

HttpServletResponse

  • void addCookie(Cookie cookie)

    把指定的cookie添加到响应中

HttpSession

  • Object getAttribute(String name)

    该方法返回在该 session 会话中具有指定名称的对象,如果没

    有指定名称的对象,则返回 null.

  • void setAttribute(String name, Object value)

    该方法使用指定的名称绑定一个对象到该 session 会话

  • boolean isNew()

    判定当前是否是新创建出的会话

实现一个登录页面

我们通过上述方法来做到用户信息的保存.

前端页面:

 doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>登录页title>
head>
<body>
<form action="login" method="post">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" value="提交">
form>
body>
html>

创键Index,后端显示登录成功的用户名和登录次数

package login;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession(false);
        if(session == null){
            //用户未登录
            resp.sendRedirect("login.html");
            return;
        }
        String name = (String)session.getAttribute("username");
        Integer visitcount = (Integer) session.getAttribute("visitcount");
        visitcount = visitcount+1;
        session.setAttribute("visitcount",visitcount);
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("当前用户为"+name+"访问次数"+visitcount);

    }
}

创建login,来处理前端请求,校验身份并且生成session.

package login;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        String name = req.getParameter("username");
        String password = req.getParameter("password");
        if(name==null||name.equals("")||password==null||password.equals("")){
            resp.getWriter().write("用户名登录或者密码格式错误,登录失败");
            return;
        }
        if(!password.equals("1234")&&!name.equals("libai")){
            resp.getWriter().write("用户名或者密码错误,登录失败");
            return;
        }
        HttpSession session = req.getSession(true);
        session.setAttribute("username",name);
        session.setAttribute("password",password);
        Integer visitcount = (Integer) session.getAttribute("visitcount");
        if(visitcount==null){
            session.setAttribute("visitcount",0);
        }else{

        }
        resp.sendRedirect("index");

    }
}

使用Servlet上传文件.

相关方法与类

HttpServletRequest

  • Part getPart(String name)

    获取请求中给定name的文件

  • Collection getParts()

    获取请求中的所有文件

Part类方法

  • String getSubmittedFileName()

    获取提交的文件名

  • String getContentType()

    获取提交的文件的文件类型

  • long getsize()

    获取文件的大小

  • void write(String path)

    把提交的文件写入磁盘

实现一个上传文件页面

前端页面:

doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>上传文件页title>
head>
<body>
<form action="load" method="post" enctype="multipart/form-data">
    <input type="file" name = "myfile">
    <input type="submit" value="提交">
form>
body>
html>

注意这里的enctype=“multipart/form-data”,这个属性是单独给"上传文件设置的",他会设置ContentType,并且为文件设置文件的结束标志.

后端代码:

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
@MultipartConfig
@WebServlet("/load")
public class upload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Part part = req.getPart("myfile");
        System.out.println(part.getSubmittedFileName());
        System.out.println(part.getSize());
        System.out.println(part.getContentType());
        part.write("D:/result.jpg");
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("成功");
    }
}

@MultipartCon 这个注解是上传文件的后端代码必须加的

你可能感兴趣的:(servlet,java-ee,java)