jsp学习

jsp的基本用法

在jsp中,主要有下面几种语法:

  • <%…%>,两个%里面用于书写java代码,此时这个相当于java中的方法,所以在java的方法里面可以些什么,那么在<%…%>里面就可以写什么。
  • <%=…%>,用于输出,相当于java中的输出,所以里面可以写变量,那么就会输出这个变量的值,如果是一个方法,那么就会输出这个方法返回值。
  • <%!..%>:相当于类,所以可以用于定义全局变量和方法。

例如下面的例子中:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>演示jsp中的几种方式</title>
    </head>
    <body>
        <%
            int a = 10;//定义一个局部变量
        %>
        <%
            out.print(a++);//在这里通过out对象,调用print方法来输出a的值,然后a自增
        %>
        <%!
            //定义全局变量和方法
            int a = 100;
            public void fun1(){
                System.out.println(a);
            }
         %>
        <%
            out.print(this.a++);//输出全局变量,然后自增
            fun1();
        %>
    </body>
</html>

测试结果:
在这里插入图片描述
jsp的原理:

jsp其实是一个特殊的Servlet,那么当我们第一次访问这个jsp的时候,服务器会将其编译成为java文件(这个java文件其实是一个Servlet类),然后再把这个java文件编译成为.class文件.之后创建Servlet类对象。然后调用service方法。当下一次再次访问的时候,就会直接调用service方法了。

这就是为什么上面中<%!..%>中的a每次访问的值都会不一样,这就是因为再第一次访问的时候,我们输出的是它的初始值,然后下一次请求的时候,直接调用service方法来输出它的值。所以每次请求都会不一样。只有在tomcat服务器关闭了,那么这个servlet就结束了,此时当我们再次打开tomcat服务器来请求这个jsp的时候,那么就会再次从a的初始值开始。

而在<%…%>中的a由于是定义在方法中,方法已结束,这个局部变量就结束了,所以每次发送请求,<%%>中的a都是一样的输出。

jsp和Servlet的分工

  • jsp主要是负责请求页面时发送数据,以及在响应的时候显示数据
  • Servlet则是负责中间处理过程.

例如下面的例子中,add1.jsp和add2.jsp由jsp来负责的,用于请求时发送数据以及响应时的显示页面,而AServlet则是在中间过程处理数据的过程.

<!--add1.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>add1</title>
    </head>
    <body>
        <form action="/AServlet" method="post">
            整数1: <input type="text" name="num1"><br>
            整数2: <input type="text" name="num2"><br>
            <input type="submit" value="提交">
        </form>
    </body>
</html>
<!--add2.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>add2</title>
</head>
<body>
   <%
       //利用jsp中已经建立的对象request,调用getAttribute,从而获取名字位sum的参数值
       int sum = (Integer)request.getAttribute("sum");//这是利用到了request域对象
       out.println(sum);
       System.out.println(sum);
   %>
</body>
</html>

Servlet类:

public class AServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int num1 = Integer.parseInt(request.getParameter("num1"));//获取请求参数num1的值
        int num2 = Integer.parseInt(request.getParameter("num2"));
        int result = num1 + num2;
        //将运算结果保留到request域中
        request.setAttribute("sum",result);
        //请求转发到add2.jsp中
        request.getRequestDispatcher("add2.jsp").forward(request,response);

    }
}

测试结果:
在这里插入图片描述

Cookie和Session

Cookie:由服务器创建,并且随着响应报文发送给客户端,保存到客户端中的一小段数据。当下一次客户端再次访问同一服务器的时候,那么这个cookie就会随着请求报文一起发送给服务器

服务器可以通过Set-Cookie响应头来创建cookie。但是如果创建多个cookie,那么不可以利用setHeader(“Set-Cookie”,“cookie_name=cookie_value”),因为setHeader创建的响应头是单值的。所以通过调用addHeader(“Set-Cookie”,“cookie_name1=cookie_value”);来创建多个cookie.

创建多个cookie之后,那么在响应报文中,Cookie响应头的值是多个cookie之间用;隔开,然后每个cookie都是以cookie_name=cookie_value的形式出现。例如当我们由"aaa=AAA","bbb=BBB"这2个cookie,那么此时的Cookie响应头的值为:“aaa=AAA;bbb=BBB”.

