JavaWeb——【JSP】——一篇文章带你入门JSP,值得你一看!

JSP


1.概述

在动态网页开发中,经常需要动态生成HTML内容,例如,一篇新闻报道的测览次数需要动态生成。这时,如果使用 Servlet 来实现 HTML 页面数据的改变,需要调用大量的输出语句,从而使静态内容和动态内容混合在一起,导致程序非常臃肿。为了克服 Servlet 的这些缺点,Oracle(Sun)公司推出了JSP技术。

1.1.什么是JSP

JSP全名是 Java Server Page,它是建立在 Servlet 规范之上的动态网页开发技术。
在JSP文件中,HTML代码与Java代码共同存在,其中,HTML代码用来实现网页中静态内容的显示,Java代码用来实现网页中动态内容的显示。为了与普通HTML有所区别JSP文件的扩展名为.jsp

2.JSP快速了解

2.1.Servlet 输出 HTML

public class HtmlServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<h1>Hello World</h1>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Hello World!</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

2.2.创建JSP界面

创建新的项目,然后再项目的WebContent目录下新建simple.jsp文件,如下
eclipse 提供了新建jsp界面的功能,在WebContent目录右键,New-JSP File
在这里插入图片描述
新建好界面后,在 节点里面添加如下代码:
在这里插入图片描述
访问jsp界面,其中输出了时间信息,其中每次查看时间都不同,会显示当前时间,这是因为simple.jsp是一个动态网页,它的效果实际上是有服务器程序实现的。
在这里插入图片描述

2.3.分析JSP所生成的Servlet代码

当用户第一次访问JSP页面时,该页面都会被 JspServlet 翻译成一个 Servlet 源文件,然后将源文件编译为 .class 文件。 Servlet 源文件和 .class 文件都放在硬盘\Workspace\eclipse.metadata.plugins\org.eclipse.wst.server.core\tmp1\work\Catalina\localhost\Things\org\apache\jsp
每个人的可能在有点稍许不同,有的work目录是在tmp2,也可能有多个tmp0和tmp1,所以这个可以根据个人情况查找。
在这里插入图片描述
idea的web项目不是直接将webapp放在tomcat容器中。而是将生成的webapp与tomcat按照idea的“技术”形成连接
具体路径为:注意需要给项目设置项目名开头的访问路径
C:\Users\登录名.IntelliJIdea2017.2\system\tomcat\Tomcat-pure_工程名\work\Catalina\localhost\appcontext名称\org\apache\jsp

3.JSP基本语法(掌握)

JSP界面可以按照编写 HTML 的方式来编写其中可以包含 HTML 文件的所有静态内容,在静态的HTML内容之中可以嵌套JSP的其它各种元素来产生动态内容和执行业务逻辑,JSP页面中的静态HTML内容被称为JSP模板元素,JSP模板元素定义了网页的基本骨架,即定义了页面的结构和外观。

3.1.JSP表达式

JSP表达式用于将程序数据输出到客户端
语法
<%= %>
将=号后面的变量或者表达式计算结果转成一个字符串,然后插入JSP页面输出结果的相应位置处,如刚刚编写的代码
<%=new Date().toLocaleString() %>

3.2.JSP脚本片段

JSP脚本片段是值嵌套在<% 和 %>之中的一条或者多条Java程序代码,这些Java程序代码必须严格遵守Java语法规范,否则编译会报错。

简单的脚本片段

<%
	int x = 10;
	out.print(x);
%>

分开写,单个脚本中的语句可以是不完整的,但是多个脚本片段组合后的结果必须是完整的Java语句

<%
	int y = 20;
%>
<%
	out.print(y);
%>

3.3.JSP声明

JSP脚本片段编写的代码都被放到了一个叫_jspService()的方法里面,变量成为了局部变量,
有时候我们希望定义的变量是成员变量,这时就可以使用JSP声明。

JSP声明中定义的都是成员方法、成员变量、静态方法、静态属性、静态代码块

语法
<%!
	java代码
%>

在这里插入图片描述

3.4.JSP注释

<%--这是注释内容--%>
需要注意的是:JSP页面中格式为<%-- 注释信息 --%> 内容不会发布到客户端

4.JSP指令(了解)

为了设置JSP页面中的一些信息,Sum公司提供了JSP指令
page、include、taglib三种指令

4.1.page指令

在JSP页面中,经常需要对页面的某些特性进行描述,例如,页面的编码方式,JSP页面采用的语言等,这时,可以通过page指令来实现

常用属性

格式:
<%@ page 属性名1= “属性值1” 属性名2= “属性值2” …%>

常用属性如下:

  • language:jsp脚本中可以嵌入的语言种类
  • pageEncoding:当前jsp文件的本身编码
  • contentType:response.setContentType(text/html;charset=UTF-8)
  • import:指定JSP页面翻译成Servlet资源文件中导入的包或者类
  • session:是否jsp在翻译时自动创建session
  • errorPage:当当前页面出错后跳转到哪个页面
  • isErrorPage:当前页面是一个处理错误的页面

4.2.include指令

