EL表达式&JSTL标签&文件上传下载学习笔记

EL表达式&JSTL标签&文件上传下载

一、EL表达式

1.1EL表达式概述

  • EL 表达式的全称是:Expression Language.是表达式语言。
  • EL表达式的作用:EL表达式主要是代替jsp页面中的表达式脚本在jsp页面中进行数据的输出
  • 因为EL表达式在输出数据的时候,要比jsp的表达式脚本要简洁很多。
  <% request.setAttribute("KEY","值");%>
<!--  表达式脚本输出key的值是:-->
  <%=request.getAttribute("KEY")==null?"":request.getAttribute("KEY")%><br>
  ${s1}<br>
  ${KEY}<br>
  • EL表达式的格式是:${表达式}
  • EL表达式在输出null值的时候,输出的是空串。jsp表达式脚本输出null值的时候,输出的是null字符串。

1.2 EL表达式搜索域数据的顺序

  • EL 表达式主要是在jsp页面输出数据。

  • 主要是输出域对象中的数据。

  • 当四个域中都有相同的key的数据的时候,EL表达式会按照四个域的从小到大的顺序去进行搜索,找的就输出。

 <%
//  request.setAttribute("key","request");2
//  session.setAttribute("key"," session");3
//  application.setAttribute("key","application");4
//  pageContext.setAttribute("key","pageContext");1
  %>
  ${key}

1.3 EL表达式输出Bean的普通属性,数组属性。List集合属性,map集合属性

  • 输出Person类中普通属性,数组属性。List集合属性和map集合属性。

Person类

package Bean;

import java.util.List;
import java.util.Map;

public class Person {
  private String name;
  private String[] phones;
  private List<String> cities;

  public String getName() {
    return name;
  }

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

  public String[] getPhones() {
    return phones;
  }

  public void setPhones(String[] phones) {
    this.phones = phones;
  }

  public List<String> getCities() {
    return cities;
  }

  public void setCities(List<String> cities) {
    this.cities = cities;
  }

  public Map<String, Object> getMap() {
    return map;
  }

  public void setMap(Map<String, Object> map) {
    this.map = map;
  }

  private Map<String,Object>map;
  public  int getAge(){
    return 18;
  }
}

输出的代码

 <%
    Person person = new Person();
    person.setName("王超666");
    person.setPhones(new String[]{"12345647896","1254478965","15344599282"});

    ArrayList<String> cities = new ArrayList<>();
    cities.add("北京");
    cities.add("上海");
    cities.add("深圳");
    person.setCities(cities);


    HashMap<String, Object>map = new HashMap<>();
    map.put("key1","value1");
    map.put("key2","value2");
    map.put("key3","value3");
    map.put("key4","value4");
    person.setMap(map);
    pageContext.setAttribute("p",person);

  %>
  输出Person:${p}<br>
  输出Person的name属性:${p.name}<br>
  输出Person的phones数组的属性值:${p.phones[1]}<br>
  输出Person的phones数组的属性值:${p.phones}<br>
  输出Person的cities数组的元素值:${p.cities}<br>
  输出PersonMap集合:${p.map};<br/>
  输出PersonMap集合中某个key的值:${p.map.key3}<br>
  输出Person的age属性:${p.age};<br/>

1.4 EL 表达式运算

语法:${运算表达式},EL表达式支持如下运算符:

关系运算
关系运算符说明示例结果
==或eq等于 5 = = 5 或 {5==5}或 5==5{5 eq 5}true
!=或ne不等于 5 ! = 5 或 {5!=5}或 5=5{5 ne 5 }false
<或lt小于 3 < 5 或者 {3<5}或者 3<5或者{3 lt 5}true
>或gt大于 2 > 10 或 {2>10}或 2>10{2 gt 10}false
<=或le小于等于 5 < = 12 或 {5<=12}或 5<=12{5 le 12}true
>=或ge大于等于 3 > = 5 或 {3>=5}或 3>=5{3 ge 5}false
逻辑运算符
逻辑运算符说明示例结果
&&或and与运算KaTeX parse error: Expected '}', got '&' at position 8: {12==12&̲&12<11}或{1 2= =12and 12<11}false
||或or或运算${12==12||12<11} 或 ${ 12 = =or 12 < 11}true
!或not取反运算 ! t r u e 或 {!true}或 true{not true}false
empty运算(常用)