在javaweb中使用cookie:

  • 原始方式:response来调用addHeader(“Set-Cookie”,“cookie_name=cookie_value”)来创建多个cookie对象。然后利用request对象调用getHeader(“Cookie”)来获取请求头Cookie的值,返回的是一个字符串,例如"aaa=AAA;bbb=BBB"的形式,这样我们还需要将这个字符串分割成为数组,才可以获取每个cookie字符串,要想获取cookie的名字,还要再进行响应的操作,相对麻烦。
  • 便捷方式
    response调用addCookie(cookie1)方法来添加cookie,而在添加之前,我们需要创建cookie对象。
    然后来利用request调用getCookies()方法来返回一个cookie数组。这样,我们只要遍历这个cookie数组,每获得一个cookie,就可以调用响应的方法,就可以得到这个cookie的名字以及值。
<!--cookie1下的a.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加cookie</title>
</head>
<body>
     <h1>添加cookie</h1>
     <%
        /*通过调用addHeader来添加Set-Cookie响应头,那么这个响应头是多汁的,
         这样才可以添加多个cookie。否则,如果调用的是setHeader来添加cookie,
         那么这个响应头是单值的。
         response.addHeader("Set-Cookie","aaa=AAA");
         response.addHeader("Set-Cookie","bbb=BBB");*/
         Cookie cookie1 = new Cookie("aaa", "AAA");
         //调用addCookie来添加cookie
         response.addCookie(cookie1);
         Cookie cookie2 = new Cookie("bbb", "BBB");
         response.addCookie(cookie2);
     %>
</body>
</html>

<!--cookie1下的b.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>获取cookie</title>
</head>
<body>
    <h1>获取cookie</h1>
    <%
        /*
        通过获取请求头Cookie,从而获取cookie中的值
        String cookie = request.getHeader("Cookie");
        String[] split = cookie.split(";");
        for(String s: split) {
            out.println(s + "<br>");
        }
        但是通过获取cookie响应头的值返回的是一个字符串,这样我们没有办法来设置
        这个cookie的相关属性的值,例如它的路径,生命时长等。
        */
        //快捷方式:直接调用getCookies(),这样就会返回cookie数组
        Cookie[] cookies = request.getCookies();
        if(cookies != null){ 
            for(Cookie c : cookies){
               out.println(c.getName() + " = " + c.getValue() +
                    ",path = " + c.getPath() +
                    ",maxAge = " + c.getMaxAge() + "<br/>");
             }
        }
    %>
</body>
</html>

测试结果:
在这里插入图片描述

但是值得注意的是,如果我们添加的cookie的值是中文,那么这时候会发生500错误。例如下面我们a.jsp中为:

Cookie cookie1 = new Cookie("aaa", "小A");
response.addCookie(cookie1);
Cookie cookie2 = new Cookie("bbb", "小B");
response.addCookie(cookie2);

访问localhost:8080/cookie1/a.jsp,就会出现下面的错误:
在这里插入图片描述
cookie的生命时长可以通过setMaxAge(second)来设置,其中生命时长是以秒为单位的。其中second值得情况不同,cookie的生命时长不同。默认情况下(即没有设置cookie生命时长),cookie是在浏览器关闭之后就会失效的。

  • second > 0,cookie保存到了客户端的硬盘中,生命时长为second。
  • second < 0,那么cookie保存到了浏览器的内存中,一旦退出了浏览器,那么这个cookie就失效了
  • second = 0,那么此时的cookie立刻失效。再次查看它的请求头Cookie时,就不会存在这个cookie了。

值得一提的是,尽管我们已经设置了cookie的生命时长,但是最后调用getMaxAge()来输出的时候却是-1.xu要我们在浏览器中的特定位置查看才可以。以必应为例,我们需要点击设置->cookie和网站权限->管理和删除cookie和站点数据->查看所有Cookie和站点数据->找到自己对应的cookie.

正如下面代码中我们设置aaa的生命时长为1小时:

<!--这是cookie2下面的a.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>设置cookie的生命时长</title>
</head>
<body>
    <h1>设置cookie的生命时长</h1>
    <%
        //调用addCookie来添加cookie
        Cookie cookie1 = new Cookie("aaa", "AAA");//创建名字为aaa的cookie,对应的值为AAA
        //调用setMaxAge(second)来设置cookie的生命时长,以秒为单位
        /*
        设置生命时长为0,那么下面虽然能将当前这个cookie添加到响应头中,
        但是在获取请求头Cookie的值中并没有此时添加的cookie,因为它已经失效了
        cookie1.setMaxAge(0);
         */
        cookie1.setMaxAge(60 * 60);
        response.addCookie(cookie1);//调用addCookie添加cookie,此时响应头Set-Cookie,就会出现这个cookie
    %>
</body>
</html>

