20210903上课

20210903上课

重定向和请求转发

请求转发(forward)
请求转发也称之为服务端跳转,即客户端只发送一次请求,后续的多次请求由服务端发起,因此客户端的请求地址栏只会显示第一次发送的地址(实际服务端已经在内部转发了多次),请求转发可以将存储在一次request范围(客户端发起的)之内的数据传递到下一个Servlet
重定向也称之为客户端跳转,即客户端请求会发送多次,而且地址栏会显示最后一次请求的地址,由于重定向是客户端的跳转方式,因此每次请求之间没有直接关系,所以存储在request范围之内数据无法传递到下一个请求
面试题:请你聊聊重定向和请求转发的区别?
相同点
*页面都会实现跳转
不同点
*请求转发的时候,url不会产生变化 307
*重定向时候,url地址栏会发生变化 302
getRequestDispatcher分成两种,可以用request调用,也可以用getServletContext()调用
不同的是request.getRequestDispatcher(url)的url可以是相对路径也可以是绝对路径。
而this.getServletContext().getRequestDispatcher(url)的url只能是绝对路径。

1、sendRedirect

LoginServlet

@WebServlet("/user/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入登录");
        resp.sendRedirect("goods/list");
    }
}

GoodListServlet

@WebServlet("/goods/list")
public class GoodListServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入商品列表");
    }
}
当在地址栏请求的时候出现404
http://localhost:8080/20210902/user/goods/list
因为现在在user后面直接拼接了goods/list因为user下面没有这个模块所以请求不到.现在想要解决的办法有:
resp.sendRedirect("../goods/list");

2、getRequestDispatcher

//获得到请求的调度器
//RequestDispatcher rd = req.getRequestDispatcher("../goods/list");
//rd.forward(req,resp);

区别:

1、请求转发能够从服务端发起跳转,重定向是在客户端进行跳转
2、地址不发生改变
   重定向的地址会发生改变
   请求转发的地址始终发生不变
   
3、请求转发每次刷新都会刷新整个过程,比如:付款转账延时的时候刷新会将之前的内容再次执行
   

3、getAttribute和setAttribute

​ 请求转发可以将存储在request范围之内的数据传输给下一个servlet中

@WebServlet("/user/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入登录");

        //resp.sendRedirect("../goods/list");
        //获得到请求的调度器
        //RequestDispatcher rd = req.getRequestDispatcher("../goods/list");
        //rd.forward(req,resp);

        req.setAttribute("username","ZhangSan");
        req.getRequestDispatcher("../goods/list").forward(req,resp);

    }
}
@WebServlet("/goods/list")
public class GoodListServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入service");
				System.out.println("goodList获取request中的数据:" + obj);
        Object obj = req.getAttribute("username");
        req.getRequestDispatcher("../system/info").forward(req,resp);
    }
}
@WebServlet("/system/info")
public class SystemServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入到系统信息");
        Object username = req.getAttribute("username");
        Object list = req.getAttribute("list");
        System.out.println("username : " + username);
        System.out.println("list : " + list);
    }
}
request的作用域一次request请求的范围(客户端请求)

Servlet作用域对象的问题

request

request作用域作用于一次请求范围(客户端请求),当使用请求转发跳转时,可以向request范围之内存储数据,并且在下一个Servlet中可以将request的数据获取
使用方式:
//存储数据到request
request.setAttribute(name,value);
//获取request数据
request.getAttribute(name)

session

session也称之为会话,通常指的是一次项目的访问过程(只要浏览器不关闭,或者不到达session的有效期)存储在session范围之内的数据会一直存在。
session有效期默认是:30分钟(在tomcat的web.xml文件中有配置):
如果需要修改session的有效期,不要去直接修改服务器中的web.xml;而是应该修改web项目中WEB-INF下的web.xml
  
<!--配置session的有效期(单位:分钟)-->
    <session-config>
        <session-timeout>20</session-timeout>
    </session-config>  
  