有时候,需要在JSP页面静态包含一个文件,例如HTML文件、文本文件等,这时,可以通过 include指令来实现

语法
<%@ include file="被包含的文件地址"%>

5.JSP隐式对象(掌握)

在JSP页面中,有一些对象需要频繁使用,如果每次创建这些对象则会非常麻烦,为此,JSP提供了9个隐式对象,它们是JSP默认创建的,可以直接在JSP页面使用,例如刚开始演示的out对象

名称 类型 描述
out javax.servlet.jsp.JspWriter 用于页面输出
Request javax.servlet.http.HttpServletRequest 得到用户请求信息,
Response javax.servlet.http.HttpServletResponse 服务器向客户端的回应信息
Config javax.servlet.ServletConfig 服务器配置,可以取得初始化参数
Session javax.servlet.http.HttpSession 用来保存用户的信息
Application javax.servlet.ServletContext 所有用户的共享信息
Page java.lang.Object 指当前页面转换后的Servlet类的实例
pageContext javax.servlet.jsp.PageContext JSP的页面容器
Exception java.lang.Throwable 表示JSP页面所发生的异常,在错误页中才起作用

5.1.1.out对象

在JSP页面中,经常需要向客户端发送文本内容,这时,可以使用out对象来实现

使用示例

<%
	out.print(new java.util.Date().toLocaleString());
	response.getWriter().println("使用response对象输出");
%>

5.1.2.pageContext对象

5.1.2.1.pageContext获取隐式对象

在JSP中,想要获取JSP隐式对象,可以使用pageContext对象,pageContext对象时Javax.servlet.jsp.PageContext类的实例对象,它代表当前JSP页面的运行环境,并提供了一些列用于获取其他隐式对象的方法。

方法 功能
JspWriter getOut() 获取out隐式对象
Object getPage() 获取page隐式对象
ServletRequest getRequest() 获取request隐式对象
ServletResponse getResponse( ) 获取response隐式对象
HttpSession getSession( ) 获取session隐式对象
ServletConfig getServletConfig( ) 获取config
ServletContext getServletContext( ) 获取application隐式对象
Exception getException() 获取exception隐式对象

示例,使用pageContext获取request对象

<%
	HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();
	String ip = request.getRemoteAddr();
	out.print(ip);
%>
5.1.2.2.pageContext操作属性
方法名 功能
void setAttribute(String name, Object value, int scope) 设置pageContext对象的属性
Object getAttribute(String name, int scope) 获取pageContext对象的属性
void removeAttribute(String name,int scope) 删除指定范围内名称为name的属性
void removeAttribute(String name) 删除所有范围内名称为name的属性
Object findAttribute(String name) 从4个域对象中查找名称为name的属性

pageContext对象的作用范围有4个值

  • pageContext.PAGE_SCOPE:表示页面范围
  • pageContext.REQUEST_SCOPE:表示请求范围
  • pageContext.SESSION_SCOPE:表示会话范围
  • pageContext.APPLICATION_SCOPE:表示Web应用程序范围

使用findAttribute()方法来查找属性是,会依次从page、request、session、application的顺序进行查找,找到立刻返回实际的值,找不到返回null。

示例

<%
	pageContext.setAttribute("company", "jf", pageContext.PAGE_SCOPE);
	Object name = pageContext.getAttribute("company", pageContext.PAGE_SCOPE);
	out.print("公司名称为:" + name);
%>

5.1.3.JSP四个域范围

PageContext常量名 描述 作用域名称 域对象类型
PageScope 当前页面中有效 pageContext PageContext
RequestScope 一次请求范围 Request HttpServletRequest
Sessionscope 一次会话范围 Session HttpSession
Applicationscope 应用范围 Application ServletContext
  • page:表示当前页,通常没用。jsp标签底层使用
  • request:表示一次请求。通常一次请求就一个页面,但如果使用请求转发,可以涉及多个页面。
  • session:表示一次会话。可以在多次请求之间共享数据
  • application:表示一个web应用(项目)。可以整个web项目共享,多次会话共享数据

6.JSP标签(了解)

JSP标签元素用来控制JSP的行为,执行一些常用的JSP页面动作。通过标签元素可以实现使用多行Java代码能够实现的效果,如包含页面文件,实现请求转发等

6.1.jsp:include标签

在JSP页面中,为了把其他资源的输出内容插入到当前JSP页面的输出内容中,JSP技术提供了jsp:include标签
语法:
<jsp:include page="relativeURL" flush=”true|false”>
page属性用于指定被引入资源的相对路径, flush属性用于指定是否将当前页面的输出内容刷新到客户端,默认情况下,fush属性的值为 false

使用示例
在项目下新建两个jsp,分别是included.jsp和dynamicInclude.jsp,其中dynamicInclude.jsp引入了included.jsp

included.jsp

<body>
	<% Thread.sleep(5000);%>
	included.jsp 中的内容;
</body>

dynamicInclude.jsp

<body>
	dynamicInclude.jsp 中的内容
	<jsp:include page="included.jsp" flush="true" />
</body>