<!--这是cookie2下面的b.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>获取cookie的生命时长</title>
</head>
<body>
    <h1>获取cookie的生命时长</h1>
    <%
        Cookie[] cookies = request.getCookies();
        for(Cookie cookie: cookies){
            /*
            cookie的时长:
             不能通过getMaxAge()来访问,否则,最后输出的是-1,因此我们要通过浏览器
             来看,例如以必应为例,点击设置->cookie和网站权限->管理和删除cookie数据
             ->查看所有的cookie和站点数据.
             进行这一步之前,需要将所有的cookie数据删除,然后在测试,这样就能很快找到
             当前运行的cookie数据。然后点击对应名字的cookie,就可以查看它的路径和生命时长了
             */
            out.println(cookie.getName() + ", value = " + cookie.getValue() +
                       ", maxAge = " + cookie.getMaxAge() + "<br>");
        }
    %>
</body>
</html>

测试结果:
在这里插入图片描述
⭐注意,设置cookie的时长,需要保证它是在addCookie之前设置的,否则如果先写addCookie,然后再设置cookie的时长,那么setMaxAge是没有生效的,此时cookie是在浏览器关闭之后就会失效的。以上面cookie2下面的a.jsp中的代码为例:
在这里插入图片描述
⭐只要当前地址栏中的URL包括了cookie的路径,那么请求头Cookie就会带有响应的cookie。正如上面的,我们点击cookie2下面的b.jsp,那么请求头中就包括了aaa这个cookie。

而JSESSIONID的路径是/,所以始终会带有这个cookie。

Session:是客户端和服务端的一次会话过程,当会话结束或者这个session失效了,那么这个session就失效了。session是保存在服务端中

获取session,如果在Servlet中,可以根据request.getSession()来获取HttpSession对象,而在JSP中,session是它的内置对象,所以我们可以直接使用

Session也是一个域对象(request,session,application是三大域对象),都含有getAttribute(target),setAttribute(target,value),removeAttribute(target)这三个方法。这三个方法是常用的主要方法。但是在session中,还有几个常用的方法:

  • void invalidate():使当前的session失效,可以用于用户退出登录,当下次再次请求的时候需要重新登录了。
  • String getSessionId():获取sessionId
  • boolean isNew():判断当前的session是否是新建的。
  • int getMaxInactiveInternal():获取当前sssion最大的不活动时间(秒),默认是30分钟.可以在web.xml中设置session的最大不活动时间:

理解request.getSession()方法:

-> 客户端如果是第一次来访问服务端,那么就会创建session,并且将对应的sessionId发送给客户端

-> 当下次客户端再次发送请求的时候,会携带sessionId,那么服务端就会根据sessionId来查找session,

如果不能找到session,那么服务端就会再新建session,然后再将新的sessionId返回给客户端;否则如果能够找到session,那么就不需要再新建session。