客户端每一次服务端建立连接时都会创建一个session(具备一个独一无二的sessionid),在同一次访问中,无论页面(请求)如何跳转,只要sessionid是同一个,则session中的数据是一直有效且共享的。一旦浏览器关闭,下一次重新开启时,sessionid会发生变更。
使用方式
HttpSession session = request.getSession();
//存储数据到session
session.setAttribute(name,value);
//取出session中的数据
session.getAttribute(name)
作用:
session的存储范围为服务端,一般用于存储一些安全性要求较高的少量数据,比如:用户的登录信息(账号密码等)
LoginServlet中一个代码
req.setAttribute("username","ZhangSan");
req.getRequestDispatcher("../goods/list").forward(req,resp);SystemServlet的service方法中添加一个代码,请求转发的时候可以将username的值带到SystemServlet,但是重定向是不可以的

Object username = req.getAttribute("username");  
//设置响应编码
resp.setCharacterEncoding("utf-8");
  
resp.getWriter().write("<html>");
        resp.getWriter().write("<head>");
        resp.getWriter().write("<meta charset=\"utf-8\">");
        resp.getWriter().write("<title>系统信息</title>");
        resp.getWriter().write("</head>");
        resp.getWriter().write("<body>");
        resp.getWriter().write("<h1>系统信息页</h1>");
        resp.getWriter().write("<hr>");
        resp.getWriter().write("欢迎你,"+username);
        resp.getWriter().write("</body>");
        resp.getWriter().write("</html>");  
在使用重定向的时候就使用session进行存储值

在LoginServlet中一个代码
	//从Request范围获取session
	HttpSession session = req.getSession();
	System.out.println("session被创建,sessionID:"+session.getId());
	//一旦客户端和服务端建立连接,服务端会自动产生一个session,如果session已存在,则不创建直接使用
	//如果不存在,则创建一个;如果使用req.getSession(true),无论何时都会重新创建session对象
	//req.getSession(false);
	session.setAttribute("user","softeem");GoodsListServletObject user = req.getSession().getAttribute("user");
	System.out.println("goodsList取得Session数据:"+user);SystemServlet中修改
  resp.getWriter().write("欢迎你,"+req.getSession().getAttribute("user"));
两个页面之间共享数据使用request
整个页面使用的时候是session
多个用户使用的时候是SevletContent

ServletContext

