JSP入门

一 概述

JSP是HTML + JS + CSS + JAVA的混合产物,负责与用户进行交互,将最终的界面呈现给用户。本质上是一个Servlet,因为Web容器(Tomcat)在使用时,将其转换Servlet进行使用。

1.1 原理

(1)Web容器(服务器)接收到JSP请求时,会将该请求交给JSP引擎处理,每一个JSP页面第一次被访问时,JSP引擎会将其翻译翻译为一个Servlet(包含_jspInit()、_jspDestory()、_jspServlet()等方法,所以说JSP本质上是一个Servlet),Web容器再调用转换后的Servlet完成业务操作。
在这里插入图片描述

(2)在Servlet中将 html + js + css 部分用out.wirte()进行输出,浏览器本身就是html运行环境,会将其解析成页面展示。
在这里插入图片描述

1.2 嵌入Java

1.2.1 嵌入脚本

<% Java脚本 %>,在<% %>中写Java代码执行逻辑。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>My JSP starting page</title>
</head>

<body>
    <%
        String str = "Hello JSP";
        System.out.println(str);
    %>
</body>
</html>

1.2.2 嵌入方法

<%! Java方法 %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>My JSP starting page</title>
</head>

<body>
    <%!
        public void say() {
            System.out.println("Hello JSP");
        }
    %>
</body>
</html>

1.2.3 嵌入表达式

<%= Java对象/变量 %>,这里的Java对象和变量会在前端页面输出。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>My JSP starting page</title>
</head>

<body>
    <% String str = "Hello JSP"; %>
    <%= str %>
</body>
</html>

在这里插入图片描述
三者结合:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>My JSP starting page</title>
</head>

<body>
    <!-- 嵌入方法 -->
    <%!
        public String say() {
            System.out.println("在控制台说:Hello JSP");

            return "Hello JSP";
        }
    %>

    <%-- 嵌入脚本 --%>
    <% String str = say(); %>

    <p>
        <%-- 嵌入对象/变量 --%>
        在网页说:<%= str %>
    </p>
</body>
</html>

在这里插入图片描述

在这里插入图片描述

上述JSP内容实际等价于在Servlet中写:

public String say() {
        System.out.println("在控制台说:Hello JSP");

        return "Hello JSP";
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        String str = say();

        servletResponse.getWriter().write("<p>");
        servletResponse.getWriter().write("在网页说:" + str);
        servletResponse.getWriter().write("</p>");
    }

二 九大内置对象

JSP转成Serlvet,提前生成好的九个对象,在JSP中可以直接使用。
(1)request: 请求对象 HttpServletRequest;
(2)response: 响应对象 HttpServletResponse;
(3)session: 一次会话 HttpSession;
(4)page: 当前JSP对应的Servlet对象,相当于this, Servlet;
(5)pageContext: 页面上下文,获取页面信息 PageContext;
(6)config: 当前JSP页面对应的Servlet对象信息 ServletConfig;
(7)application: 表示当前Web应用,全局对象,保存所有用户共享信息 ServletContext;
(8)out: 向浏览器输出信息 JspWriter;
(9)exception: 表示当前JSP页面法神的异常 Exception。

在此选取若干常用内置对象进行阐述:

2.1 request

常用方法:
(1)String getParameter(String key):根据参数名从客户端(浏览器)接收参数值;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)String[] getParameterValues(String key):获取客户端传来的多个同名参数的值,存入数组;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)void setAttribute(String key, Object value):用键值对形式保存数据;

(4)String getAttribute(String key):使用通过key值取出存入的value值。Serlvet之间传递参数时使用,注意与getParameter()区分。
在这里插入图片描述
在这里插入图片描述
(5)RequestDispatcher getRequestDispatcher(String path):返回一个RequestDispatcher对象,通过该对象的forward方法进行请求转发。
在这里插入图片描述
(6)void setCharacterEncoding(String charset):指定请求的编码。
在这里插入图片描述

2.1 response

常用方法:
(1)sendRedirect(String path):重定向,页面之间的跳转。

getRequestDispatcher()请求转发 与 sendRedirect()重定向的区别:

请求转发:将同一个请求传给下一个页面,同一个请求在服务器中传递,地址栏不变,也叫服务器跳转,

重定向:重新创建一个新的请求传给下一个页面,之前的请求接收生命周期,客户端发送一次新的请求访问目标资源,地址改变,也叫客户端跳转。

综上所述可以知道,开发过程中如果两个页面间需要用到request传值,则必须使用请求转发,因为重定向会接收原来的请求(request)的生命周期,无法保存需要传递的数据。

2.3 session

属于统一会话的请求有一个统一的标识,sessionID

session常用方法:
(1)String getId():获取sessionID;

(2)void setAttribute(String key, Object value):向session以键值对形式存放数据;