empty运算可以判断一个数据是否为空,如果为空,则输出true,不为空输出false。

  • 以下几种情况为空:
    • 1、值为null值的时候,为空
    • 2、值为空串的时候,为空
    • 3、值是Object类型数组,长度为零的时候
    • 4、list集合,元素个数为零
    • 5、map集合,元素个数为零
 //1.值为null时,为空
    request.setAttribute("emptyNull",null);
  //2.值为null时,为空
    request.setAttribute("emptyStr","");
  //3.值是Object类型数组,长度为零的时候
    request.setAttribute("emptyArr",new Object[]{});
  //4.list集合,元素个数为零
    ArrayList<String> list = new ArrayList<>();
   list.add("123");
    request.setAttribute("emptyList",list);
  //5.map集合,元素个数为零
    HashMap<String, Object> map = new HashMap<>();
   // map.put("123",2);
    request.setAttribute("emptyMap",map);

  %>
  ${empty emptyNull}<br>
  ${empty emptyStr}<br>
  ${empty emptyArr}<br>
  ${empty emptyList}<br>
  ${empty emptyMap}
<!--
true
true
true
false
true
-->
三元运算
  • 表达式1?表达式2:表达式3
  • 如果表达式1的值为真,返回表达式2的值,如果表达式1的值为假,返回表达式3的值