启动 Tomcat服务器,访问地址,发现浏览器首先会显示 dynamicInclude jsp页面中的输出内容,等待5秒后,才会显示 included jsp页面的输出内容。说明被引用的资源 included jsp在当前JSP页面输出内容后才被调用,显示结果如下
在这里插入图片描述

注意:虽然include指令和jsp:include标签都能够包含一个文件,但是它们4之间有很大的区别:
< jsp:include>标签中要引入的资源和当前 JSP 页面是两个彼此独立的执行实体,即被动态引入的资源必须能够被Web容器独立执行。而 include 指令只能引入遵循JSP格式的文件,被引入文件与当前JSP文件需要共同合并才能翻译成一个 Servlet 源文件
<jsp:include>标签中引入的资源是在运行时才包含的,而且只包含运行结果。而 include指令引入的资源是在编译时期包含的,包含的是源代码
<jsp:include>标签运行原理与 RequestDispatcher.include()方法类似,即被包含的页面不能改变响应状态码或者设置响应头,而 include指令没有这方面的限制。

6.2.jsp:forward标签

在JSP页面中,经常需要将请求转发给另外一个资源,这时,除了 RequestDispatcher 接口的 forward() 方法可以实现外,还可以通过<jsp:forward>标签来实现,<jsp:forward>标签的具体语法格式如下所示:
<jsp:forward page="relativeURL" />
page属性用于指定请求转发到的资源的相对路径,该路径是相对于当前的JSP页面的URL

jspforward.jsp

<body>
	<jsp:forward page="welcome.jsp" />
</body>

welcome.jsp

<body>
	你好欢迎访问,当前的时间是
	<% out.print(new java.util.Date()); %>>
</body>

显示结果
在这里插入图片描述

7.案例

7.1.显示列表

添加ListServlet,使用循环生成列表需要的数据,并添加到集合中

public class ListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ArrayList<Message> messages = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Message m = new Message();
            m.setId(i);
            m.setTitle("标题" + i);
            m.setContent("内容" + i);
            messages.add(m);
        }
        req.setAttribute("messages",messages);
        req.getRequestDispatcher("/list.jsp").forward(req,resp);
    }
}

添加list.jsp,获取到request域中的数据,使用循环进行显示

<table border="1" width="600px" align="center">
    <%
        ArrayList<Message> messages = (ArrayList<Message>) request.getAttribute("messages");
        if (messages != null) {
            for (int i = 0; i < messages.size(); i++) {
    %>
        <tr>
            <td align="center"><%=messages.get(i).getTitle() %></td>
            <td align="center"><%=messages.get(i).getContent()%></td>
        </tr>
    <%
            }
        }
    %>
</table>

7.2.图片验证码

使用jsp完成图片验证码的功能

<%@page import="javax.imageio.ImageIO"%>
<%@page import="java.awt.Font"%>
<%@page import="java.awt.Graphics"%>
<%@page import="java.awt.image.BufferedImage"%>
<%@page import="java.util.Random"%>
<%@page import="java.awt.Color"%>
<%@ page language="java" contentType="image/JPEG; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%!
    //获取随机颜色  
    Color getRandColor(int fc,int bc){
        Random random = new Random();
        if(fc>255) fc=255;
        if(bc>255) bc=255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r,g,b);
    }
%>
<%
    //设置页面不缓存
    response.setHeader("Pragma", "No-cache");
    response.setHeader("Cache-Control", "no-cache");
    response.setDateHeader("Expires", 0);
    //在内存中创建图像
    int width = 60;
    int height = 20;
    BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
    //获取图形上下文
    Graphics g = image.getGraphics();
    //随机类
    Random random = new Random();
    //设定背景
    g.setColor(getRandColor(200, 250));
    g.fillRect(0, 0, width, height);
    //设定字体
    g.setFont(new Font("Times New Roman",Font.PLAIN,18));
    //随机产生干扰线
    g.setColor(getRandColor(160, 200));
    for (int i = 0; i < 100; i++) {
        int x = random.nextInt(width);
        int y = random.nextInt(height);
        int xl = random.nextInt(12);
        int yl = random.nextInt(12);
        g.drawLine(x, y, x + xl, y + yl);
    }
    //随机产生4位验证码
    String[] codes = {"2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","J","K","L","M","N","P","Q","R","S","T","U","V","W","X","Y","Z"};
    String code = "";
    for(int i=0;i<4;i++){
        String str = codes[random.nextInt(codes.length)];
        code += str;
        // 将认证码显示到图象中
        g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
        //调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
        g.drawString(str, 13 * i + 6, 16);
    }
    // 将认证码存入SESSION
    session.setAttribute("code", code);
    // 图象生效
    g.dispose();
    // 输出图象到页面
    ImageIO.write(image, "JPEG", response.getOutputStream());
    //加上下面代码,运行时才不会出现java.lang.IllegalStateException: getOutputStream() has already been called ..........等异常
    response.getOutputStream().flush();
    response.getOutputStream().close();
    response.flushBuffer();
    out.clear();
    out = pageContext.pushBody();
%>
发布了230 篇原创文章 · 获赞 250 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/weixin_42247720/article/details/103822579