练习: 利用session以及cookie来实现登录界面,要求如下:
在这里插入图片描述
所以解题思路:

  1. 创建login.jsp,success1.jsp,success2.jsp这几个文件,并且显示对应的页面。
  2. 创建LoginServlet类,用于处理数据。
  3. 在LoginServlet类中,首先获取login.jsp传来的数据,考虑到参数的值可能是中文,那么需要进行解码。此时请求编码,并且是post请求,所以直接调用setCharacterEncoding来设置编码即可。
  4. 然后判断用户名和密码是否正确,如果不正确,那么利用request域对象,调用setAttribute,来设置错误的提示信息,然后转发到login.jsp中(不可以是重定向,否则,在login.jsp中不可以利用request来获取提示信息)
  5. 否则,如果用户名和密码都正确,那么就需要保存当前登录的用户名保存到session中,这样就可以在success1.jsp中利用session调用getAttribute来获取登录用户了。
  6. 如果没有登录,直接访问success1.jsp,那么需要利用是否存在session来判断是否已经有用户登录了,如果没有,那么就设置对应的提示信息,并将提示信息转发到login.jsp中.
    LoginServlet类:
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //判断是否登录成功
        //对于客户端编码,我们需要利用request直接调用setCharacterEncoding即可
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("name");
        String password = request.getParameter("password");
        //判断用户名或者密码是否为空
        if(name == null || "".equals(name)){
            //说明用户名没有写就提交了登录按钮
            request.setAttribute("msg","用户名为空!!!");
            //转发到login.jsp页面
            request.getRequestDispatcher("/session/login.jsp").
                    forward(request,response);
        }
        if(password == null || "".equals(password)){
            //说明用户名没有写就提交了登录按钮
            request.setAttribute("msg","密码为空!!!");
            //转发到login.jsp页面
            request.getRequestDispatcher("/session/login.jsp").
                    forward(request,response);
        }
        //判断用户名和密码是否正确
        if("张三".equals(name) && "123456".equals(password)){
            /*
            密码正确,然后重定向到success1.jsp页面,并且将用户名保存到session中
            之所以要保存到session中,是因为session是在一次会话中的,只要没有关闭服务
            器,那么就可以这个session就一直存在,这样我们跳转到其他的页面,都可以
            利用session来获取用户名。

            如果我们使用的是request来保存name这个属性,那么就不可以利用重定向来跳转
            到success1.jsp中,因为此时的重定向是重新发送请求的,所以如果利用的是request,
            那么需要不断进行请求转发,但是地址栏上依旧是当前页面的url,显然并不符合实际开发.
            request.setAttribute("name",name);
            request.getRequestDispatcher("/session/success1.jsp")
                    .forward(request,response);
            */

            /*
            添加cookie,从而如果之前没有登录过,那么添加cookie,记住当前的用户
            然后在cookie失效之前,每次登录,都可以在文本框中显示登录用户的名字
            */
            Cookie cookie = new Cookie("username", URLEncoder.encode(name,"utf-8"));
            /*
            设置当前cookie时长为1小时,注意这个语句需要在addCookie执行之前执行
            否则,如果是下面那样,那么就会导致cookie存入到了浏览器内存中,当浏览器
            关闭的时候,这个cookie就失效了
            response.addCookie(cookie);
            cookie.setMaxAge(60 * 60);
             */
            response.addCookie(cookie);

            HttpSession session = request.getSession();
            session.setAttribute("name",name);
            //重定向到success1.jsp中,从而使得地址栏发生了变化
            response.sendRedirect("/session/success1.jsp");
        }else{
            //设置提示信息,表示用户名或者密码错误
            request.setAttribute("msg","用户名或者密码错误");
            //重新跳转到login.jsp中
            request.getRequestDispatcher("/session/login.jsp")
                    .forward(request,response);
        }
    }
}

login.jsp、succes1.jsp、success2.jsp:

<!--login.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录界面</title>
</head>
<body>
    <span style="color: red;">
        <b>
            <!--获取错误的提示信息,如果提示信息为空,说明是第一次访问,否则是登录失败-->
            <%=request.getAttribute("msg") == null ? "" : request.getAttribute("msg")%>
        </b>
    </span>
    <%
        String username = "";
        //获取cookie请求头
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for(Cookie cookie : cookies){
                if("username".equals(cookie.getName())){
                    //因为登录用户的值可能是中文,所以需要进行解码
                    username = URLDecoder.decode(cookie.getValue(),"utf-8");
                    break;
                }
            }
        }
    %>
    <form action="/LoginServlet" method="post">
        姓 名: <input type="text" name="name" value="<%=username%>"><br>
        密 码: <input type="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

<!--success1.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功登录的界面1</title>
</head>
<body>
    <%
        /*
        首先从session中获取name这个参数的值,如果为空,说明没有登录,需要
        转发到login.jsp中,否则,如果不为空,那么直接赋值给user
        */
        String user = "";
        String name = (String)session.getAttribute("name");
        if(name == null){
            //如果为空,那么需要将对应的提示信息报存到request域中,然后转发到login页面
            request.setAttribute("msg","没有权限,请先登录");
            request.getRequestDispatcher("/session/login.jsp")
                    .forward(request,response);
            return;//通过这个,那么剩下的所有代码不会执行了,
        }else{
            user = name;
        }
    %>
    <h1>成功登录的界面</h1>
    您好,<%=user%>
</body>
</html>
<!--success2.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功登录之后的界面2</title>
</head>
<body>
    <%
        /*
        同样的,如果没有登录,就来访问这个页面,需要重新跳转到login.jsp页面
        但是因为需要利用request域来保存提示信息,如果利用的是重定向的话,那么
        没有办法看到提示信息,所以需要利用的是请求转发
        */
        String user = "";
        String name = (String)session.getAttribute("name");
        if(name == null){
            //如果name的值为空,说明还没有登录,需要转发到login页面
            request.setAttribute("msg","没有权限,请先登录");
            request.getRequestDispatcher("/session/login.jsp")
                    .forward(request,response);
            return;
        }else{
            user = name;
        }

    %>
    <h1>成功登录后的界面2</h1>
    您好,<%=user%>
</body>
</html>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值