${12==12?“正确”:''错误"}

“.”运算和[]中括号运算符

.点运算,可以输出Bean对象中某个属性的值。

[]中括号运算,可以输出有序集合中某个元素的值。

并且[]中括号运算,还可以输出map集合中key里含有特殊字符的key的值。

<body>
    <%
    Map<String,Object>map=newHashMap<String,Object>();
    map.put("a.a.a","aaaValue");
    map.put("b+b+b","bbbValue");
    map.put("c-c-c","cccValue");
    request.setAttribute("map",map);
    %>
    
    ${map['a.a.a']}<br>
    ${map["b+b+b"]}<br>
    ${map['c-c-c']}<br>

</body>

1.5 El表达式的11个隐含对象

变量类型作用
pageContextPageContextImpl它可以获取jsp中的九大内置对象
pageScopeMap<String,Object>它可以获取pageContext域中的数据
requestScopeMap<String,Object>它可以获取Request域中的数据
sessionScopeMap<String,Object>它可以获取Session域中的数据
applicationScopeMap<String,Object>它可以获取ServletContext域中的数据
paramMap<String,String>它可以获取请求参数的值
paramValuesMap<String,String[]>它也可以获取请求参数的值,获取多个值的时候使用。
headerMap<String,String>它可以获取请求头的信息
headerValuesMap<String,String[]>它可以获取请求头的信息,它可以获取多个值的情况
cookieMap<String,Cookie>它可以获取当前请求的Cookie信息
initParamMap<String,String>它可以获取在web.xml中配置的< context-param>上下文参
pageContext对象的使用
  • 1.协议:
  • 2.服务器ip:
  • 3.服务器端口:
  • 4.获取工程路径:
  • 5.获取请求方法:
  • 6.获取客户端ip地址:
  • 7.获取会话的id编号:
<%--
    request.getScheme()它可以获取请求的协议
    request.getServerName()获取请求的服务器ip或域名
    request.getServerPort()获取请求的服务器端口号
    getContextPath()获取当前工程路径
    request.getMethod()获取请求的方式(GET或POST)
    request.getRemoteHost()获取客户端的ip地址
    session.getId()获取会话的唯一标识
    --%>
<%
pageContext.setAttribute("req",request);
%>

<%=request.getScheme()%><br>

1.协议:${req.scheme}<br>
2.服务器ip:${pageContext.request.serverName}<br>
3.服务器端口:${pageContext.request.serverPort}<br>
4.获取工程路径:${pageContext.request.contextPath}<br>
5.获取请求方法:${pageContext.request.method}<br>
6.获取客户端ip地址:${pageContext.request.remoteHost}<br>
7.获取会话的id编号:${pageContext.session.id}<br>
EL表达式其他隐含对象的使用
变量类型作用
paramMap<String,String>他可以获取请求参数的值
paramValuesMap<String,String[]>他也可以获取请求参数的值,获取多个值的时候使用
输出请求参数username的值:${param.username}<br>
输出请求参数password的值:${param.password}<br>

输出请求参数username的值:${paramValues.username[0]}<br>
输出请求参数hobby的值:${paramValues.hobby[0]}<br>
输出请求参数hobby的值:${paramValues.hobby[1]}<br>

二、JSTL标签库

1. 概述

​ JSTL标签库全称是指JSPStandardTagLibraryJSP标准标签库。是一个不断完善的开放源代码的JSP标签库。

​ EL表达式主要是为了替换jsp中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个jsp页面变得更佳简洁

在jsp标签库中使用taglib指令引入标签库CORE标签库

< %@taglibprefix="c"uri=“http://java.sun.com/jsp/jstl/core”%>

XML标签库

< %@taglibprefix="x"uri=“http://java.sun.com/jsp/jstl/xml”%>

FMT标签库

< %@taglibprefix="fmt"uri=“http://java.sun.com/jsp/jstl/fmt”%>

SQL标签库

< %@taglibprefix="sql"uri=“http://java.sun.com/jsp/jstl/sql”%>

FUNCTIONS标签库

< %@taglibprefix="fn"uri=“http://java.sun.com/jsp/jstl/functions”%>

1.1JSTL标签库的使用步骤

1、先导入jstl标签库的jar包。

taglibs-standard-impl-1.2.1.jar

taglibs-standard-spec-1.2.1.jar

2、第二步,使用taglib指令引入标签库。< %@taglibprefix="c"uri=“http://java.sun.com/jsp/jstl/core”%>

2.core核心库的使用

2.1 < c:if/>
  • 作用:用来做if判断
<%--<c:if/>if标签用来做if判断。test属性表示判断的条件(使用EL表达式输出)--%>
  <c:if test="${12==12}">
    <h1>正确</h1>
  </c:if>
  <c:if test="${12!=12}">
    <h1>错误</h1>
  </c:if>

2.2< c:choose>< c:when>< c:otherwise>标签
  • 作用:多路判断。跟switch…case…default非常接近
<%-- choose标签开始选择判断
    when标签表示每一种判断情况
    test属性表示当前这种判断情况的值
    otherwise标签表示剩下的情况
    <c:choose><c:when><c:otherwise>标签使用时需要注意的点:
        1、标签里不能使用html注释,要使用jsp注释
        2、when标签的父标签一定要是choose标签
        --%>
<%request.setAttribute("height",120);%>
<c:choose>

  <c:when test="${requestScope.height>190}">
    <h2>小巨人</h2>
  </c:when>
  <c:when test="${requestScope.height>180}">
    <h2>很高</h2>
  </c:when>
  <c:when test="${requestScope.height>170}">
  <h2>还可以</h2>
</c:when>
  <c:otherwise>
  <c:choose>
  <c:when test="${requestScope.height>160}">
  <h3>大于160</h3>
  </c:when>
  <c:when test="${requestScope.height>150}">
  <h3>大于150</h3>
  </c:when>
  <c:when test="${requestScope.height>140}">
  <h3>大于140</h3>
  </c:when>
  <c:otherwise>其他小于140</c:otherwise>
  </c:choose>
  </c:otherwise>
</c:choose>
2.3< c:forEach/>
  • 遍历输出
遍历1到10
<%--begin属性设置开始的索引
end属性设置结束的索引
var属性表示循环的变量(也是当前正在遍历到的数据)
--%>
  <c:forEach begin="1" end="10" var="i">
    <tr>
      <td>第${i}</td><br>
    </tr>
  </c:forEach>
遍历Object数组
<%-- for(Objectitem:arr)
    items表示遍历的数据源(遍历的集合)
    var表示当前遍历到的数据
    --%>
 <%
  request.setAttribute("arr",new String[]{"185655615156","1925645132","17165156651"});
  %>
  <c:forEach items="${requestScope.arr}" var="item">
    ${item}<br>
  </c:forEach>
遍历Map集合
<%
    HashMap<String, Object> map = new HashMap<>();
    map.put("key1","value1");
    map.put("key2","value2");
    map.put("key3","value3");
    map.put("key4","value4");
    request.setAttribute("map",map);
  %>
  <c:forEach items="${requestScope.map}" var="entry">
    <h1 style="color: brown">${entry.key}=${entry.value}</h1>
  </c:forEach>
遍历List集合

Student类:

public class Student {
  private Integer id;
  private String username;
  private String password;
  private Integer age;
  private String phone;


  @Override
  public String toString() {
    return "Student{" +
      "id=" + id +
      ", username='" + username + '\'' +
      ", password='" + password + '\'' +
      ", age=" + age +
      ", phone='" + phone + '\'' +
      '}';
  }

  public Integer getId() {
    return id;
  }

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

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public Integer getAge() {
    return age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  public String getPhone() {
    return phone;
  }

  public void setPhone(String phone) {
    this.phone = phone;
  }

  public Student() {
  }

  public Student(Integer id, String username, String password, Integer age, String phone) {
    this.id = id;
    this.username = username;
    this.password = password;
    this.age = age;
    this.phone = phone;
  }
}

代码

<!--  遍历学生List集合-->
  <%
    ArrayList<Student> studentList = new ArrayList<>();
    for (int i = 1; i <10 ; i++) {
      studentList.add(new Student(i,"username"+i,"pass"+i,18+i,"phone"+i));
    }
    request.setAttribute("stus",studentList);
  %>
  <table>
    <tr>
      <th>编号</th>
      <th>用户名</th>
      <th>密码</th>
      <th>年龄</th>
      <th>电话</th>
      <th>操作</th>
    </tr>

    <%--
    items表示遍历的集合
    var表示遍历到的数据
    begin表示遍历的开始索引值
    end表示结束的索引值
    step属性表示遍历的步长值
    varStatus属性表示当前遍历到的数据的状态
    for(inti=1;i<10;i+=2--%>
    <c:forEach begin="2" end="9" step="1" varStatus="status" items="${requestScope.stus}" var="stu">
      <tr>
        <td>${stu.id}</td>
        <td>${stu.username}</td>
        <td>${stu.password}</td>
        <td>${stu.age}</td>
        <td>${stu.phone}</td>
        <td>${status.step}</td>
      </tr>
    </c:forEach>
  </table>

三、文件的上传和下载

3.1文件上传

  • 文件上传:将客户端的文件 保存到服务器端

  • 1、要有一个form标签,method=post请求

  • 2、form标签的encType属性值必须为multipart/form-data值

    • application/x-www-form-urlencoded:数据进行URL编码 格式:键=值&键=值
    • text/plain:纯文本发送
    • multipart/form-data:可以发送二进制数据,专门用于文件上传;表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
  • 3、在form标签中使用inputtype=file添加上传的文件

  • 4、编写服务器代码(Servlet程序)接收,处理上传的数据。

对Servlet限制:
1.request.getParameter()方法不能使用了。即使用了也获取的是null
2.使用request.getInputStream()来获取所有消息体数据。然后解析

解析消息体数据:

  • 使用 commons-fileupload 组件解析消息体
步骤:
	1.导入jar包。注意:还需要导入 commons-io.jar
	2.创建解析器工厂
	3.获取解析器
	4.解析request对象,返回 List<FileItem>	(表单项对象集合)
	5.遍历集合,获取每一个表单项,获取数据
		* FileItem对象的方法:
			* 通用方法:
				* 判断是否是普通表单项:isFormField() 
				* 获取表单项name名称:getFieldName()
			* 普通表单项的方法:
				* 获取表单项的值:getString(String encoding) 
			* 文件表单项的方法:
				* 获取文件名称:getName()
				* 获取文件类型:getContentType() 
				* 获取文件大小:getSize()

操作流程


			* 获取文件关联的输出流:getOutputStream()
			* 将文件数据写入硬盘:write(File file)
	//解决文件名称乱码问题
	request.setCharacterEncoding("utf-8");
	
	//1.导入jar包
	//2.创建解析器工厂
	DiskFileItemFactory factory = new DiskFileItemFactory();
	//3.获取解析器
	ServletFileUpload fileUpload = new ServletFileUpload(factory);
	//4.解析 request
	List<FileItem> fileItems = fileUpload.parseRequest(request);
	//5.遍历
	for (FileItem fileItem : fileItems) {
		//获取表单项的name属性值
		String fieldName = fileItem.getFieldName();
		System.out.println(fieldName);
		//5.1判断
		if(fileItem.isFormField()){
			//普通表单项
			//获取表单项提交的数据
			 //获取普通表单项的值
     	if (fieldName.equals("username")) {
        	 String username = fileItem.getString("utf-8");
        	 System.out.println("通表单项的值:" + username);
           				 }
		}else{
			//文件表单项
			//获取文件名称
			String name = fileItem.getName();
			//文件类型
			String contentType = fileItem.getContentType();
			//文件大小
			long size = fileItem.getSize();
			System.out.println(name);
			System.out.println(contentType);
			System.out.println(size);
			
//将文件写入硬盘上 这个upload文件夹一开始判断一下,如果不存在,要用代码创建出来
File dir = new File(this.getServletContext().getRealPath("/upload"));
			String filename = UUIDUtils.randomUUID() + "_" + name;//随机文件名(保证文件名称唯一)
			
			File file = new File(dir, filename);
			
			fileItem.write(file);
			
		}
		System.out.println("-------------------------");
	}

案例演示 JSP代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="http://localhost:8080/WenJianShangChuan_war_exploded/upload" method="post" enctype="multipart/form-data">
   用户名 <input type="text" name="username" >
    密码 <input type="password" name="password" >
    选择上传的文件:<input type="file" name="uplod">
    <input type="submit" value="提交">
  </form>
  </body>
</html>

Servlet代码

@WebServlet(name = "Upload", value = "/upload")
public class Upload extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doPost(request, response);
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload fileUpload = new ServletFileUpload(factory);
    try {
      List<FileItem> fileltems = fileUpload.parseRequest(request);
      for (FileItem fileItem : fileltems) {

          if (fileItem.isFormField()) {
            if (fileItem.equals("username")) {
              String username = fileItem.getString();
              System.out.println("姓名"+username);
            }
            if (fileItem.equals("password")) {
              String password = fileItem.getString();
              System.out.println("密码"+password);
            }
          }else {
            String name = fileItem.getName();
            String contentType = fileItem.getContentType();
            long size = fileItem.getSize();
            File dir = new File(this.getServletContext().getRealPath("/upload"));
            String filename=name;
            File file = new File(dir, filename);

            fileItem.write(file);
          }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

成功后

3.2 文件下载

文件下载:服务器端保存到客户端
注意:下载时测试中文命名的文件 不要在eclipse 里面改中文名 可以在外面改好之后拿进来
* 下载方式:
1.超链接直接指向目标资源下载:
* 如果浏览器可以解析目标文件,则直接在浏览器中打开。反之,则弹出下载提示框
2.通过Servlet实现下载
1.超链接指向servlet,传递目标资源的标识符。
2.定义Servlet
2.1获取文件标识,找到文件对象
2.2创建输入流,关联目标文件
2.3设置响应头:
content-disposition:消息体数据的打开方式
* content-disposition:attachment;filename=xxx
content-type:类型
2.4将输入流数据写入response输出流中

下载细节:
	文件名乱码:
		1.Servlet获取文件名称,解决乱码,get请求
			filename = new String(filename.getBytes("iso-8859-1"), "utf-8");
		2.让下载提示框也显示中文。
				2.1获取浏览器版本信息	
			String agent = request.getHeader("user-agent");
				2.2根据不同的版本,发送不同的数据
  <body>
	<a href="/day13/xlj.avi">寻龙诀.avi 下载</a>
	<a href="/day13/404.jpg">寻龙诀海报</a>
	<hr>
	<a href="/day13/downloadServlet?filename=寻龙诀.avi">寻龙诀.avi 下载</a>
	<a href="/day13/downloadServlet?filename=404.jpg">寻龙诀海报</a>
</body>
	// 1.获取文件名称
	String filename = request.getParameter("filename");
	//如是8.0以上版本的tomcat 这行不需要因为8.0的tomcat get请求 中文参数tomcat8.0已经处理了
	//filename = new String(filename.getBytes("iso-8859-1"), "utf-8");
	// 2.获取文件对象
	String realPath = this.getServletContext().getRealPath("/" + filename);
	// 3.创建输入流,关联文件
	FileInputStream fis = new FileInputStream(realPath);

	// 获取浏览器的版本信息,根据不同的浏览器,发送不同的数据(文件名称)
	String agent = request.getHeader("user-agent");
	if (agent.contains("MSIE")) {
		// IE浏览器
		filename = URLEncoder.encode(filename, "utf-8");
		filename = filename.replace("+", " ");
	} else if (agent.contains("Firefox")) {
		// 火狐浏览器
		BASE64Encoder base64Encoder = new BASE64Encoder();
		filename = "=?utf-8?B?"
				+ base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
	} else if (agent.contains("Chrome")) {
		// google浏览器
		filename = URLEncoder.encode(filename, "utf-8");
	} else {
		// 其它浏览器
		filename = URLEncoder.encode(filename, "utf-8");
	}

	// 4.设置响应头
	// 告诉浏览器,响应消息体数据打开方式
	response.setHeader("content-disposition", "attachment;filename="
			+ filename);
	response.setHeader("content-type", this.getServletContext()
			.getMimeType(filename));
	// 5.写数据
	IOUtils.copy(fis, response.getOutputStream());

	fis.close();

下载的常用API说明:

​ response.getOutputStream();

​ servletContext.getResourceAsStream();

​ servletContext.getMimeType();

​ response.setContentType();

response.setHeader(“Content-Disposition”,“attachment;fileName=1.jpg”);

这个响应头告诉浏览器。这是需要下载的。而attachment表示附件,也就是下载的一个文件**fileName=**后面,表示下载的文件名。

完成上面的两个步骤,下载文件是没问题了。但是如果我们要下载的文件是中文名的话。你会发现,下载无法正确显示出正确的中文名。

原因是在响应头中,不能包含有中文字符,只能包含ASCII码

URLEncoder解决IE和谷歌浏览器的附件中文问题

​ 如果客户端浏览器是IE浏览器或者是谷歌浏览器。我们需要使用URLEncoder类先对中文名进行UTF-8的编码操作。

​ 因为IE浏览器和谷歌浏览器收到含有编码后的字符串后会以UTF-8字符集进行解码显示。

//把中文名进行UTF-8编码操作。

Stringstr="attachment;fileName="+URLEncoder.encode("中文.jpg","UTF-8");

//然后把编码后的字符串设置到响应头中

response.setHeader("Content-Disposition",str);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值