(3)void getAttribute(String key):通过key值从session中获取参数;

(4)void setMaxInactiveInterval(int i):设置session自动失效时间,单位秒。若不设置,默认1800秒;

(5)int getMaxInactiveInterval():获取session自动失效时间。

(6)void invalidate():手动使session失效。

三 作用域

pageContext,request,Session,application都有setAttribute()和getAttribute(),可以保存和读取数据,所有讨论作用域范围才有意义。

从小到大排列:
pageContext <= request <= Session <= application

(1)page作用域:注意描述的是PageContext对象,不是page对象!!!,范围在当前JSP页面内;

(2)request作用域:范围在一次请求内;

(3)session作用域:范围在一次会话内;

(4)application作用域:范围在一次Web应用内;

四 EL表达式

简化JSP中对数据操作的代码写法,只能在JSP中使用,${ 变量名 } 的写法非常简洁方便。

不使用EL表达式,获取数据的写法如下:

<%
	request.setAttribute("name", "张三");
%>
<%= request.getAttribute("name") %>

使用EL表达式后:

${name}

通过上面的例子,可以看出EL表达式本质上就是简化了getAttribute()的使用。但也因此有一个前提,必须先有setAttribute()存放数据,才能取出数据。

4.1 访问优先级

EL表达式访问变量,是在域(pageContext 、request、session、application)对象中访问,当不同域中存在同名对象时,访问优先级为:

pageContext ==> request ==> session ==> application。

当然,可以指定访问某个域中的对象,写法:
访问page 域:${ pageScope.name },名字虽然是page,但与page内置对象无关。
访问request域:${ requestScope.name }
访问session域:${ sessionScope.name }
访问application域:${ applicationScope.name }

4.2 操作对象

假设存在User类,域中存在User的对象user{id=1,name=“张三”}

public class User {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
<%
	User user = new User();
	user.setId(1);
	user.setName("张三");

	application.setAttribute("user", user);
%>

4.2.1 获取对象属性:

${ user.id }
${ user.name } 

等价于:

<%= application.getAttribute("user").getId() %>
<%= application.getAttribute("user").getName() %>

4.2.2 设置对象属性

${ user.id=2 }
${ user.name="李四" } 

等价于:

<% 
	user.setId(2);
	application.setAttribute("user", user);
%>
<%= application.getAttribute("user").getId() %>

<% 
	user.setName("李四");
	application.setAttribute("user", user);
%>
<%= application.getAttribute("user").getName() %>

注:EL表达式中是通过反射机制获取类中的getXxx()和setXxx(Xxx xxx)方法进行调用,是与方法绑定,而不是与属性绑定。

4.2.3 执行表达式

&& || ! != > < >= <= ==

(1)&& and
(2)|| or
(3)! not
(4)!= ne
(5)== eq
(6)< lt
(7)> gt
(8)<= le
(9)>= ge
(10)empty 变量为null,长度为0的String,size为0的集合

五 JSTL

JSTL 是JSP Standard Tag Library 的缩写,翻译过来叫JSP标准标签库。与EL表达式一样是用来简化JSP中代码的。不过El侧重于数据展示,JSTL侧重于逻辑处理。

例如A页面request中存放一个集合,B页面通过拼接for循展示数据,C页面使用jstl标签展示数据。

<%
		// A页面
        User user1 = new User(1, "张三", new Cat("波斯猫"));
        User user2 = new User(2, "李四", new Cat("埃及猫"));
        User user3 = new User(3, "王五", new Cat("大橘猫"));

        List<User> list = new ArrayList<>();

        list.add(user1);
        list.add(user2);
        list.add(user3);


