zoukankan      html  css  js  c++  java
  • Servlet 学习(五)

    重定向redirect

    1、使用方法

    • response.sendRedirect("/应用名/ 访问资源名");
    • response.sendRedirect(request.getContextPath() + "/pages/dispatch/index.html");

    2、重定向原理

    重定向中,组件A 的request 和response 不会被组件B 所共享或继续使用使用重定向,浏览器地址栏显式的地址会发生改变!

    3、重定向测试案例

    测试案例:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Dispatch</title>
    </head>
    <body>
    
        <h5>注册</h5>
        <form action="/Servlet/dispatch/regist" method="post" >
            <input type="text" name="username" placeholder="用户名">
            <input type="password" name="password" placeholder="输入密码">
            <input type="password" name="confirm" placeholder="确认密码">
            <input type="submit" value="提交">
        </form>
        
        <hr>
        
        <a href="/Servlet/page/login" >登录</a>
        
    </body>
    
    </html>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>成功</title>
    </head>
    <body>
    
        <h1>成功</h1>
    
    </body>
    </html>
    package ecut.dispatch.redirect;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/dispatch/regist")
    public class RegistServlet extends HttpServlet {
    
        private static final long serialVersionUID = -4191840660711521199L;
    
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("regist");
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
    
            // PrintWriter w = response.getWriter();
    
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String confirm = request.getParameter("confirm");
    
            // 判断用户名是否为空 ( 页面上可能根本就没有提交username 、页面提交了空串)
            if (username == null || username.trim().isEmpty()) {
                // 不能注册
                // w.println("<h3>用户名不能为空,3秒后返回首页</h3>");//刷新存在表单再次提交问题,因为地址没有改变还是当前URL,刷新就会再次请求
                // response.setHeader("refresh", "3,URL=" +request.getContextPath() + "/pages/dispatch/index.html"); // 定时跳转
                response.sendRedirect(request.getContextPath() + "/pages/dispatch/index.html");//重定向到了另一个页面解决了表单提交的问题
                return;
            } else {
                // 用户名可能使用,但是需要检查密码是否为空且两次密码输入是否一致
                if (password != null && password.length() != 0 && password.equals(confirm)) {
                    // 可以注册
                    // w.println( "<h3>注册成功</h3>" );
                    response.sendRedirect(request.getContextPath() + "/pages/dispatch/success.html");
                    return;
                } else {
                    // 没有密码 或 密码输入不一致 不能注册
                    // w.println( "<h3>密码输入不正确</h3>" );
                     response.sendRedirect(request.getContextPath() + "/pages/dispatch/index.html");
                    return;//响应结束了
                }
            }
    
        }
    
    }

    运行结果如下:

    输入正确跳转到成功页面,其他情况回到首页

     

    请求调度器RequestDispatche

    1、它是javax.servlet 中的一个接口

    • 使用时的实现类,由Servlet容器提供
    • 该接口中所包含的方法(仅此两个),forward() 和include()

    2、获取RequestDispatcher 的途径

    • ServletRequest#getRequestDispatcher(String path)
    • ServletContext#getRequestDispatcher(String path)
    • ServletContext#getNamedDispatcher(String name)

    转发forward

    1、使用方法

    • request.getRequestDispatcher("/相对路径<不包含应用名>").forward( request , response );
    • RequestDispatcher dispatcher = request.getRequestDispatcher( "/page/success" );
      dispatcher.forward( request , response );

    2、转发原理

    转发中,组件A 的request 和response 会被组件B 继续使用(被传递过来),使用转发,浏览器地址栏显式的地址不会发生改变!

     

    3、转发测试案例

    测试案例:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>登录成功</title>
    </head>
    <body>
        <h1>登录成功</h1>
    </body>
    </html>
    package ecut.dispatch.forward;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    //登陆页面
    @WebServlet( "/page/login" )
    public class LoginPageServlet extends HttpServlet {
    
        private static final long serialVersionUID = 2075180219363356668L;
    
        @Override
        protected void service( HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            response.setContentType( "text/html;charset=UTF-8" );
            
            PrintWriter w = response.getWriter();
            
            w.println( "<!DOCTYPE html>" );
            w.println( "<html>" );
            w.println( "<head>" );
            w.println( "<meta charset='UTF-8'>" );
            w.println( "<title>登录</title>" );
            w.println( "</head>" );
            w.println( "<body>" );
            w.println( "    <h5>登录</h5>" );
            
            w.println( "    <form action='" + request.getContextPath() + "/action/login' method='post' >" );
            w.println( "        <input type='text' name='username' placeholder='用户名'>" );
            w.println( "        <input type='password' name='password' placeholder='输入密码'>" );
            w.println( "        <input type='submit' value='登录'>" );
            w.println( "    </form>" );
            
            w.println( "</body>" );
            w.println( "</html>" );
            
        }
        
        
    
    }
    package ecut.dispatch.forward;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    //登陆操作
    @WebServlet( "/action/login" )
    public class LoginActionServlet extends HttpServlet {
    
        private static final long serialVersionUID = 6978052887387276476L;
    
        @Override
        protected void service( HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            response.setContentType( "text/html;charset=UTF-8" );
            
            String username = request.getParameter( "username" );
            String password = request.getParameter( "password" );
            
            System.out.println( "username : " + username + " , password : " + password );
            
            if( "zhangsanfeng".equals( username ) && "hello2017".equals( password ) ){
                //RequestDispatcher dispatcher = request.getRequestDispatcher( "/WEB-INF/dispatch/login_success.html" );
                //dispatcher.forward( request , response );//转发到另一个页面,刷新页面存在表单重新提交的问题,因为地址没有改变还是当前URL,刷新就会再次请求再次提交表单
                response.setHeader("suibian", "suibianzhi");
                request.setAttribute("counter", 250);//可以将request当做Map<String , Object>来使用,map.put("counter",250)
                RequestDispatcher dispatcher = request.getRequestDispatcher( "/page/success" );
                dispatcher.forward( request , response );//转发到另一个页面Servlet,刷新页面存在表单重新提交的问题,因为地址没有改变还是当前URL,刷新就会再次请求再次提交表单
                
                //为了解决表单重复提交的问题,可以采取以下方法:
                // 1、重定向到另外的一个 Servlet ,比如 LoginSuccessServlet
                // 2、由 另外的一个 Servlet ,比如 LoginSuccessServlet 完成 转发操作
                //response.sendRedirect(  request.getContextPath() + "/forward/login/success" );//由LoginSuccessServlet去转发
                return ;
            } else {
                response.sendRedirect(  request.getContextPath() + "/page/login" );
                return ;
            }
            
        }
        
        
    
    }
    package ecut.dispatch.forward;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    //登陆页面
    @WebServlet( "/page/success" )
    public class SuccessPageServlet extends HttpServlet {
    
        private static final long serialVersionUID = 2075180219363356668L;
    
        @Override
        protected void service( HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            response.setContentType( "text/html;charset=UTF-8" );
            Object value=request.getAttribute("counter");//可以将request当做Map<String , Object>来使用,map.get("counter")
            System.out.println(value);//用的是同一个请求
            System.out.println(response.getHeader("suibian"));//用的是同一个响应
            PrintWriter w = response.getWriter();
            
            w.println( "<!DOCTYPE html>" );
            w.println( "<html>" );
            w.println( "<head>" );
            w.println( "<meta charset='UTF-8'>" );
            w.println( "<title>登录</title>" );
            w.println( "</head>" );
            w.println( "<body>" );
            w.println( "    <h1>登录成功</h1>" );
            w.println( "</body>" );
            w.println( "</html>" );
            
        }
        
        
    
    }
    package ecut.dispatch.forward;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( "/forward/login/success" )
    public class LoginSuccessServlet extends HttpServlet {
    
        private static final long serialVersionUID = -7565331422887485255L;
    
        @Override
        protected void service( HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            response.setContentType( "text/html;charset=UTF-8" );
            //这个页面不能被直接访问
            RequestDispatcher dispatcher = request.getRequestDispatcher( "/WEB-INF/dispatch/login_success.html" );
            dispatcher.forward( request , response );
            
        }
        
        
    
    }

    运行结果如下:

    username : AmyZheng , password : 123
    250
    suibianzhi
    username : AmyZheng , password : 
    username :  , password : 

    转发和重定向的区别

    • Redirect ( 重定向 ) :

        地址栏:

          从第一个被请求的地址 变成 第二个请求对应的地址
        客户端发起两次请求:
          第一次请求由 "用户" 主动发起
          第二次请求是由于 浏览器接受到了 来自服务器的 "指示"所以重新发起请求

        实现:

          重定向通过 response.sendRedirect( location ) 来实现

    • Forward ( 转发 )  

        地址栏:

          所请求的路径不会发生变化
        客户端仅发起一次请求:

          服务器内部完成对请求的组件的调度在 /page/login 对应的页面的登录表单:<form ation = request.getContextPath() +  "/action/l
          ogin"  >,因此点击登陆按钮后会请求 /action/login,而在 /action/login 对应的 Servlet 中:RequestDispatcher dispatcher = req
          uest.getRequestDispatcher( "/WEB-INF/dispatch/login_success.html" );dispatcher.forward( request , response );

        实现:

          转发通过非静态方法 RequestDispatcher.forward( ServletRequest , ServletResposne ) 方法来实现在转发操作中 ,第一个组件的
          request 和 response 被传递给 第二个组件继续使用:

    包含include

     1、使用方法

    • request.getRequestDispatcher("/相对路径<不包含应用名>"). include(request , response);
    • dispatcher = request.getRequestDispatcher( "/pages/dispatch/header.jsp" );                                                                                                                   dispatcher.include( request , response );

    2、包含原理

    3、包含测试案例

    测试案例一:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>header</title>
    <style type="text/css">
        .header { 
            border: 1px solid #dedede ; 
            box-shadow: 0px 0px 5px 4px #eee ; 
            width : 600px ; 
            margin: 20px auto ;
            height: auto;
            overflow: hidden;
        }
        
        .header span {
            float: left ;
            text-align : center ;
            width: 25% ;
            line-height : 80px ; 
            height : 80px ; 
            box-shadow: 0px 0px 1px 0px blue inset ;
        }
    </style>
    </head>
    <body>
    
        <div class="header">
            <span>first</span>
            <span>second</span>
            <span>third</span>
            <span>forth</span>
        </div>
    
    </body>
    </html>
    package ecut.dispatch.include;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( "/include/first" )
    public class FirstServlet extends HttpServlet {
    
        private static final long serialVersionUID = 3984166560156790204L;
        
        @Override
        protected void service( HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            response.setContentType( "text/html;charset=UTF-8" );
            //斜杆表示从WebContent算起的路径
            RequestDispatcher dispatcher = request.getRequestDispatcher( "/pages/dispatch/header.html" );
            //jsp就是servlet所以不会报错,因此可以包含多个
            //RequestDispatcher dispatcher = request.getRequestDispatcher( "/pages/dispatch/header.jsp" );
    
            dispatcher.include( request , response );
            //包含静态资源(HTML页面)的时候,页面输出完,流就结束意味着响应结束,再去输出流就会报错
            //getOutputStream() has already been called for this response,想获得输出流时候但是响应结束了
            PrintWriter w = response.getWriter() ; 
            
            w.println( "<h1>First Servlet</h1>" );
            
        }
    
    }

    运行结果如下:

     

    测试案例二:

    <%@ page language="java"  pageEncoding="UTF-8" %>
    <%@ page contentType="text/html; charset=UTF-8" %>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>header</title>
    <style type="text/css">
        .header { 
            border: 1px solid #dedede ; 
            box-shadow: 0px 0px 5px 4px #eee ; 
            width : 600px ; 
            margin: 20px auto ;
            height: auto;
            overflow: hidden;
        }
        
        .header span {
            float: left ;
            text-align : center ;
            width: 25% ;
            line-height : 80px ; 
            height : 80px ; 
            box-shadow: 0px 0px 1px 0px blue inset ;
        }
    </style>
    </head>
    <body>
    
        <div class="header">
            <span>first</span>
            <span>second</span>
            <span>third</span>
            <span>forth</span>
        </div>
    
    </body>
    </html>
    package ecut.dispatch.include;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( "/include/second" )
    public class SecondServlet extends HttpServlet {
    
        private static final long serialVersionUID = 3984166560156790204L;
        
        @Override
        protected void service( HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            response.setContentType( "text/html;charset=UTF-8" );
            
            RequestDispatcher dispatcher = request.getRequestDispatcher( "/pages/dispatch/header.jsp" );
            dispatcher.include( request , response );
            
            PrintWriter w = response.getWriter() ; 
            
            w.println( "<h1 style='text-align:center;'>Second Servlet</h1>" );
            
            dispatcher = request.getRequestDispatcher( "/pages/dispatch/header.jsp" );
            dispatcher.include( request , response );
            
        }
    
    }

    运行结果如下:

    转发和包含的区别

    •  Forward ( 转发 )

        转发通过非静态方法 RequestDispatcher.forward( ServletRequest , ServletResposne ) 方法来实现
        响应有去无回
          web client ---->  A(request,response)
                                   A:forward(request,response)
                                     B(request,response)       --------->web client 

    • Include ( 包含)

        包含通过非静态方法 RequestDispatcher.include( ServletRequest , ServletResposne ) 方法来实现
        响应有去有回
          web client ---->  A(request,response)  --------->web client
                                    A:include(request,response)
                         ^
                                      |
                                      |
                                      |
                                      |
                                      |
                                  B(request,response)      

    转载请于明显处标明出处

    http://www.cnblogs.com/AmyZheng/p/8902155.html

  • 相关阅读:
    相对路径和绝对路径的问题"/"带不带斜杠
    El表达式获取项目名称
    struts 中的创建Action的三种方法
    maven中的profile文件的解析
    Maven中模块的聚合以及对jar包的继承
    Maven中解决依赖冲突的问题
    maven中的传递依赖和传递依赖的解除
    String类为什么是final的
    jdbc 报错解决办法
    org.hibernate.PropertyValueException: not-null property references a null or transient value:
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/8902155.html
Copyright © 2011-2022 走看看