精华内容
下载资源
问答
  • Servlet 项目tomcat的部署与测试第一个servlet登录小项目JSP作为servlet处理使用servlet处理用户交互servlet连接mysql数据库实现学生...页面次数对服务器四个内置保存对象理解tomcat与servlet的关系图JSP执行过程(面试)...

    程序架构

    • B/S架构
      在这里插入图片描述

    • URL:主机地址是当前电脑IP和服务器端口号、目标资源:访问的项目名
      在这里插入图片描述

    Web服务器

    应用服务器如何得到用户在浏览器发送的请求呢? ----Web服务器。
    Tomcat服务器的优点:Apache的开源项目,轻量级,稳定,资源占用小
    在这里插入图片描述
    修改tomcat端口号:在conf下的server.xml中,编辑
    在这里插入图片描述

    JSP / Servlet 项目

    JSP(Java Server Pages)

    • 运行在服务器端的Java页面,使用HTML嵌套Java代码实现

    Servlet(Server Applet)是JAVA Servlet 的简称,是使用java语言编写的运行在服务器端的程序,具有独立的平台和协议特性,用于处理客户端传来的HTTP请求,并返回一个响应,能处理doGet()和doPost()等。主要功能在于交互的浏览和生成数据,生成动态的web内容

    • 通常来说:servlet是指所有实现类Servlet接口的类
      Servlet由Servlet容器提供,Servlet容器是指提供了Servlet功能的服务器(如:Tomcat)
      Servelt容器会将Servlet动态的加载到服务器上,然后通过HTTO请求和HTTP应用于客户端进行交互

    Servlet的技术特点

    			1、方便				
    			​	Servelt提供了大量的实用工具,比如处理很难完成的HTML表单数据、读取、设置HTPP的头,以及处理Cookie和跟踪会话等				
    			2、跨平台
    			
    			​	Servlet实用Java类编写,可以在不同的操作系统平台和不同的应用程序服务器平台运行
    			
    			3、灵活性和可扩展性强
    			
    			​	采用Servlet开发的web应用程序,由于java类继承性以及构造函数等特点,使得应用灵活,可随意扩展
    

    servlet运行的体系结构: 浏览器发送请求给HTTP服务器,HTTP服务器发送给Servlet容器(tomcat),Servlet容器再请求到当前的Servlet对应的方法上面。
    在这里插入图片描述

    tomcat的部署与测试

    • 创建一个项目
      在这里插入图片描述

    • 将解压好的tomcat添加到项目中
      在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    • 在tomcat中创建一个userServlerlet
      在这里插入图片描述

    • 由于有接口无法识别,需要添加依赖jar包,将tomcat文件夹下的两个jar包添加到项目中就可以识别了

    • 先在web-INF创建一个lib目录,然后点击project Strcture添加tomcat文件夹下的两个jar包
      在这里插入图片描述

    在这里插入图片描述

    第一个servlet登录小项目

    JSP作为servlet处理

    <%%> 脚本片段:用于定义局部的变量、表达式、java代码
    <%!%>声明语句用于变量声明 和 方法的定义
    <%=%> 表达式 用于存放变量或者比倒是
    <%@ %>指令 通过书信定义jsp的特性,实现与jsp容器的通信
    language :用于指定jsp页面使用的脚本语言
    import: 用于引用脚本语言中使用的类文件
    contentType:用于指定页面MIME类型,以及字符编码集

    通过在JSP上写java代码,进行客户端与服务端的交互。

    • 首先在login.jsp中写一个用户输入的表单,用户输入的用户名和密码就会通过post请求提交到index.jsp的页面中,web.xml中设置默认登录页面为login.jsp,开启tomcat打开浏览器输入urlhttp://localhost:8080/javaServlet/ /javaServlet为访问的项目名 (url在edit configration中查看 ),就可以默认进去login的页面

    在这里插入图片描述

    web.xml中设置默认登录页面为login.jsp
    在这里插入图片描述

    • 在index.jsp中获取用户输入的内容 request..getParameter 并显示出来out

    • 用户输入的内容后点击提交时会包含request,通过request就可以获取用户提交的信息了, 注意此处获取用户输入的内容是通过input标签中的name属性来获取的,用户输入的信息也是通过name属性一一对应,request也是通过name属性获取用户输入对应的信息。
      在这里插入图片描述

    • 测试,当用户点击提交的时候,页面就会跳转到index.jsp中,然后显示用户名和密码

    使用servlet处理用户交互

    为了让web知道你写了servlet,需要在web.xml中设置,web.xml是核心页面,用于设置当前整个项目。
    url-pattern用于 <!--指定浏览器通过该url 找到servlet 。一定要加 " / " -->
    在这里插入图片描述

    在login.jsp页面中将用户表单提交的地址输入为 在web.xml设置我们创建的Userservlet被访问的名称地址/UserServlet,但是不能加入斜杠,login.jsp不能写action="/UserServlet",如果这样写,当用户点击提交时就会不会访问项目下的UserServlet,而直接是/UerServlet,就会找不到。

    • 我们按住ctrl点击UserServlet时,就会定位到web.xml中我们设置的servlet-mapping映射中,通过servlet-mapping找到项目中的Userservlet,按照用户提交表单时表单设置的get或者post请求来执行相对应的方法

    在这里插入图片描述

    • demo.UserServlet中的post方法写相对应要处理的逻辑:
    • 首先设置字符编码集,防止中文乱码现象
    • 获取用户在表单提交的内容, request..getParameter
      如果在Dopost方法下输入System.out.println("这是DoPost方法");,当tomcat运行时,用户输入玩信息提交后,后台就会显示这句话。
      在这里插入图片描述

    servlet连接mysql数据库实现学生登录

    三层架构:

    dao(数据访问层):与数据库交流 执行 查询 、添加、删除、修改
    service(业务层):调用dao层 处理业务或者数据
    servlet : 被请求、响应

    • 首先导入mysql jar包,放入web-INf下的lib中,并对这个jar包添加依赖
    • 创建实体层 entity :创建学生类,用于产生学生对象
    • 创建工具类utils:放入连接Mysql数据库的工具类BaseDao
    • 创建Dao层:Dao层的作用是连接mysql数据库的数据访问层。 首先创建一个学生的接口studentDao,由于要实现学生登录的功能,StudentDao这个接口是定义一个查询学生的方法,创建继承StudentDao接口的实现类StudentDaoImpl去实现如何查询学生的具体逻辑,StudentDaoImpl要继承连接Mysql的工具类BaseDao,才能根据用户输入的学生编号,查询数据库中的学生信息,如果查到的话就将数据保存到Student中,并返回给StudentDao。此处整个Dao 层的逻辑是根据用户的信息找到这个学生对象并返回给业务层,去进行登录逻辑操作。

    实现类StudentDaoImpl代码如下:

    public class StudentDaoImpl extends BaseDao implements studentDao {
        //根据用户输入的学生编号,查询数据库中的学生信息,如果查到的话就将数据保存到Student中,并返回
        @Override
        public Student queryStudent(String stuCode) {
    
            String sql = "select * from student where studentNo = ?";
            Connection connection = getConnection();
            ResultSet rs = executeQuery(connection, sql, new Object[]{stuCode});
            Student student =null;
            try {
                while (rs.next()) {
                    student = new Student(
                            rs.getInt("studentNo"),
                            rs.getString("loginPwd"),
                            rs.getString("studentName"),
                            rs.getString("sex"),
                            rs.getInt("gradeId"),
                            rs.getString("phone"),
                            rs.getString("address"),
                            rs.getString("bornDate"),
                            rs.getString("email"),
                            rs.getString("identityCard")
                    );
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                closeAll(connection,null,rs);
            }
            return student;
        }
    }
    
    • 创建业务层service:业务层用于将Dao层数据库查询的结果进行下一步逻辑操作。创建一个接口StudentService,定义方法用于查询学生登录并返回学生对象;创建业务层的实现类StudentServiceImpl,实现登录逻辑的判断。实现类StudentServiceImpl中实例化Dao层的实现类StudentDaoImpl,并用接口StudentDao来接收,StudentDao调用查询方法查询学生对象返回给业务层中的实现类StudentServiceImpl,StudentServiceImpl再判断这个学生对象是否为空,不为空就再次判断用户输入的密码和数据库查询的密码是否一致,一致的话就返回这个学生对象给servlet。

    实现类StudentServiceImpl代码如下:

        public Student studentLogin(String stuCode, String stuPwd) {
            //调用dao层的查询方法 通过账号查询到学生对象 1、null 账号错误 2、找到了学生对象
            Student student = sDao.queryStudent(stuCode);
           if (null!=student){
               if (student.getLoginPwd().equals(stuPwd)){
                   return student;
               }
           }
            return null;
        }
    
    
    • servlet中的post方法调用业务层的实现类StudentServiceImpl ,要用业务层接口来接收。StudentService studentService= new StudentServiceImpl();,来获取是否登陆成功的学生对象。

    如果学生对象不为null,说明登陆成功,那么这个用户就可以访问其他页面,因此需要将值保存在session会话当中,session是共享的,因此其他页面也可以获取session中的值,然后重定向到其他页面index.jsp即可。如果学生对象为null,说明登陆失败,需要显示登陆失败的信息,因此为带值跳转,先将登陆失败的信息放入request中,再将request对象一起跳转到登陆login页面。
    此处理解:session保存了值,不带参数的重定向为什么页面还可以获取到值呢?–因为session是由服务器创建,所以可以直接获取到session保存的值。 而请求转发页面中是request带着值跳转到其他页面,因此在一次的请求转发中页面是可以获取到request保存的值。

    servlet中doPost代码如下:

        protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            System.out.println("这是DoPost方法");//后台输出
            /*1、在http协议传输中只能用ISO-8859-1  会产生中文乱码*/
            /*设置request字符编码集合*/
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            //设置传过来的内容可能是文本text或者html
            response.setContentType("text/html;charset=utf-8");
    
            //获取用户输入的内容
            String userCode = request.getParameter("userCode");
            String userPwd = request.getParameter("userPwd");
    
    //通过业务层调用方法 查询学生(账号 密码)信息 返回一个学生对象
            Student student = studentService.studentLogin(userCode, userPwd);
    if (null!=student){
        // 登陆成功
        //跳转到index.jsp中
        //两种方式 跳转页面 1、请求转发  2、重定向
        //如果需要带有值 跳转到页面 请求转发
        //如果不需要带有值 跳转页面 重定向
    
        //将用户信息存入session 内置对象之一  服务器可以为每个用户创建一个会话对象(session)
        //1、session是内置对象不需要你创建  2、由服务器创建
        //获取session
        HttpSession session = request.getSession();
        // 获取session ID
        String sessionId = session.getId();
        //设置session 生命周期 单位秒
        session.setMaxInactiveInterval(30*60);
        //将学生对象保存在session中
        session.setAttribute("USER",student);
        response.sendRedirect("index.jsp");
    
    
    }else {
       //登陆失败
        //重定向到登陆页面
        request.setAttribute("mag","登录失败,账号或者密码错误");
        request.getRequestDispatcher("login.jsp").forward(request,response);
    }
    
        }
    
    
    • index.jsp页面中登录失败需要获取servlet里面request带值转发到此页面中的参数来显示登录失败,而request中获取参数返回的是一个Object类型,我们在servlet中给request添加的参数是String类型,因此需要拆箱操作。

    index.jsp

      <%
          //获取servlet传递过来的值
          Student student = (Student) session.getAttribute("USER");
          out.print(student);
      %>
    
    • login.jsp 中首先接收servlet返回的登录失败的信息,此处需要做判断,如果用户登录成功或者第一次登录那么servlet中request通过键msg获取的值就为null,因此不需要显示登陆失败的信息,之后再显示输入用户名和密码,提交按钮。
     <%
          <%--写一个form表单,用户在浏览器提交post提交表单时会定位到UserServlet处--%>
    <%--此处不能写action="/UserServlet",如果这样写,当用户点击提交时就会不会访问项目下的UserServlet,而直接是/UerServlet,就会找不到--%>
    <form method="post" action="UserServlet"></form>
    <%= request.getAttribute("msg")==null?"":request.getAttribute("msg")%>
    账号:<input type="text" name="userCode" />
    密码:<input type="password" name="userPwd" />
    <input type="submit"/> <input type="reset"/>
      %>
    

    同一个servlet下增加注销功能

    为了让servlet可以处理多个请求,所以在Dopost方法中调用不同的子方法,每一个方法处理一个请求,比如学生登陆、注销、查找学生信息…,为了区分用户提交的请求,前端页面在获取用户请求时给servlet传入相应的参数,每一个参数对应一个处理用户不同请求的方法即可。

    用于注销的解决方式就是让session失效。注销后就跳转到登陆页面

    UserServlet:

    package servlet;
    
    import entity.Student;
    import org.apache.catalina.Session;
    import service.StudentService;
    import service.impl.StudentServiceImpl;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    public class UserServlet extends javax.servlet.http.HttpServlet {
        @Override
        public void init() throws ServletException {
            //初始化会先执行,再执行doPost或者Doget方法
            super.init();
        }
        private  StudentService studentService= new StudentServiceImpl();
    
        protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            System.out.println("这是DoPost方法");//后台输出
            /*1、在http协议传输中只能用ISO-8859-1  会产生中文乱码*/
            /*设置request字符编码集合*/
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            //设置传过来的内容可能是文本text或者html
            response.setContentType("text/html;charset=utf-8");
    
            switch (request.getParameter("index")){
                case "1":
                    login(request,response);
                    break;
                case "2":
                    logout(request,response);
                    break;
                case "3":
                    login(request,response);
                    break;
    
                default:
                    break;
            }
    
    
    
    
        }
    
        protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
    doPost(request,response);
        }
    
        @Override
        public void destroy() {
            //销毁方法必须手动调用,用于资源释放,例如数据库的关闭
            super.destroy();
        }
    
        /**
         * 为了让servlet处理多个请求 所以创建不同的方法
         * @param request
         * @param response
         */
    
        private void  login(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws ServletException, IOException {
            //获取用户输入的内容
            String userCode = request.getParameter("userCode");
            String userPwd = request.getParameter("userPwd");
    
    //通过业务层调用方法 查询学生(账号 密码)信息 返回一个学生对象
            Student student = studentService.studentLogin(userCode, userPwd);
            if (null!=student){
                // 登陆成功
                //跳转到index.jsp中
                //两种方式 跳转页面 1、请求转发  2、重定向
                //如果需要带有值 跳转到页面 请求转发
                //如果不需要带有值 跳转页面 重定向
    
                //将用户信息存入session 内置对象之一  服务器可以为每个用户创建一个会话对象(session)
                //1、session是内置对象不需要你创建  2、由服务器创建
                //获取session
                HttpSession session = request.getSession();
                // 获取session ID
                String sessionId = session.getId();
                //设置session 生命周期 单位秒
                session.setMaxInactiveInterval(30*60);
                //将学生对象保存在session中
                session.setAttribute("USER",student);
                response.sendRedirect("index.jsp");
    
    
            }else {
                //登陆失败
                //重定向到登陆页面
                request.setAttribute("mag","登录失败,账号或者密码错误");
                request.getRequestDispatcher("login.jsp").forward(request,response);
            }
    
        }
        /**
         * 用于注销  让session失效
         * @param request
         * @param response
         * @throws IOException
         * @throws ServletException
         */
        private void logout(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws IOException {
            HttpSession session = request.getSession();
          Student student=(Student)  session.getAttribute("USER");
          session.invalidate();//设置session失效
            response.sendRedirect("login.jsp");
    
        }
    }
    
    

    login页面:

    <form method="post" action="UserServlet?index=1"></form>
    <%= request.getAttribute("msg")==null?"":request.getAttribute("msg")%>
    账号:<input type="text" name="userCode" />
    密码:<input type="password" name="userPwd" />
    <input type="submit"/> <input type="reset"/>
    </body>
    </html>
    

    index页面:

     <%
          //获取servlet传递过来的值
          Student student = (Student) session.getAttribute("USER");
          if (null==student){response.sendRedirect("login.jsp");}//如果学生对象为空就跳转到登录页面
          else ;
      %>
    <%--  通过表达式显示内容,UserServlet?index=2表示向UserServlet传入参数index为2,UserServlet通过request获取页面传来的参数index--%>
      <%= student.getStudentName()%> <a href="UserServlet?index=2" >注销</a>
    

    理解: 数据访问层Dao层只用于去数据库查询信息获取值,业务层来控制具体的业务层

    同一个servlet下增加学生信息查询功能

    大体思路:

    按照学生编号或者年级或者姓名查询到学生并展示到index.jsp中:请求servlet返回request,request保存一个学生集合,通过脚本jsp和java代码块来展示

    小技巧:

    1. 如果需要循环遍历值并显示到页面上,把一段for循环的java块拆分开,包裹html代码
    2. 按照学生编号或者年级或者姓名查询到学生的sql语句的书写问题:此条件表示任意去除一个条件,都可以查询到相关结果,而sql语句需要用AND拼接条件,去掉任意一个条件,都会多出一个AND,因此多加一个等值条件,这样去掉任意一个条件都不会出错。
    3. sql代码如下:
    SELECT *
    FROM student
    JOIN grade
    on grade.gradeID= student.gradeId
    WHERE 1=1
    AND studentNo=? 
    AND studentName like ?
    AND grade.gradeID=?
    
    • Dao层:StudentDao中编写查询学生信息的方法,返回一个集合list, StudentDaoImpl类中实现这个方法,由于BaseDao中的查询语句必须要传入参数,但是按照目前问题的要求,参数值的大小和个数都是不一定的,因此,我们重写BaseDao的executeQuery方法,并设置不传入需要给sql语句遍历的参数,直接执行传进来的sql语句

    重写的BaseDao的executeQuery方法如下:

    
        public ResultSet executeQuery(Connection connection,String sql) {
            try {
                prepareStatement = connection.prepareStatement(sql);
                System.out.println(prepareStatement);
                resultSet = prepareStatement.executeQuery();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return resultSet;
        }
    

    StudentDao文件中

        List<Student> queryAll(String stuNo,String stuName,String gradeId);
    
    

    StudentDaoImpl类中实现这个方法:

         public List<Student> queryAll(String stuNo, String stuName, String gradeId) {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("SELECT * ");
            stringBuffer.append("        FROM student ");
            stringBuffer.append("JOIN grade ");
            stringBuffer.append("on grade.gradeID= student.gradeId ");
            stringBuffer.append("WHERE 1=1 ");
            if (stuNo!=null&&!stuNo.equals(""))
            stringBuffer.append("AND studentNo= "+stuNo );
            if (stuName!=null&&!stuName.equals(""))
            stringBuffer.append("AND studentName like  '%"+stuName+"%'  " );
            if (gradeId!=null&&!gradeId.equals(""))
            stringBuffer.append("        AND grade.gradeID= "+gradeId );
    
            Connection connection = getConnection();
    
            ResultSet rs = executeQuery(connection, stringBuffer.toString());
            ArrayList<Student> studentList = new ArrayList<>();
            try {
                while (rs.next()){
                    studentList.add( new Student(
     //学生对象属性根据数据库中student表中的设计表属性顺序添加,因此通过数据库获取的学生信息也跟Student类的属性顺序一致,
                                    rs.getInt("studentNo"),
                                    rs.getString("loginPwd"),
                                    rs.getString("studentName"),
                                    rs.getString("sex"),
                                    rs.getInt("gradeId"),
                                    rs.getString("phone"),
                                    rs.getString("address"),
                                    rs.getString("bornDate"),
                                    rs.getString("email"),
                                    rs.getString("identityCard"),
                                    rs.getString("gradeName")
                            )
    
                    );
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeAll(connection,null,rs);
            }
    
    
            return studentList;
        }
    
    • 业务层 接口定义方法名,实现类用于实现
      studentservice文件:
    List<Student> queryStudent(String stuNo,String stuName,String gradeId);
    

    studentserviceImpl文件:

      public List<Student> queryStudent(String stuNo, String stuName, String gradeId) {
            List<Student> students = sDao.queryAll(stuNo, stuName, gradeId);
            return students;
        }
    
    • UserServlet层:写一个查询到学生信息的方法,并将信息保存到request中,请求转发到index.jsp中。此方法用在用户输入完登录信息后也就是登录方法后,就会显示查询到用户的相关信息。而无需再用户登录后就跳转页面。
    
        private void login(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws ServletException, IOException {
            //获取用户输入的内容
            String userCode = request.getParameter("userCode");
            String userPwd = request.getParameter("userPwd");
    
    //通过业务层调用方法 查询学生(账号 密码)信息 返回一个学生对象
            Student student = studentService.studentLogin(userCode, userPwd);
            if (null != student) {
                // 登陆成功
                //跳转到index.jsp中
                //两种方式 跳转页面 1、请求转发  2、重定向
                //如果需要带有值 跳转到页面 请求转发
                //如果不需要带有值 跳转页面 重定向
    
                //将用户信息存入session 内置对象之一  服务器可以为每个用户创建一个会话对象(session)
                //1、session是内置对象不需要你创建  2、由服务器创建
                //获取session
                HttpSession session = request.getSession();
                // 获取session ID
                String sessionId = session.getId();
                //设置session 生命周期 单位秒
                session.setMaxInactiveInterval(30 * 60);
                //将学生对象保存在session中
                session.setAttribute("USER", student);
                //学生登录成功就去查询此学生并将展示结果到index.jsp页面上,跳转到此页面
                queryAllStudent(request,response);
    
    
            } else {
                //登陆失败
                //重定向到登陆页面
                request.setAttribute("mag", "登录失败,账号或者密码错误");
                request.getRequestDispatcher("login.jsp").forward(request, response);
            }
    
        }
    
        private void queryAllStudent(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws ServletException, IOException {
            //获取用户在页面输入的内容
            String stuNo = request.getAttribute("StuNo").toString();
            String stuName = request.getAttribute("StuName").toString();
            String gradeId = request.getAttribute("gradeId").toString();
            List<Student> students = studentService.queryStudent(stuNo, stuName, gradeId);
            request.setAttribute("Students",students);
            request.getRequestDispatcher("index.jsp").forward(request,response);
    
        }
    
    
    • index.jsp页面:使用form表单提交用户输入的信息到userservlet中对应index=3所要执行的查询学生信息方法,循环遍历查找的学生结果并展示
    • 会遇到的问题:用户在查询学生完成之后,用户在网页的查询信息不能滞留,因此需要在UserServlet中将获取到的用户查询时输入的信息再次存储到request中并请求转发展示到页面上。
      用户请求servlet,sertlet请求数据问业务层要,业务层问数据访问层要
    <%@ page import="entity.Student" %>
    <%@ page import="java.util.List" %>
    <%@ page import="java.text.SimpleDateFormat" %>
    <%@ page import="java.text.ParseException" %><%--
      Created by IntelliJ IDEA.
      User: scq
      Date: 2020/11/19
      Time: 22:17
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
      <%
          //用户登录:获取servlet传递过来的值
          Student student = (Student) session.getAttribute("USER");
          if (null==student){response.sendRedirect("login.jsp");}//如果学生对象为空就跳转到登录页面
          else ;
      %>
    <%--  通过表达式显示内容,UserServlet?index=2表示向UserServlet传入参数index为2,UserServlet通过request获取页面传来的参数index--%>
      <%= student.getStudentName()%> <a href="UserServlet?index=2" >注销</a>
      </body>
    <form method="post" action="UserServlet?index=3">
        <tr>
            <td>
                <%--  此处name属性为值为request的键,request通过此键就可以获取用户输入的内容--%>
    <%-- 将用户输入的数据再通过servlet保存之后带回到页面上 --%>
                <input type="text" name="StuNo" value="<%= request.getAttribute("StuNo")!=null?request.getAttribute("StuNo"):""%>">
                <input type="text" name="StuName" value="<%= request.getAttribute("StuName")!=null?request.getAttribute("StuName"):""%>">
                <select name="gradeId">
    <%--                先做非空处理,否则显示null --%>
                    <%if (null!=request.getAttribute("gradeId")&& request.getAttribute("gradeId").toString().equals("1")){%>
                    <option selected value="1">一年级</option>
                    <%} else {%>
                    <option value="1">1年级</option>
                    <%}%>
    
                    <% if (null != request.getAttribute("gradeId") && request.getAttribute("gradeId").toString().equals("2")) { %>
                    <option selected value="2">二年级</option>
                    <% } else {%>
                    <option value="2">二年级</option>
                    <%} %>
    
                    <%if (null != request.getAttribute("gradeId") && request.getAttribute("gradeId").toString().equals("3")){%>
                    <option selected value="3">3年级</option>
                    <%}else{%>
                    <option value="3">3年级</option>
                    <%}%>
                </select>
                <input type="submit">
            </td>
        </tr>
    
    
    
    </form>
      <tr>
          <th>学生编号</th>
          <th>学生姓名</th>
          <th>学生性别</th>
          <th>年级名称</th>
          <th>学生生日</th>
          <th>学生电话</th>
          <th>学生地址</th>
          <th>学生邮箱</th>
          <th>学生身份证号码</th>
      </tr>
    <%
        //获取查询到的学生集合
        if (null!= request.getAttribute("Students")){
       List<Student> students = (List<Student>) request.getAttribute("Students");
        for (Student stu:students){
    %>
      <tr>
          <td><%=stu.getStudentNo() %>
          </td>
          <td><%=stu.getStudentName() %>
          </td>
          <td><%=stu.getSex() %>
          </td>
          <td><%=stu.getGradeName() %>
          </td>
          <td><%= dateFormat(stu.getBornDate()) %>
          </td>
          <td><%=stu.getPhone() %>
          </td>
          <td><%=stu.getAddress() %>
          </td>
          <td><%=stu.getEmail() == null ? "暂无数据" : stu.getEmail() %>
          </td>
          <td><%=stu.getIdentityCard() == null ? "暂无数据" : stu.getIdentityCard() %>
          </td>
      </tr>
    
      <%
        }
        }
    
    %>
    <%--声明使用: 用于声明变量或者定义方法:此处定义一个转化时间格式的方法--%>
    <%!
      String dateFormat(String date) throws ParseException {
          SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
          return simpleDateFormat.format(simpleDateFormat.parse(date));//此处把字符串date转换为时间类型再转换为自定义时间格式
      }
    %>
    </html>
    
    

    同一个servlet下增加分页的功能

    第一次进入login.jsp页面,登陆成功后跳转index.jsp页面,此时当前页pageNum为null,因此设置为第一页,然后servlet查询学生信息,返回给前台,前台展示;当点击上一页或者下一页时,同时访问servlet,并传入当前页参数与用户查询条件,servlet返回查询结果给前台,前台展示。

    • 写一个分页工具类
    package utils;
    
    import java.util.List;
    
    public class PageUtil<T> {
        private int pageNum; //当前页
        private  int pageSize;//每页显示条数
        private  int pageCount;//总页数
        private int  sumCount;//总条数
        private List<T> list; //每页显示的数据
    
        public int getPageNum() {
            return pageNum;
        }
    
        public void setPageNum(int pageNum) {
            this.pageNum = pageNum;
        }
    
        public int getPageSize() {
            return pageSize;
        }
    
        public void setPageSize(int pageSize) {
            this.pageSize = pageSize;
        }
    
        public int getPageCount() {
            return pageCount;
        }
    
        public void setPageCount(int pageCount) {
            this.pageCount = pageCount;
        }
    
        public int getSumCount() {
            return sumCount;
        }
    
        public void setSumCount(int sumCount) {
            this.sumCount = sumCount;
            if (sumCount%pageSize==0){
                pageCount=sumCount/pageSize; //总页数=总条数/每页显示条数
            }else{pageCount=sumCount/pageSize+1; }
        }
    
        public List<T> getList() {
            return list;
        }
    
        public void setList(List<T> list) {
            this.list = list;
        }
    }
    
    
    • Dao层接口创建计算总条数的方法,实现类实现该方法,此处需要注意的是分页查询需要携带条件,因此sql语句的编写需要加入条件
    • Dao层查询学生信息的方法中需要加入当前页数pageNum,和每页显示条数PageSize这两个参数用于分页,因此接口加入2个参数,实现类需要修改sql语句显示分页。

    接口:

    /**
         * 查询学生信息
         * @param stuNo 学生编号
         * @param stuName 学生姓名
         * @param gradeId 年级
         * @return 学生集合
         */
        List<Student> queryAllStudent(String stuNo,String stuName,String gradeId,int pageNum,int pageSize);
    
    //计算总条数
        int queryCountStudent(String stuNo,String stuName,String gradeId);
    

    实现类:

        public List<Student> queryAll(String stuNo, String stuName, String gradeId,int pageNum,int pageSize) {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("SELECT * ");
            stringBuffer.append("        FROM student ");
            stringBuffer.append("JOIN grade ");
            stringBuffer.append("on grade.gradeID= student.gradeId ");
            stringBuffer.append("WHERE 1=1 ");
            if (stuNo!=null&&!stuNo.equals(""))
            stringBuffer.append("AND studentNo= "+stuNo );
            if (stuName!=null&&!stuName.equals(""))
            stringBuffer.append("AND studentName like  '%"+stuName+"%'  " );
            if (gradeId!=null&&!gradeId.equals(""))
            stringBuffer.append("        AND grade.gradeID= "+gradeId );
    
    
            // 计算分页参数 (当前页-1)*每页显示条数就是每一页第一个数据下标
            stringBuffer.append(" LIMIT "+(pageNum-1)*pageSize+", "+pageSize+"");
            Connection connection = getConnection();
    
            ResultSet rs = executeQuery(connection, stringBuffer.toString());
            ArrayList<Student> studentList = new ArrayList<>();
            try {
                while (rs.next()){
                    studentList.add( new Student(
     //学生对象属性根据数据库中student表中的设计表属性顺序添加,因此通过数据库获取的学生信息也跟Student类的属性顺序一致,
                                    rs.getInt("studentNo"),
                                    rs.getString("loginPwd"),
                                    rs.getString("studentName"),
                                    rs.getString("sex"),
                                    rs.getInt("gradeId"),
                                    rs.getString("phone"),
                                    rs.getString("address"),
                                    rs.getString("bornDate"),
                                    rs.getString("email"),
                                    rs.getString("identityCard"),
                                    rs.getString("gradeName")
                            )
    
                    );
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeAll(connection,null,rs);
            }
    
    
            return studentList;
        }
    
        public int queryCountStudent(String stuNo, S
        tring stuName, String gradeId) {
            //分页也需要携带条件
            StringBuffer sql = new StringBuffer();
            sql.append("select count(1) from student ");
            sql.append("where 1=1 ");
            if(stuNo!=null && !stuNo.equals("")){
                sql.append("AND  studentNo = "+ stuNo );
            }
            if(stuName!=null && !stuName.equals("")){
                sql.append("AND studentName like '%"+stuName+"%' ");
            }
            if(gradeId!=null && !gradeId.equals("")){
                sql.append("AND grade.gradeID=  "+gradeId);
            }
            Connection connection = getConnection();
            ResultSet rs = executeQuery(connection, sql.toString());
    
            int count = 0;
            try {
                while (rs.next()) {
                    count = rs.getInt(1);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                closeAll(connection,null,rs);
            }
            return count;
            
            
        }
    
    
    • 业务层,接口定义配合查询显示分页获取符合条件的总学生人数的方法,实现类实现具体方法
    • 由于Dao层加入分页功能,因此业务层接口需要查询学生信息的方法需要加入当前页和每页显示条数,实现类去调用Dao层的方法即可。

    接口:

    
     /**
         * 通过 学生编号  姓名  年级  多条件查询学生信息
         * @param stuNo
         * @param stuName
         * @param gradeId
         * @return 学生集合
         */
        List<Student> queryStudent(String stuNo, String stuName, String gradeId,int pageNum,int pageSize);
    
     /**
      
         * 用于配合查询方法 进行分页处理  获取符合条件的学生总数
         * @param stuNo
         * @param stuName
         * @param gradeId
         * @return
         */
        int queryCountStudent(String stuNo,String stuName,String gradeId);
    

    实现类:

     public List<Student> queryStudent(String stuNo, String stuName, String gradeId,int pageNum,int pageSize) {
            List<Student> students = sDao.queryAll(stuNo,stuName,gradeId,pageNum,pageSize);
            return students;
        }
        
    public int queryCountStudent(String stuNo, String stuName, String gradeId) {
            int count = sDao.queryCountStudent(stuNo, stuName, gradeId);
            return count;
        }
    
    • servlet:
      整体逻辑如下: 获取用户在页面输入的内容,将获取到的用户查询时输入的信息再次存储到request中;获取分页工具类,通过工具类的各种页面参数查询学生,将查询结果放入分页工具类的List中,一次性传入页面。之后页面去遍历工具类来分页展示结果。
      要注意的问题如下: 从页面获取当前页,如果第一次进入login.jsp,执行此函数要获取PageNum是没有的,因此需要判断,如果为null就赋值为1,表示进入首页;
      当总页数计算出后才能判断从前台传来的当前页的页数范围是否在1–总页数之间;
    package servlet;
    
    import entity.Student;
    import org.apache.catalina.Session;
    import service.StudentService;
    import service.impl.StudentServiceImpl;
    import utils.PageUtil;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.util.List;
    
    public class UserServlet extends javax.servlet.http.HttpServlet {
        @Override
        public void init() throws ServletException {
            //初始化会先执行,再执行doPost或者Doget方法
            super.init();
        }
    
        private StudentService studentService = new StudentServiceImpl();
    
        protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            System.out.println("这是DoPost方法");//后台输出
            /*1、在http协议传输中只能用ISO-8859-1  会产生中文乱码*/
            /*设置request字符编码集合*/
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            //设置传过来的内容可能是文本text或者html
            response.setContentType("text/html;charset=utf-8");
    
            switch (request.getParameter("index")) {
                case "1":
                    login(request, response);
                    break;
                case "2":
                    logout(request, response);
                    break;
                case "3":
                    queryAllStudent(request, response);
                    break;
    
                default:
                    break;
            }
    
    
        }
    
    
    
        protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            doPost(request, response);
        }
    
        @Override
        public void destroy() {
            //销毁方法必须手动调用,用于资源释放,例如数据库的关闭
            super.destroy();
        }
    
        /**
         * 为了让servlet处理多个请求 所以创建不同的方法
         *
         * @param request
         * @param response
         */
    
        private void login(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws ServletException, IOException {
            //获取用户输入的内容
            String userCode = request.getParameter("userCode");
            String userPwd = request.getParameter("userPwd");
    
    //通过业务层调用方法 查询学生(账号 密码)信息 返回一个学生对象
            Student student = studentService.studentLogin(userCode, userPwd);
            if (null != student) {
                // 登陆成功
                //跳转到index.jsp中
                //两种方式 跳转页面 1、请求转发  2、重定向
                //如果需要带有值 跳转到页面 请求转发
                //如果不需要带有值 跳转页面 重定向
    
                //将用户信息存入session 内置对象之一  服务器可以为每个用户创建一个会话对象(session)
                //1、session是内置对象不需要你创建  2、由服务器创建
                //获取session
                HttpSession session = request.getSession();
                // 获取session ID
                String sessionId = session.getId();
                //设置session 生命周期 单位秒
                session.setMaxInactiveInterval(30 * 60);
                //将学生对象保存在session中
                session.setAttribute("USER", student);
                //学生登录成功就去查询此学生并将展示结果到index.jsp页面上,跳转到此页面
                queryAllStudent(request,response);
    
    
            } else {
                //登陆失败
                //重定向到登陆页面
                request.setAttribute("mag", "登录失败,账号或者密码错误");
                request.getRequestDispatcher("login.jsp").forward(request, response);
            }
    
        }
    
        /**
         * 用于注销  让session失效
         *
         * @param request
         * @param response
         * @throws IOException
         * @throws ServletException
         */
        private void logout(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws IOException {
            HttpSession session = request.getSession();
            Student student = (Student) session.getAttribute("USER");
            session.invalidate();//设置session失效
            response.sendRedirect("login.jsp");
    
        }
    
        private void queryAllStudent(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws ServletException, IOException {
            //获取用户在页面输入的内容 后台获取前台的参数通过getParameter与前台设置的参数名来获取参数值,前台获取后台的参数通过request.getAttribute来获取
            String stuNo = request.getParameter("StuNo").toString();
            String stuName = request.getParameter("StuName").toString();
            String gradeId = request.getParameter("gradeId").toString();
    
            //将获取到的用户查询时输入的信息再次存储到request中并请求转发展示到页面上。
            request.setAttribute("StuNo",stuNo);
            request.setAttribute("StuName",stuName);
            request.setAttribute("gradeId",gradeId);
    
            //获取分页工具类,指定泛型为Student类型
            PageUtil<Student> pageUtil = new PageUtil();
    
            Integer pageNum=null;
            // 从页面获取当前页,如果第一次进入login.jsp,执行此函数要获取PageNum是没有的,因此需要判断,如果为null就赋值为1,表示进入首页
            if (null==request.getParameter("PageNum")){pageNum=1;}else
            { pageNum = Integer.parseInt(request.getParameter("PageNum").toString());}
    
            pageUtil.setPageSize(5);//设置每页显示条数为5条
            //通过数据库查询获取总条数,同时也计算出了总页数pageUtil.getPageCount();
            pageUtil.setSumCount(studentService.queryCountStudent(stuNo,stuName,gradeId));
    
            // 当总页数计算出后才能判断从前台传来的当前页的页数范围是否在1--总页数之间
            if (pageNum<1)pageNum=1;
            else if (pageNum>pageUtil.getPageCount())pageNum=pageUtil.getPageCount();
    
            //设置当前页
             pageUtil.setPageNum(pageNum);
    
            //通过工具类分页查询学生
            List<Student> students = studentService.queryStudent(stuNo, stuName, gradeId,pageUtil.getPageNum(),pageUtil.getPageSize());
            //将查询结果放入分页工具类的List中,一次性传入页面,因为页面需要知道当前页数总页数
            pageUtil.setList(students);
            //由于
            request.setAttribute("pageUtil",pageUtil);
            request.getRequestDispatcher("index.jsp").forward(request,response);
    
        }
    
    }
    
    
    • jsp:
      上一页下一页进行查看信息时也在访问servlet,但是没有加入查询条件的话,不断点击上一页或者下一页就会出现所有学生的信息,这是因为前台没有将查询条件在点击上一页或者下一页传入后台(request保存的值指在一次请求转发中有效,第二次请求转发保存的值为空),后台获取的参数为空,就会显示所有的信息。
      用户在前台输入查询学生信息,后台获取用户输入的内容,并保存下来,前台再次获取用户输入的内容并在点击上一页或者下一页的时候传入用户查询的信息(再次通过request传值),servlet接收到用户查询的信息就会显示相应的内容,而不是因为null来展示查询所有的内容。
    <%@ page import="entity.Student" %>
    <%@ page import="java.util.List" %>
    <%@ page import="java.text.SimpleDateFormat" %>
    <%@ page import="java.text.ParseException" %>
    <%@ page import="utils.PageUtil" %><%--
      Created by IntelliJ IDEA.
      User: scq
      Date: 2020/11/19
      Time: 22:17
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
      <%
          //用户登录:获取servlet传递过来的值
          Student student = (Student) session.getAttribute("USER");
          if (null==student){response.sendRedirect("login.jsp");}//如果学生对象为空就跳转到登录页面
          else ;
      %>
    <%--  通过表达式显示内容,UserServlet?index=2表示向UserServlet传入参数index为2,UserServlet通过request获取页面传来的参数index--%>
      <%= student.getStudentName()%> <a href="UserServlet?index=2" >注销</a>
    
    <form method="post" action="UserServlet?index=3">
        <tr>
            <td>
                <%--  此处name属性为值为request的键,request通过此键就可以获取用户输入的内容--%>
    <%-- 将用户输入的数据再通过servlet保存之后带回到页面上 --%>
                <input type="text" name="StuNo" value="<%= request.getAttribute("StuNo")!=null?request.getAttribute("StuNo"):""%>">
                <input type="text" name="StuName" value="<%= request.getAttribute("StuName")!=null?request.getAttribute("StuName"):""%>">
                <select name="gradeId">
    <%--                先做非空处理,否则显示null --%>
                    <%if (null!=request.getAttribute("gradeId")&& request.getAttribute("gradeId").toString().equals("1")){%>
                    <option selected value="1">一年级</option>
                    <%} else {%>
                    <option value="1">1年级</option>
                    <%}%>
    
                    <% if (null != request.getAttribute("gradeId") && request.getAttribute("gradeId").toString().equals("2")) { %>
                    <option selected value="2">二年级</option>
                    <% } else {%>
                    <option value="2">二年级</option>
                    <%} %>
    
                    <%if (null != request.getAttribute("gradeId") && request.getAttribute("gradeId").toString().equals("3")){%>
                    <option selected value="3">3年级</option>
                    <%}else{%>
                    <option value="3">3年级</option>
                    <%}%>
                </select>
                <input type="submit">
            </td>
        </tr>
    
    
    
    </form>
      <tr>
          <th>学生编号</th>
          <th>学生姓名</th>
          <th>学生性别</th>
          <th>年级名称</th>
          <th>学生生日</th>
          <th>学生电话</th>
          <th>学生地址</th>
          <th>学生邮箱</th>
          <th>学生身份证号码</th>
      </tr>
    <%
        //声明分页工具类对象
        PageUtil<Student> pageUtil=null;
        //通过分页工具类获取查询到的学生集合
        if (null!= request.getAttribute("pageUtil")){
       pageUtil =((PageUtil) request.getAttribute("pageUtil"));
            List<Student> studentList = pageUtil.getList();
            for (Student stu:studentList){
    %>
      <tr>
          <td><%=stu.getStudentNo() %>
          </td>
          <td><%=stu.getStudentName() %>
          </td>
          <td><%=stu.getSex() %>
          </td>
          <td><%=stu.getGradeName() %>
          </td>
          <td><%= dateFormat(stu.getBornDate()) %>
          </td>
          <td><%=stu.getPhone() %>
          </td>
          <td><%=stu.getAddress() %>
          </td>
          <td><%=stu.getEmail() == null ? "暂无数据" : stu.getEmail() %>
          </td>
          <td><%=stu.getIdentityCard() == null ? "暂无数据" : stu.getIdentityCard() %>
          </td>
      </tr>
    
      <%
        }
        }
    
    %>
    <%--声明使用: 用于声明变量或者定义方法:此处定义一个转化时间格式的方法--%>
    <%!
      String dateFormat(String date) throws ParseException {
          SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
          return simpleDateFormat.format(simpleDateFormat.parse(date));//此处把字符串date转换为时间类型再转换为自定义时间格式
      }
    %>
    
    <%--  如果查询结果只有一页就不需要显示上一页下一页,只显示内容即可--%>
    <%if (pageUtil.getPageCount()>1){%>
    
         <tr>
        <td colspan="9">
      <%-- 当前页/总页数--%>
      <%=pageUtil.getPageNum()%>  / <%=pageUtil.getPageCount()%>
      <%-- index=3&PageNum=1 &表示拼接,向后台传多个参数时使用,将当前页等于1传给后台 后台获取参数查找内容再返回给前台--%>
      <a href="UserServlet?index=3&PageNum=1">首页</a>
      <a href="UserServlet?index=3&PageNum=<%=pageUtil.getPageNum()-1%>&StuNo=<%=request.getAttribute("StuNo")%>&StuName=<%=request.getAttribute("StuName")%>&gradeId=<%=request.getAttribute("gradeId")%>">上一页</a>
      <a href="UserServlet?index=3&PageNum=<%=pageUtil.getPageNum()+1%>&StuNo=<%=request.getAttribute("StuNo")%>&StuName=<%=request.getAttribute("StuName")%>&gradeId=<%=request.getAttribute("gradeId")%>">下一页</a>
      <a href="UserServlet?index=3&PageNum=<%=pageUtil.getPageCount()%>&StuNo=<%=request.getAttribute("StuNo")%>&StuName=<%=request.getAttribute("StuName")%>&gradeId=<%=request.getAttribute("gradeId")%>">尾页</a>
      </td>
    
      </tr>
    
      <%} %>
    
    
    </body>
    </html>
    
    

    通过计算访问页面次数对服务器四个内置保存对象理解

          pageContext.setAttribute(); 保存的值 只在当前页面有效
          request.setAttribute();     保存的值 在请求转发中有效 (这一次请求中有效)(注意:request会拼接)
          session.setAttribute();     会话级别,在这次会话访问中有效
          application.setAttribute(); 整个tomcat中有效
    

    test.jsp中:理解session保存的值的有效性,不断刷新页面count值++,页面显示人数增加,因为session保存的是会话级值,在一次客户端与服务端的交互中,此值一直存在,也就是说当用户退出登录(session失效),值失效;如果session换为request,那么每一次刷新页面,页面显示人数都是1,因为request指在转发页面中保存值,每刷新一次页面都是一个新的值,因此值无法累加。

    <%--
      Created by IntelliJ IDEA.
      User: scq
      Date: 2020/11/20
      Time: 8:04
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>test</title>
    </head>
    <body>
    <%
    int count=1;
    if (null!=session.getAttribute("number")){
       count = Integer.parseInt(session.getAttribute("number").toString());
       count++;
       session.setAttribute("number",count);
    
    
    }else{
        session.setAttribute("number",count);
    }
    
    
    
    
    %>
    当前访问人数:<%session.getAttribute("number")%>
    </body>
    </html>
    
    

    tomcat与servlet的关系图

    tomcat响应给客户端请求的过程形式
    在这里插入图片描述

    JSP执行过程(面试)

    当客户端调用index.jsp,应用程序服务器根据index.jsp生成一个index.jsp.java文件,再根据这个java文件编译成class文件,将这个class文件告诉应用程序服务器。
    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • Idea部署web项目 ...发现启动服务器页面不进行跳转,显示的url地址为乱码。 解决: isELIgnored=“false 在开头添加这一行 因为 <%@ page isELIgnored="true|false”%>如果设定为真,那么JSP

    Idea部署web项目

    服务器用tomcat,实现一个启动服务到页面跳转的功能。
    windows.location.href="/url" 当前页面打开URL页面
    window.location.href=window.location.href;则是向指定的url提交数据

    发现启动服务器,页面不进行跳转,显示的url地址为乱码。
    解决: isELIgnored=“false 在开头添加这一行
    因为 <%@ page isELIgnored="true|false”%>如果设定为真,那么JSP中的表达式被当成字符串处理。所以解析错误,页面报404。
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 当发送一个URL请求时,不管这个URL是Web页面URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询。这能使浏览器获得请求对应的IP地址。 浏览器与远程Web...

    一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
    分为4个步骤:

    1. 当发送一个URL请求时,不管这个URL是Web页面的URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器上启动一个DNS查询。这能使浏览器获得请求对应的IP地址
    2. 浏览器与远程Web服务器通过TCP三次握手来建立一个TCP/IP连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
    3. 一旦TCP/IP连接建立,浏览器会通过该连接向远程服务器发送HTTP的GET请求。远程服务器找到资源并使用HTTP响应返回该资源,值为200的HTTP响应状态表示一个正确的响应。
    4. 此时,Web服务器提供资源服务,客户端开始下载资源。包括如下过程:

      -浏览器开始下载html文档(响应报头,状态码200),同时设置缓存。
      -之后浏览器对整个 HTML 结构进行解析,形成 DOM 树;与此同时,它还需要对相应的 CSS 文件进行解析,形成 CSS 树(CSSOM)。
      -接下来,需要结合 DOM + CSSOM,形成一个绘制树(Render Tree)。
      -得到绘制树之后,需要计算每个结点在页面中的位置,这一个过程称为layout 。
      -layout的过程是在一个连续的二维平面上进行的,接下来,需要将这些结果栅格化,映射到屏幕的离散二维平面上。这一过程称为 paint ; 现代浏览器为提升性能,将页面划分多个 layer,各自进行 paint 然后组合成一个页面(composite layers)。

    展开全文
  • 我在linux上安装了anaconda我正试着提出朱庇特笔记本...但是当我试图访问url时http://:8889我收到页面不可用错误。你知道我遗漏了什么吗?这是启动Jupyter笔记本后的输出:bin]$ ./jupyter notebook --no-browser --p...

    我在linux上安装了anaconda我正试着提出朱庇特笔记本如下:

    ./jupyter notebook --no-browser --port=8889

    看起来它启动了,控制台上没有错误。但是当我试图访问url时

    http://:8889

    我收到页面不可用错误。你知道我遗漏了什么吗?

    这是启动Jupyter笔记本后的输出:

    bin]$ ./jupyter notebook --no-browser --port=8889

    [I 15:43:02.760 NotebookApp] JupyterLab beta preview extension loaded from /usr/local/clo/ven/python-2.7.12/anaconda2/lib/python2.7/site-packages/jupyterlab

    [I 15:43:02.760 NotebookApp] JupyterLab application directory is /usr/local/clo/ven/python-2.7.12/anaconda2/share/jupyter/lab

    [I 15:43:02.765 NotebookApp] Serving notebooks from local directory: /usr/local/clo/ven/python-2.7.12/anaconda2/bin

    [I 15:43:02.765 NotebookApp] 0 active kernels

    [I 15:43:02.766 NotebookApp] The Jupyter Notebook is running at:

    [I 15:43:02.766 NotebookApp] http://localhost:8889/?token=e2d0598937406066fc34f23f5f2187f2d6393976d84b5a2e

    [I 15:43:02.766 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

    [C 15:43:02.766 NotebookApp]

    Copy/paste this URL into your browser when you connect for the first time,

    to login with a token:

    http://localhost:8889/?token=e2d0598937406066fc34f23f5f2187f2d6393976d84b5a2e&token=e2d0598937406066fc34f23f5f2187f2d6393976d84b5a2e

    展开全文
  • URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址。 浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP ...
  • (1),当发送一个URL请求时,不管这个URL是Web页面URL还是Web页面上每个资源的URL, 浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询。这能使浏览器获得请求对应的IP地址。 (2...
  • 当发送一个url请求时(可能是web页面也可能是web页面中的资源url),浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询,使浏览器获得请求对应的IP地址。 浏览器与远程WEB服务器通过TCP...
  • 发送一个URL请求,不管这个URL是web页面URL还是web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询,这能使浏览器获得请求对应的IP地址。 浏览器与远程服务器...
  • URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址。 2. 浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。该握...
  • 当发送一个URL请求时,不管这个URL是web页面URL还是web页面的每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询,这样就可以使得浏览器获得请求对应的IP地址了。...
  • (1)当发送一个URL请求时,不管这个URL是Web页面URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询。这能使浏览器获得请求对应的IP地址。 (2)浏览器与...
  • 从输入URL页面加载完成的过程中都发生了什么事情? 一、初始准备(服务器端) 1.服务器启动监听服务,准备迎接来自客户机的请求。服务器启动操作系统—启动http服务进程(apache or nginx or ..)--服务...
  • 标签,src引用的就是本地的视频,视频在Tomcat服务器里边。 (项目是ssm框架/前端页面没有用框架,就是jsp页面) 1. 我在我本地运行来了访问没问题,视频可以播放; 2. 在局域网中运行起来,别的电脑访问也可以...
  • 当发送一个 URL 请求时,不管这个 URL 是 Web 页面URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址...
  • 工作中曾经遇到这样的需求,同一套代码,要在不同端(微信、普通浏览器、第三方app)显示,第三方app...之前的同事通过复制不同node层入口,启动不同服务器,然后引入不同页面实现。这种做法其实将问题复杂化了。...
  • 1、当发送一个URL请求时,浏览器会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询,解析获取网址的IP地址;2、浏览器与远程Web服务器通过TCP三次握手协商来建立一个TCP/IP连接。该握手包括一个...
  • 刚开始在eclipse 开发和调试web服务器,用的是tomcat,启动服务后,在浏览器中输入:localhost:8080 老是会报异常,并且也无法访问到欢迎页面,必须要加上项目名才 可以,例如localhost:8080/{project_name} ...
  • 在Django的views里面用matplotlib画图并保存到项目static文件夹里,启动服务器,matplotlib 绘图的图像保存为 HTML 文件HTML 文件中,内嵌的图片是以 base64 代码的形式嵌入的,故而只需将图像转为 base64 代码即可...
  • 分为4个步骤: (1)当发送一个URL请求时,不管这个URL是Web页面URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询。这能使浏览器获得请求对应的IP...
  •  答:服务器启动好监听服务,准备迎接来自客户机的请求, 1、输入地址  当我们开始在浏览器中输入网址的时候,浏览器其实已经开始在智能的匹配可能得到的URL了,他会从历史记录、书签等地方,找到已经输入的字符...
  • 分为4个步骤:(1),当发送一个URL请求时,不管这个URL是Web页面URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器启动一个DNS查询。这能使浏览器获得请求对应的IP...
  • VS环境里面,菜单-项目-项目属性(最下得选项)-配置属性(左边第二项)-Debugging-Enable Asp.Net Debugging 设置为True作用:确定调试器能过启动IIS来调试asp.net页面!2:确认你的"we
  • 那我们就开始了,故事其实并不是从在浏览器的地址栏输入一个网址,或者我们抓着鼠标点击一个链接开始,事情的开端要追溯到服务器启动监听服务的时候,在某个未知的时刻,一台机房里普普通通的刀片服务器,加上电,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 582
精华内容 232
关键字:

服务器启动页面url