        request.setAttribute("list", list);
    %>
<%
	// B页面
	List<User> userList = (List<User>) request.getAttribute("list");
	for (User user:userList) {
        request.setAttribute("user", user);
%>
	${user.id}
    ${user.name}
    ${user.cat.type}
<%
	}
%>
<%-- C页面 --%> 
<c:forEach items="${list}" var="user">
        ${user.id}
        ${user.name}
        ${user.cat.type}
</c:forEach>

光从代码行数上来看,使用jstl都会简便很多,并且结构更加清晰统一,降低了拼接可能导致的错误。

5.1 前置准备

(1)使用时需要导入jstl.jar和standard.jar两个包,通过官网http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/下载。

在这里插入图片描述
(2)在项目工程web/WEB-INF下创建lib目录,将两个jar包复制进去。
在这里插入图片描述

(3)在工程里引用两个jar包.
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
(4)在JSP页面导入标签库,便可以使用了。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

5.2 常用标签

set、out、remove、catch

5.2.1 set

可以向域中添加数据,若不指定存放的域,默认存放在page域中。

<%-- var和value设置键值对 scope指定存放的作用域范围 --%>
<c:set var="name" value="关雁玲" scope="application"></c:set>

可以修改对象的数据

<%-- target指定对象,property指定属性,value指定修改值 --%>
    <c:set target="${user}" property="name" value="赵国庆"></c:set>

5.2.2 out

输出域对象:

<%-- value指定key值,default指定域中没有key值对应数据时输出的内容 --%>
    <c:out value="${Exgirl}" default="关雁玲"></c:out>

5.2.3 remove
根据key值删除域对象:

<%-- var指定根据哪个key值删除域对象,scope指定删除哪个域中的对象 --%>
<c:remove var="name" scope="application"></c:remove>

5.2.4 catch

捕获异常,var指定异常的信息:

<c:catch var="error">
        <%
            int i = 10/0;
        %>
</c:catch>
 
${error}

5.2.5 if 和 choose

判断分支:

<c:set var="num1" value="1"></c:set>
<c:set var="num2" value="2"></c:set>

<%-- test判断条件 --%>
<c:if test="${num1>num2}">num1大</c:if>
<c:if test="${num1<num2}">num2大</c:if>

<%-- test判断条件,该结构类似switch case --%>
<c:choose>
	<c:when test="${num1>num2}">num1大</c:when>
    <c:when test="${num1<num2}">num2大</c:when>
    <c:otherwise>一样大</c:otherwise>
</c:choose>

5.2.6 forEach

进行集合元素的迭代:

<%
	List list1 = new ArrayList();
    list1.add(1);
    list1.add(2);
    list1.add(3);
    list1.add(4);
    list1.add(5);
    list1.add(6);
    list1.add(7);
    list1.add(8);

    request.setAttribute("list", list1);
%>
<%-- items迭代的集合,var每个元素的临时key值,begin开始下标,end结束下标 step迭代步长 varStatus迭代信息(开始下标,结束下标,当前下标等) --%>
<c:forEach items="${list1}" var="num" begin="0" end="7" step="2" varStatus>
	${sta.index}
	${num}
</c:forEach>

5.3 其它标签库

5.3.1 fmt标签库

格式标签库fmt,使用时导入:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

格式化日期标签formatDate、格式化数值标签formatNumber

<%
	Date date = new Date();
	request.setAttribute("date", date);

	float num5 = 123.456f;
	request.setAttribute("num5", num5);
%>

<%-- value格式化的日期,patter格式 --%>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate>

<%-- var格式化的数值,maxIntegerDigits整数位数,maxFractionDigits小数位数 --%>
<fmt:formatNumber var="${num5}" maxIntegerDigits="2" maxFractionDigits="2">

5.3.2 function标签库

提供各种函数,使用时导入:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%
	request.setAttribute("info", "Java,C");
%>
<%-- 内容是否存在 --%>
${fn:contains(info, "Python")}
<%-- 是否以某内容开头 --%>
${fn:startsWith(info, "Java")}
<%-- 是否以某内容结尾 --%>
${fn:endsWith(info, "C")}
<%-- 某内容开始下标 --%>
${fn:indexOf(info, "va")}
<%-- 替换内容 --%>
${fn:replace(info, "C", "Python")}
<%-- 截取 --%>
${fn:substring(info, 2, 3)}
<%-- 分隔 --%>
${fn:split(info, ",")[0]}-${fn:split(info, ",")[1]}

六 文件上传/下载

6.1 文件上传

前提条件:
(1)input标签type为file;
(2)form表单的enctype为multipart/form-data,以二进制形式传输数据;
(3)form表单的method为post,get请求会将文件名传给服务器,而不是文件本身。

过程图解:
在这里插入图片描述

6.1.1 JSP写法

<%-- enctype传输类型:二进制 --%>
<form enctype="multipart/form-data" action="/upload" method="post">
		<%-- type输入的类型:文件 --%>
        <input type="file" name="file">
        <input type="submit">
</form>

6.1.2 Servlet写法

@WebServlet("/upload")
public class Upload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 接收客户端传来的文件的字节流
        InputStream inputStream = req.getInputStream();
        // 转成字符输入流
        Reader reader = new InputStreamReader(inputStream,"UTF-8");
        // 再转成字符输入缓冲流,读的快,其实可以宏观看成输入流
        BufferedReader bufferedReader = new BufferedReader(reader);

        // 获取文件绝对路径
        String path = req.getServletContext().getRealPath("file/test.txt");

        // 建立输出流,并字节输出流=》字符输出流=》字符输出缓冲流
        OutputStream outputStream = new FileOutputStream(path);
        Writer writer = new OutputStreamWriter(outputStream);
        BufferedWriter bufferedWriter = new BufferedWriter(writer);

        // 临时接收读取的内容
        String str = "";