ServletContext也称之为上下文环境;一旦web容器启动,项目被装载后,服务端会自动创建一个上下文环境(SerlvetContext,该环境是唯一的**(单例)**;只要服务器不重启,存储在在该范围内的数据会一直有效,并且可以实现多个用户之间的数据共享。
//获取ServletContext(jsp:application)
//方式一:
    ServletContext app1 = this.getServletContext();
//方式二:
    ServletContext app2 = this.getServletConfig().getServletContext();
//方式三:
    ServletContext app3 = req.getSession().getServletContext();

    System.out.println(app1);
    System.out.println(app2);
    System.out.println(app3);
    app1.setAttribute("viewCount",10);
使用方式:
		ServletContext context = req.getSession().getServletContext();
		//存储数据到ServletContext
		context.setAttribute(name,value);
		//获取ServletContext数据
		context.getAttribute(name)
      
      
  如果需要对指定作用域中的属性清除可以使用:
	removeAttribute(name)移除
	对于session来说还可以直接使用`invalidate()`方法,清除整个session对象
      
  resp.getWriter().write("<html>");
        resp.getWriter().write("<head>");
        resp.getWriter().write("<meta charset=\"utf-8\">");
        resp.getWriter().write("<title>系统信息</title>");
        resp.getWriter().write("</head>");
        resp.getWriter().write("<body>");
        resp.getWriter().write("<h1>系统信息页</h1>");
        resp.getWriter().write("<hr>");
        resp.getWriter().write("欢迎你,"+username);
        resp.getWriter().write("<p>网站总访问量:"+this.getServletContext().getAttribute("viewCount")+"</p>");
        resp.getWriter().write("</body>");
        resp.getWriter().write("</html>");  

清空session

@WebServlet("/req/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+"/"+password);
        if(Objects.equals("softeem",username)){
            if(Objects.equals("123456",password)){
                //向session中存储用户信息
                req.getSession().setAttribute("user",username);
                //登录成功(跳转主界面)
                resp.sendRedirect("../req/index");
            }else{
                //密码错误
                req.setAttribute("msg","密码错误");
                req.getRequestDispatcher("../req/loginpage").forward(req,resp);
            }
        }else{
            //账户不存在
            req.setAttribute("msg","账户不存在");
            req.getRequestDispatcher("../req/loginpage").forward(req,resp);
        }
    }
}
@WebServlet("/req/loginpage")
public class LoginPageServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        Object msg = req.getAttribute("msg");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().write("<html>");
        resp.getWriter().write("<head>");
        resp.getWriter().write("<meta charset='UTF-8'>");
        resp.getWriter().write("<title>用户登录</title>");
        resp.getWriter().write("</head>");
        resp.getWriter().write("<body>");
        resp.getWriter().write("<h1>用户登录</h1>");

        if(msg != null) {
            resp.getWriter().write("<h2 style=\"color:red\">" + msg + "</h2>");
        }
        resp.getWriter().write("<form action=\"../req/login\">");
        resp.getWriter().write("账号:<input type='text' name='username'><br>");
        resp.getWriter().write("密码:<input type='password' name='password'><br>");
        resp.getWriter().write("<button>登录</button>");
        resp.getWriter().write("</form>");
        resp.getWriter().write("</body>");
        resp.getWriter().write("</html>");
    }
}
@WebServlet("/req/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        Object user = req.getSession().getAttribute("user");
        if(user == null){
            req.setAttribute("msg","请登陆后再试!");
            req.getRequestDispatcher("../req/loginpage").forward(req,resp);
            return;
        }

        resp.setCharacterEncoding("utf-8");
        resp.getWriter().write("<html>");
        resp.getWriter().write("<head>");
        resp.getWriter().write("<meta charset='UTF-8'>");
        resp.getWriter().write("<title>主页</title>");
        resp.getWriter().write("</head>");
        resp.getWriter().write("<body>");
        resp.getWriter().write("<h1>XXX管理系统</h1>");
        resp.getWriter().write("<h2>欢迎你,"+user+"</h2>");
        resp.getWriter().write("<a href='../req/logout'>安全退出</a>");
        resp.getWriter().write("</body>");
        resp.getWriter().write("</html>");
    }
}
@WebServlet("/req/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //将session中的指定属性移除
//        session.removeAttribute("user");
//        req.removeAttribute("XXX");
//        this.getServletContext().removeAttribute("XXX");
        //将session失效
        session.invalidate();
        resp.sendRedirect("../req/loginpage");
    }
}

Cookie

Http协议是无状态的(每次一次的http请求相互之间无关联),但是实际开发中经常需要在多个请求之间进行数据的传递,以及状态的转移;此时servlet中支持四种会话跟踪技术:

  1. URL传值(get请求)

    http://localhost/javaweb01/login?username=admin&password=123456&code=0.12312435345345
    
  2. 隐藏域传值(post/get请求)

    <input type="hidden" name="method" value="login">
    
  3. session

    session.setAttribute(name,value);
    
  4. Cookie

    Cookie是客户端浏览器,实现数据缓存的一种技术,是通过在本地操作系统中以文件存储的形式,存储少量(4kb左右)的数据信息;cookie由服务端制造,通过response对象响应到客户端,然后再通过request发送到服务端,

