• day30_servlet


    今日内容

    零、复习昨日

    一、接收请求

    二、处理响应

    三、综合案例

    零、复习昨日

    画图, 请求处理的完整流程(javaweb开发流程)

    image-20230818094130792

    零、注解改造

    @WebServlet注解,相当于是在web.xml中配置的servlet映射

    Servlet类

    package com.qf.servlet;
    
    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;
    
    /**
     * --- 天道酬勤 ---
     *
     * @author QiuShiju
     * @desc
     * 注解@WebServlet取代web.xml中的配置
     * 服务器运行时会处理这个注解
     * 根据注解后的参数匹配请求路径
     */
    @WebServlet("/a")
    public class MyServlet1 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("接收请求" );
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    web.xml , 内容不用配置

    
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
    
    
    
    
    
    
    
    
    
    
        
    web-app>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    启动项目,访问/a路径即可

    一、接收请求

    需求: html页面中写一个表单,发送请求,后台服务器接收所有请求数据

    1.1 编写页面

    index.jsp或者index.html都行

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
    
    <%--
        input必须加name属性,因为后台服务器通过name获取输入框的值
        单选,复选框,选择框,需要设置value属性,后台服务器获得是value的值
        文件上传比较特殊,后续单独讲,暂时忽略
    --%>
    

    演示:servlet接收请求数据

    用户名
    密码
    性别
    爱好 唱歌 跳舞 rap
    生日
    学历
    提交
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    image-20230818104807614

    1.2 编写Servlet

    package com.qf.servlet;
    
    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;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * --- 天道酬勤 ---
     *
     * @author QiuShiju
     * @desc 演示接收请求数据
     */
    @WebServlet("/req")
    public class MyServlet2 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            /**
             * 请求中有请求方法,请求路径以及请求数据
             * ----------------------------------
             * 通过doGet方法参数1 HttpServletRequest req对象来获得请求数据
             * ps:当请求到达该类的这个方法时,该参数req就会被赋值,其中就有关于请求的所有东西
             */
            String method = req.getMethod( );
            String uri = req.getRequestURI( );
            StringBuffer url = req.getRequestURL( );
            System.out.println("method = " +  method);
            System.out.println("uri = " +  uri);// uri资源标识符
            System.out.println("url = " +  url);// url资源定位符
    
            // ===============获得请求数据[重点]===================
            /**
             * 获得请求参数的方法是
             * req.getParameter("key"); key就是前端标签name值
             * [重点:] 后端获得的数据全都是字符串,如果需要后续使用,
             * 还需按照性质做相应的转换
             * 比如: 字符串转数字,字符串转日期
             */
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String sex = req.getParameter("sex");
            // int i = Integer.parseInt(sex);
    
            String birthday = req.getParameter("birthday");
            // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            // try {
            //     Date parse = sdf.parse(birthday);
            // } catch (ParseException e) {
            //     e.printStackTrace( );
            // }
    
            String xl = req.getParameter("xl");
            System.out.println("username = " +  username);
            System.out.println("password = " +  password);
            System.out.println("sex = " +  sex);
            System.out.println("birthday = " +  birthday);
            System.out.println("xl = " +  xl);
    
    
            // 多选框使用getParameterValues()
            String[] hobbies = req.getParameterValues("hobby");
            for (String hobby : hobbies) {
                System.out.println("hobby = " + hobby );
            }
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    总结:

    • req.getParameter(“”) 能获得请求数据
    • req.getParameterValues(“”) 能获得请求数据

    1.3 配置web.xml

    注解开发,不需要配置
    
    • 1

    1.4 部署项目

    1.5 启动测试

    复习回顾

    前端
    html,css,js/jq

    后端服务器:

    1开发架构有哪些:

    • b/s,
    • c/s

    2服务器是干什么的?

    • 运行web项目项目容器
    • 接收请求,做出响应

    3浏览器如何发出的请求

    • 常见的如,a标签,form表单
    • js中使用ajax发请求
    • vue中使用axios发请求

    4发请求后如何与后端servlet类关联的?
    (或者说绑定的?一一映射的?)

    • 没注解时,通过web.xml文件一一映射关联
    • 有注解,通过注解@WebServlet(“/路径”)中设置路径

    5什么时候servlet类会执行doGet方法,什么时候执行doPost方法?

    • 前端发get,后端就执行doGet
    • 前端发post,后端就执行doPost

    6写出完整的项目(假设项目命名his)http请求路径,以登录(login)请求为例

    • 协议://ip:端口/资源?k=v&k=v
    • jdbc:mysql://localhost:3306/java2313?useSSL=false&serverTimeZone=utc
    • http://localhost:8080/his/login?username=admin&password=123456

    7画图, 请求处理的完整流程(javaweb开发流程)

    8具体如何接收请求中的数据?

    • 通过HttpServletRequest对象接收请求中的数据
    • 通过req对象调用getParameter(“key”)

    二、做出响应

    做出响应是通过HttpServletResponse对象

    • 响应正文
      • 向浏览器展现的内容
    package com.qf.servlet;
    
    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;
    import java.io.PrintWriter;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * --- 天道酬勤 ---
     *
     * @author QiuShiju
     * @desc 演示接收请求数据,响应内容
     */
    @WebServlet("/req")
    public class MyServlet2 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           // ....
    
            // ==================演示响应=======================
            /**
             * 响应是通过HttpServletResponse resp对象来完成
             * 响应可以设置响应内容(即展示在浏览器上的内容)
             * -----------------------------------------
             * ps: 其实响应也可以设置响应状态码,但是一般不需要,服务器会自动设置状态码
             * 但是需要知道一些常见状态码:
             * 200 成功, 404 资源未找到, 500 服务器内部错误,
             * 405 get/post请求方式不对,400 一般是数据解析出错了
             */
            // 响应乱码,在响应前设置编码格式
            resp.setContentType("text/html;charset=utf-8");
            // 响应是通过输出流的形式实现
            PrintWriter out = resp.getWriter( );
            //out.write("hello this is response - 这是响应");
            out.write("");
            out.write("响应");
            out.write("");
            out.write("

    这是响应的页面

    "
    ); out.write("
    div
    "
    ); out.write("

    "+username+"

    "
    ); out.write(""); out.write(""); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    三、乱码解决

    请求乱码

     req.setCharacterEncoding("utf-8");
    
    • 1

    响应乱码

    resp.setContentType("text/html;charset=utf-8");
    
    • 1

    四、 综合案例-登录(Servlet + JDBC)

    • 要求:实现登录功能
    第一步: 先设计数据库
    	库,表 (ORM,要根据表设置实体类)
    登录页面
    	html/jsp
    	表单发送请求,携带数据
    后台服务器代码
    	servlet,接收数据
    	jdbc+orm
    	servlet,做出响应
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4.0 项目结构[重点]

    web开发有三层架构

    • 控制层 -servlet 流程控制,是指整个请求响应的流程
    • 业务层 - service - 是指在请求接收后,对数据按照需求处理
    • 数据访问层 - DataAccessObject - DAO

    image-20230818145238992

    三层架构

    image-20230818150122062

    4.1 数据库

    CREATE TABLE `tb_user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(20) DEFAULT NULL,
      `password` varchar(20) DEFAULT NULL,
      `sex` char(1) DEFAULT NULL,
      `money` double(10,2) DEFAULT NULL,
      `createTime` date DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    实体类 - ORM

    需要创建一个包,专门存储实体类,一般命名pojo/entity/model

    public class User {
        // 列名对属性名
        private int id;
        private String username;
        private String password;
        private String sex;
        private double money;
        private Date createTime;
    
        // set get 构造 toString
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.2 pom依赖

       
        <dependency>
          <groupId>javax.servletgroupId>
          <artifactId>javax.servlet-apiartifactId>
          <version>3.1.0version>
        dependency>
        
        <dependency>
          <groupId>javax.servlet.jspgroupId>
          <artifactId>javax.servlet.jsp-apiartifactId>
          <version>2.3.1version>
        dependency> 
        
        <dependency>
          <groupId>mysqlgroupId>
          <artifactId>mysql-connector-javaartifactId>
          <version>5.1.47version>
         
        <dependency>
          <groupId>commons-dbutilsgroupId>
          <artifactId>commons-dbutilsartifactId>
          <version>1.7version>
        dependency>
        dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4.3 登录页面

    index.jsp

    <body>
    <h2>登录h2>
    <form action="/login" method="post">
        用户名<input type="text" name="username"><br>
        密码<input type="password" name="password"><br>
        <input type="submit" value="提交"><br>
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.4 控制层Servlet

    Servlet只负责接收请求数据,做出响应

    如果要处理数据,那就调用业务层

    package com.qf.servlet;
    
    import com.qf.model.Admin;
    import com.qf.service.AdminService;
    import com.qf.service.AdminServiceImpl;
    
    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;
    import java.io.PrintWriter;
    import java.util.List;
    
    /**
     * --- 天道酬勤 ---
     *
     * @author QiuShiju
     * @desc 命名
     * 功能+层
     * LoginServlet
     * LoginService
     * LoginDao
     */
    @WebServlet("/login")
    public class LoginServlet 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 接收请求数据
            String username = req.getParameter("username");
            String password = req.getParameter("password");
    
     		// servlet调用service(业务层)
            LoginService service = new LoginService( );
            User user = service.login(username, password);
    
            // 做出响应
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter writer = resp.getWriter( );
    
            if (user != null) { // 登录成功
                writer.write("登录成功!");
                writer.write(user.toString());
            } else { // 登录失败
                writer.write("登录失败!用户名或密码错误");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    4.5 业务层service

    业务层就处理项目业务逻辑的,业务逻辑包含哪些内容?

    • 除了servlet接收请求做出响应以及jdbc操作数据库的代码,其他全是业务逻辑
      • 加密解密
      • 处理上传下载excel表格
      • 处理项目中数据格式
      • 计算项目中涉及金额
      • 缓存处理
      • 购物车,订单,支付
      • 短信,验证码,定时调度,推送
      • …等等

    业务层代码编码

    • 需要创建包结构service

    LoginService

    public class LoginService {
    
        /**
         * 业务层要定义方法,能接收数据,处理后返回数据
         * -----
         * 登录一般返回的是实体类
         * - 登录成功,返回实体类对象中有数据
         * - 登录失败,返回实体类对象是null
         * ----------------------
         * 业务层需要调用数据层 操作数据库
         */
        public User login(String username, String password){
    
            // 处理业务
            // ...
            // 处理后,要将数据继续传递给dao层
            LoginDao loginDao = new LoginDao( );
            User user = loginDao.login(username, password);
    
            return user;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    4.6 数据访问层dao

    数据访问层 Data Access Object - DAO

    项目需要创建dao层代码专门操作数据库

    dao层编码

    LoginDao

    public class LoginDao {
    
        public User login(String username,String password) {
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try{
                Class.forName("com.mysql.jdbc.Driver");
                conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java23132?useSSL=false", "root", "123456");
                ps = conn.prepareStatement("select * from tb_user where username = ? and password = ?");
                ps.setString(1,username);
                ps.setString(2,password);
    
               rs = ps.executeQuery( );
                while (rs.next()) {
                    User user = new User( );
                    user.setId(rs.getInt("id"));
                    user.setUsername(rs.getString("username"));
                    user.setPassword(rs.getString("password"));
                    user.setSex(rs.getString("sex"));
                    user.setMoney(rs.getDouble("money"));
                    user.setCreateTime(rs.getDate("createTime"));
                    return user;
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                try {
                    rs.close();
                    ps.close();
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace( );
                }
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    4.7 测试

    登录页面

    image-20230523162257066

    登录成功

    image-20231120143529612

    登录失败

    image-20231120143524446

    4.8 总结

    重点

    • 熟悉开发的流程
    • 熟记开发架构 (控制层,业务层,数据访问层)
    • 响应拼接页面方式,了解即可
    • 前后端发请求,做响应

    经验总结

    1 写项目不要照抄,应该按照流程一步一步写
    (前端–>servlet–>service–>dao–>service—>servlet–>前端)

    2 学会看异常

    • 前端页面报错404,405,500
    • 后端控制台要查看异常(注意几个关键词,Exception,error,caused by ,at …)

    3 逻辑bug

    • 前端页面没有报错,后端控制台有没有报错,但是结果不对
    • 这就是bug,该怎么解决?
    • 从头(按照流程)读,检查代码,去输出,高端玩家打断点

    4 如果确定前端,后端,数据库都没问题,考虑缓存

    • idea缓存(file-invalidate cache)(删除target文件夹)
    • 浏览器缓存(清空)

    5 学会倒推

    五、注册功能

    (如何写需求?建议当做用户,见到什么写什么,需要什么写什么)

    注册 —> 向数据库插入数据

    5.1 跳转注册

    5.2 注册页面

    5.3 发请求,后端Servlet接收

    注意接收的中文防止乱码

    5.4 UserService

    注意: 将之前的LoginService重命名为UserService,因为一个类中可以定义多个方法,不需要创建很多类

    5.5 UserDao

    注意日期bug,只能是java.sql.Date类型

    5.6 UserDao返回给UserService

    5.7 UserService在返回给RegistServlet

    5.8 Servlet根据结果做响应

    六、作业-查询全部

    登录成功后查询全部,并展示全部

  • 相关阅读:
    关于C#.Net网页跳转的7种方法
    归约证明在密码学中的应用
    斯坦福NLP课程来了
    Sqoop(SQL to Hadoop)数据传输工具:用于在Hadoop和关系数据库服务器之间传输数据
    C语言银行综合业务系统
    组件分享之后端组件——开源ELT平台airbyte
    AI基础软件:如何自主构建大+小模型?
    UDP内核发包流程
    树上启发式合并 待补
    用Python字典简单实现词频统计
  • 原文地址:https://blog.csdn.net/weixin_39641494/article/details/134515276