        // 向文件中写内容
        while((str = bufferedReader.readLine()) != null) {
            System.out.println(str);
            bufferedWriter.write(str);
        }

        bufferedWriter.flush();
        bufferedWriter.close();
        writer.close();
        outputStream.close();
        bufferedReader.close();
        reader.close();
        inputStream.close();
    }
}

6.1.3 fileupload写法

使用fileupload组件,可以将表单信息封装成对象,以对象形式对文件进行操作,使业务逻辑更清晰,同时自动处理请求传递中无关的信息,保持文件内容的原始性。

使用时需要commos-fileuploadcommos-io两个jar包,下载地址分别为:commos-fileupload下载commons-io下载
在这里插入图片描述
在这里插入图片描述
将两个jar包复制进Web项目中web/WEB-INF/lib目录下。
在这里插入图片描述

将jar包导入工程。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
使用:

@WebServlet("/upload")
public class Upload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
        	// FileItem工厂
            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);

            // 获取请求中的表单内容,将表单元素用FileItem封装,存入List集合
            List<FileItem> list = servletFileUpload.parseRequest(req);

            // 遍历表单元素并处理
            for (FileItem fileItem : list) {

                // fileItem对象是否为普通表单元素(text、password等)
                if(fileItem.isFormField()) {

                    // 获取表单元素的name值
                    String name = fileItem.getFieldName();
                    // 获取表单元素的输入值
                    String value = fileItem.getString();

                } else {    // 不是则为文件,进行上传

                    // 用字节输入流接收文件数据流
                    InputStream inputStream = fileItem.getInputStream();

                    // 获取项目工程的绝对路径,并拼接“保存目录/保存文件名”
                    String path = req.getServletContext().getRealPath("file/" + fileItem.getName());
                    // 设置字节输出流
                    OutputStream outputStream = new FileOutputStream(path);

                    int temp = 0;
                    // 按字节读文件,读完为止。上传文件的内容==>保存的文件内容
                    while((temp = inputStream.read()) != -1) {
                        outputStream.write(temp);
                    }
					
					// 关闭输出、输入流,完成保存
                    outputStream.close();
                    inputStream.close();
                }
            }

        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
}

6.2 文件下载

6.2.1 JSP写法

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <base href="<%=basePath%>">
    <title>My JSP '' starting page</title>
</head>

<body>
    <a href="/download?type=txt">下载文本</a>
    <a href="/download?type=jpg">下载图片</a>
</body>
</html>

6.2.2 Servlet写法

@WebServlet("/download")
public class Download extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String type = req.getParameter("type");
        String fileName = "";

        // 根据不同选择,下载不同文件
        switch(type) {
            case "txt":
                fileName = "test.txt";
                break;
            case "jpg":
                fileName = "背景.jpg";
                break;
        }

        // 设置响应格式,让浏览器知道是下载操作
        resp.setContentType("applicaton/x-mdownload");
        // 设置下载后的文件名
        resp.setHeader("Content-Disposition", "atachment;filename=" + fileName);
        // 设置响应编码
        resp.setContentType("text/html;charset=UTF-8");
        // 建立输出流的连接
        OutputStream outputStream = resp.getOutputStream();

        // 可下载文件的存放位置的绝对路径
        String path = req.getServletContext().getRealPath("file/" + fileName);
        // 获取下载文件的内容
        InputStream inputStream = new FileInputStream(path);

        int temp = 0;
        // 向输出流中写下载文件的内容
        while((temp = inputStream.read()) != -1) {
            outputStream.write(temp);
        }

        // 关闭输入、输出流,下载完成
        inputStream.close();
        outputStream.close();
    }
}
@WebServlet("/download")
public class Download extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String filename = req.getParameter("filename");
        File tempfile = new File(filename);
        String realname = tempfile.getName();

        // 设置响应格式,让浏览器知道是下载操作
        resp.setContentType("applicaton/x-mdownload");
        // 设置下载后的文件名
//        resp.setHeader("Content-Disposition", "atachment;filename=" + realname);
		// 中文下载文件名乱码或呈_时使用
        resp.setHeader("Content-disposition", "attachment; filename=" + new String(realname.getBytes("utf-8"),"ISO8859-1"));

        // 设置响应编码
        resp.setContentType("text/html;charcet=UTF-8");

        // 建立输出流的连接
        OutputStream outputStream = resp.getOutputStream();

        // 可下载文件的存放位置的绝对路径
        String path = "D://upFiles/" + filename;
        // 获取下载文件的内容
        InputStream inputStream = new FileInputStream(path);

        int temp = 0;
        // 向输出流中写下载文件的内容
        while((temp = inputStream.read()) != -1) {
            outputStream.write(temp);
        }

        // 关闭输入、输出流,下载完成
        inputStream.close();
        outputStream.close();
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值