cookie的使用如下:

  1. 制造并存储cookie

    public class User {
        private int id;
        private String username;
        private String password;
        private int level;
      
      public class Model {
        int code;
        String msg;
        Object data;
    
    @WebServlet("/cookie/add")
    public class CookieServlet extends HttpServlet {
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            User u = new User(1,"张三","张三123",5);
            Model m = new Model(0,"操作成功",u);
    
            //创建cookie对象
            Cookie c = new Cookie("username","softeem");
            //设置cookie的有效期(秒) 一周时间  默认有效期与session保持一致
            c.setMaxAge(60*60*24*7);
            //设置cookie生效的域名(主机地址)
            //        c.setDomain("com.softeem.top");
            //设置cookie生效的位置(对于同一个主机中的哪一个项目)
            //        c.setPath("/javaweb05");
            c.setPath("/");
    
            //将对象转换为json字符串
            String s = JSON.toJSONString(m);
            //将数据转码(Cookie不支持中文和特殊符号)
            s = URLEncoder.encode(s, "utf-8");
            System.out.println("json---->"+s);
            Cookie c2 = new Cookie("info", s);
            c2.setMaxAge(60*60*24);
            c2.setPath("/javaweb05");
            //将cookie对象通过response对象发送到客户端
            resp.addCookie(c);
            resp.addCookie(c2);
        }
    }
    
    
  2. 读取Cookie

    @WebServlet("/cookie/read")
    public class ReadCookieServlet extends HttpServlet {
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		//获取从客户端传递过来的所有cookie信息
            Cookie[] cookies = req.getCookies();
            for (Cookie c : cookies) {
                String name = c.getName();
                String value = c.getValue();
                System.out.println(name+"---->"+value);
                if("info".equals(name)){
                    //解码
                    String json = URLDecoder.decode(value, "utf-8");
                    System.out.println("info解码后:"+json);
                    //解析为javabean
                    Model model = JSON.parseObject(json, Model.class);
                    System.out.println("解析json为javabean:"+model);
                }
            }
        }
    }
    
    @WebServlet("/cookie/login")
    public class LoginServlet extends HttpServlet {
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String save = req.getParameter("save");
            if("softeem".equals(username) && "123456".equals(password)){
                if("1".equals(save)){
                    //保存账号信息
                    User u = new User();
                    u.setUsername(username);
                    u.setPassword(password);
                    String data = URLEncoder.encode(JSON.toJSONString(u), "utf-8");
                    System.out.println("存储用户:"+data);
                    //将用户对象转换为json字符串并转码之后存储到cookie中
                    Cookie c = new Cookie("user", data);
                    c.setMaxAge(60*60*24*7);
                    c.setPath("/javaweb05");
                    resp.addCookie(c);
                }
                resp.sendRedirect("main.html");
            }else{
                //登录失败
                req.setAttribute("msg","请检查账号或密码");
                req.getRequestDispatcher("../index.jsp").forward(req,resp);
            }
        }
    }
    
    @WebServlet("/cookie/check")
    public class CheckCookieServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String username = req.getParameter("username");
            Cookie[] cookies = req.getCookies();
            for (Cookie c : cookies) {
                if(c.getName().equals("user")){
                    String user = URLDecoder.decode(c.getValue(), "utf-8");
                    User u = JSON.parseObject(user,User.class);
                    if(u.getUsername().equals(username)){
                        req.setAttribute("user",u);
                    }
                }
            }
            req.getRequestDispatcher("../index.jsp").forward(req,resp);
        }
    }
    
    <html>
      <head>
        <base href="<%=basePath%>">
        <meta charset="UTF-8">
        <title>$Title$</title>
      </head>
      <body>
    
      <h2 style="color:red"><%=request.getAttribute("msg")%></h2>
      <%--<%=((User)request.getAttribute("user")).getUsername()%>--%>
        <form action="cookie/login">
          <input type="text" name="username" id="username" value="${user.username}" placeholder="请输入用户名"><br>
          <input type="password" name="password" value="${user.password}" placeholder="请输入密码"><br>
          <input type="checkbox" name="save" value="1">保存一周 <br>
          <button>登录</button>
        </form>
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
      <script>
        $(function(){
          $("#username").blur(function(){
            location.href="cookie/check?username="+$(this).val();
          })
        })
      </script>
      </body>
    </html>
    
    

Cookie的应用场景:

  1. 大型网站的首页信息的缓存
  2. 购物车功能
  3. 保存账号功能
  4. 历史浏览记录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值