JavaEE中级.20190611.Servlet3.0 注解.Servlet3.0.请求乱码问题.JSP.EL表达式.JSP内置对象四种属性范围(重点)

一.Servlet3.0 注解

           在 Servlet3.0 之前一直使用的都是配置文件的方式来实现各种组件,Servlet3.0 之后提供了注解,可以达到零配置。但现实中一般是注解+配置结合使用。我们看几个常用的注解。

      1. @WebServlet
          开发servlet项目,使用@WebServlet将一个继承于javax.servlet.http.HttpServlet 的类定义为Servlet组件。在Servlet3.0中 , 可以使用@WebServlet注解将一个继承于javax.servlet.http.HttpServlet的类标注为可以处理用户请求的 Servlet。
          用注解配置 Servlet

@WebServlet(name="ServletDemo",value="/servletDemo")

           也可以配置多个 urlPatterns 来指定多个访问路径

@WebServlet(name="ServletDemo",urlPatterns={"/servletDemo","/servletDemo2"})

       2. @WebFilter
            @WebFilter 用来配置过滤器

@WebFilter(filterName="TestFilter",urlPatterns="/*")

       3. @WebListener
            Servlet3.0 提供@WebListener 注解将一个实现了特定监听器接口的类定义为监听器。将 实现了 ServletContextListener 接口的 MyServletContextListener 标注为监听器。
       4. @MultipartConfig
           使用注解@MultipartConfig 将一个 Servlet 标识为支持文件上传。 Servlet3.0 将 multipart/form-data 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作。

                

二.Servlet3.0

          Servlet3.0 将 multipart/form-data 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作

package com.shsxt.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 使用注解@MultipartConfig 将一个 Servlet 标识为支持文件上传。
	Servlet3.0 将 multipart/form-data 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作。
 * @author Lisa Li
 *
 */
@WebServlet("/upload")
@MultipartConfig // 表示支持文件上传  注:如果前台表单提交时的表单类型为enctype="multipart/form-data",后台必须要加@MultipartConfig注解!!!!!
public class UploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;


	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 获取普通参数
		String name = request.getParameter("uname");
		System.out.println(name);
				
		
		
		// 得到Part对象
		//  request.getPart(name):name代表的是前台文件域的name属性值
		/*Part part = request.getPart("myfile");
		// 得到上的文件名
		String fileName = part.getSubmittedFileName();
		// 通过上传的文件名是否为空可以判断是否上传了文件
		if (fileName == null || "".equals(fileName)) {
			
			// 未上传文件
			return;
		}
		
		// 得到文件存放路径
		String realPath = request.getServletContext().getRealPath("/");
		// 上传文件到指定路径
		part.write(realPath + fileName);
		*/
		
	}

}

三.请求乱码问题      

 Tomcat8及以上版本Tomcat7及以下版本
POST请求会乱码,request.setCharacterEncoding("UTF-8");会乱码,request.setCharacterEncoding("UTF-8");

GET

请求

不会乱码,不处理会乱码,new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");

 

 

 

 

 

package com.shsxt.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

@WebFilter("/*")
public class EncodeFilter implements Filter {  
    public EncodeFilter() {
        
    }
	
	public void destroy() {
	}
	
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException {
		
		// 基于HTTP
		HttpServletRequest request = (HttpServletRequest) arg0;
		HttpServletResponse response = (HttpServletResponse) arg1;
		
		// 处理POST请求乱码 (无论什么版本服务器)
		request.setCharacterEncoding("UTF-8");
		
		// 处理GET请求乱码
		// 1、得到请求类型
		String method = request.getMethod();
		// 2、判断是否是GET请求
		if ("GET".equalsIgnoreCase(method)) {
			// 3、如果是GET请求,则获取服务器版本信息
			String serverInfo = request.getServletContext().getServerInfo();
			//System.out.println(serverInfo);
			// 4、得到服务器的版本号
			String versionStr = serverInfo.substring(serverInfo.lastIndexOf("/")+1,serverInfo.lastIndexOf("/")+2);
			// 5、判断是否是Tomcat8以下版本服务器
			if (Integer.parseInt(versionStr) < 8) {
				// new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");
				// 定义类,继承HttpServletRequestWrapper封装类,重写getParameter()方法,返回的类的本质是request对象
				HttpServletRequest req = new MyWapper(request);
				// 放行指定request对象  (Ttomcat7及以下版本的GET请求)
				chain.doFilter(req, response);
				return;
			}
		}
		
		// POST请求和Ttomcat8及以上版本的GET请求放行
		chain.doFilter(request, response);
	}	

	public void init(FilterConfig fConfig) throws ServletException {
		
	}

}

/**
 * 1、定义类
 * 2、继承HttpServletRequestWrapper封装类
 * 3、重写getParameter()方法
 * 
 * @author Lisa Li
 *
 */
class MyWapper extends HttpServletRequestWrapper {
	
	// 定义属性。提升作用域
	private HttpServletRequest request;

	/**
	 * 带参构造器
	 * @param request
	 */
	public MyWapper(HttpServletRequest request) {
		super(request);
		this.request = request;
	}

	/**
	 * 重写getParameter()方法,处理乱码问题
	 */
	@Override
	public String getParameter(String name) { // name代表的是前台传递的参数名,即键
		
		// 获取参数的值
		String value = request.getParameter(name);
		
		// 判断值是否为空,不为空处理乱码问题
		if (value == null || "".equals(value.trim())) {
			return value;
		}
		try {
			// 处理乱码问题
			value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return value;
	}	
}

四.JSP

      1.配置Eclipse

         这一步不是必须的,当然由于 eclipse 中有写默认的配置项我们觉得不是很完美,比如 字符编码,比如 HTML 的 DOCTYPE,我们可以在新建 JSP 页面之前就先修改为我们需要的。

                

                  

                  

              最后一路保存,关闭即可

       2. 新建 JSP 文件

                   

                    

             新建完成以后的完整代码如下:

                    

       3.JSP基础语法

           1)注释
              在 JSP 中支持两种注释的语法操作,一种是显示注释,这种注释是允许客户端看见的; 另一种是隐式注释,此种注释是客户端无法看见的
              ① 显示注释语法:从 HTML 风格继承而来
              ② 隐式注释语法:从 JAVA 风格继承;JSP 自己的注释
            JSP 的三种注释方式:
              ① // 注释,单行注释 /* 多行注释*/
              ② <!-- HTML风格的注释 -->
              ③<%-- JSP注释 --%>
          2)Scriptlet
             在 JSP 中最重要的部分就是 Scriptlet(脚本小程序),所有嵌入在 HTML 代码中的 Java 程序都必须使用 Scriptlet 标记出来,在 JSP 中一共有三种 Scriptlet 代码:
             第一种:<% %>: java 脚本段,可以定义局部变量、编写语句
             第二种:<%! %>:声明,可以定义全局(成员)变量、方法、类
             第三种:<%= %>:表达式,数据一个变量或具体内容
             通过观察解析为 java 文件的 jsp 代码理解三种小脚本

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>JSP的使用</h2>
	<%
		String str = "Hello JSP";
		System.out.println(str);
		response.getWriter().write(str);
	
	%>
	
	<%!
		String memberStr="a member String";
	%>
	
	<%=memberStr%>
	<h1>This is a JSP page!</h1>
	
</body>
</html>

      4.JSP指令标签

         page指令
                  language:支持的语言,目前只有java
                  contentType:响应类型及编码格式
                  pageEncoding:字符编码
                  import:导包,只有该属性可以同时设置多次
                  errorPage:当页面报错时要跳转的页面,一般与isErrorPage属性一起使用,且跳转的页面的isErrorPage属性设置为true
        isErrorPage:是否是处理错误的页面,默认是false。一般与errorPage属性一起使用
        注:页面的编码以charset的值为准;若charset未设置,则以pageEncoding为准;若两者都未设置,则使用默认编码ISO-8859-1

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"
 import="java.util.List" import="java.util.ArrayList" isErrorPage="false" %>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP指令标签</title>
</head>
<body>

<%
	List<String> list = new ArrayList<>();

	/* int a = 1/0; */

%>

</body>
</html>

      5.include静态包含和动态包含

         1)include静态包含
                格式:<%@include file="文件路径" %>  相对路径
                           file属性支持表达式去取值
                特点:只会生成一个源码文件,相当于直接将内容拷贝进来,所以不能有同名变量。
                           运行效率高一点点。耦合性较高,不够灵活。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>include静态包含</title>
</head>
<body>
<div style="height: 800px;width:800px">
	<div id="left" style="width: 200px;height:800px;background-color: pink;float: left;">
	 	<%@include file="left.jsp" %>
	</div>
	<div id="right" style="width: 600px;height:800px;background-color: gray;float: left;">
	 	<%@include file="right.jsp" %>
	</div>
</div>
<%
	// int a = 1;

%>

</body>
</html>

         2)include动态包含
              语法:<jsp:include page="要包含的文件路径"></jsp:include>
                         page属性支持表达式去取值
              特点:生成多个源码文件,相当于方法的调用,可以有同名变量。
                         耦合度低,比较灵活,效率高。    
              注:
                  ①<jsp:include>双标签之间不能有任何内容(除非有参数)  
                      Expecting "jsp:param" standard action with "name" and "value" attributes
                  ②动态包含可以传递参数
                       <jsp:param name="参数名" value="参数值"/>
                      获取参数使用:request.getParameter(name)
                      value属性支持表达式,name属性不支持
                      The name attribute of the jsp:param standard action does not accept any expressions

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>include动态包含</title>
</head>
<body>

  <%
 	int a =10;
  
  	String key = "userName";
  	String val = "admin";
 
 %>
 
 <div style="height: 800px;width:800px">
	<div id="left" style="width: 200px;height:800px;background-color: blue;float: left;">
	 	<jsp:include page="left.jsp"></jsp:include>
	 	
	 	<jsp:include page="left.jsp">
	 		<jsp:param value="<%=val %>" name="uname"/>
	 	</jsp:include>
	 	
	</div>
	<div id="right" style="width: 600px;height:800px;background-color: green;float: left;">
	 	<jsp:include page="right.jsp"></jsp:include>
	</div>
</div>
</body>
</html>

       6.九大内置对象

            

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
	// 四大域对象
	pageContext.setAttribute("uname1", "zhanggsan");
	//request
	// session
	// application
	
	// 两个输出对象
	// out
	// response
	
	// 配置对象
	// config
	
	// 当前页面对象
	//page
	
	// 异常对象  主要当前页面设置了isErrorPage="true"时才能使用
	// exception

%>
</body>
</html>

五.EL表达式

        语法:${key }  key代表的是存在域对象中的键
        注意:el表达式一般操作的是域对象,无法操作变量
        取值范围:
               从小范围到大范围取,取到为止,若未取到,则一直向大返回查找;若四个范围都未获取到,返回空字符串。    
        获取指定范围的值:
               pageScope、requestScope、sessionScope、applicationScope
               pageContext, request, session, application;范围依次是,本页面,一次请求, 一次会话,整个应用程序。
               而 EL 默认的查找方式为 从小到大查找,找到即可。当域对象全 找完了还未找到则返回空字符串””。
        EL操作对象
               获取对象中的属性:${对象.属性名}
               注:属性必须提供get和set方法

<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@page import="com.shsxt.model.User"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>EL表达式</title>
</head>
<body>

<%
	// 设置域对象的值
	pageContext.setAttribute("uname", "zhangsan");
	request.setAttribute("uname", "lisi");
	session.setAttribute("uname", "wangwu");
	application.setAttribute("uname", "zhaoliu");
	
	String str = "admin";
	
	// 将对象存到域对象中
	User user = new User();
	user.setUserId(1);
	user.setUserName("Lisa");
	user.setUserPwd("123123");
	request.setAttribute("user", user);
	
	
	// 将集合存到域对象中
	User user2 = new User();
	user2.setUserId(2);
	user2.setUserName("Lily");
	user2.setUserPwd("123456");
	
	List<String> list = new ArrayList<>();
	list.add("aaa");
	list.add("bbb");
	list.add("ccc");
	
	List<User> userList = new ArrayList<>();
	userList.add(user);
	userList.add(user2);
	
	
	List<String> list2 = new ArrayList<>();
	
	List<String> list3 = null;
	
	request.setAttribute("mylist", list);
	request.setAttribute("userList", userList);
	request.setAttribute("list2", list2);
	request.setAttribute("list3", list3);
	
	
	
	Map map = new HashMap();
	map.put("aaa", "111");
	map.put("bbb", 2222);
	map.put("ccc-a", 333);
	request.setAttribute("map", map);
	
	
	
	request.setAttribute("num", 10);
	request.setAttribute("num2", 2);
	request.setAttribute("str1", "aa");
	request.setAttribute("str2", "bb");
	
	pageContext.setAttribute("a", "aa", PageContext.REQUEST_SCOPE);
	
	pageContext.getAttribute("a", PageContext.REQUEST_SCOPE);
	
	
%>

<%=request.getAttribute("uname1") %>

<hr>


 <br>
 <h2>EL的基本使用</h2>
 uname:${uname } <br>
 uname1: ${uname1 }<br>
 requestScope:${requestScope.uname } <br>
 str:${str }<br>
 
 
 
 <br><br>
 <h2>EL 对象取值</h2>
 user对象:${user }<br>
    获取user对象中的属性:${user.userName }<br>
 
 
 
 <h2>EL 集合取值</h2>
    获取集合:${mylist } ---- ${userList }<br>
   获取指定下标的值: ${mylist[0] } ---- ${userList[0].userPwd }<br>
  获取集合的长度:${userList.size() }
   
  <h2>判断为空empty</h2>
   判断字符串是否为空:${empty uname } --- ${empty uname1 } --- ${!empty uname }<br>
   判断对象是否为空:${empty user }<br> 
   判断集合是否为空:${empty userList }  --- ${empty list2 } --- ${empty list3 }<br>
   
 <h2>EL Map取值</h2>
   获取Map的值:${map }<br>
  获取指定key的value:${map.aaa } --- ${map["aaa"] }<br>
  
  
 <h2>EL 运算</h2>
 ${1+1 } -- ${num+1 } -- ${num + num2 } <br>
 ${num / num2 } --- 
<%--  ${num div num2 } --%>
 <br>
 
 <h2>EL 比较</h2>
 ${num == 1 }  -- ${num >= 10 } <br>
 ${str1 == str2 } -- ${str1 eq str2 }<br>
 ${num + 10 > 10 }
 

</body>
</html>

六.JSP内置对象四种属性范围(重点)

     目标
          ⑴掌握属性的操作方法
          ⑵掌握JSP中的四种属性范围的作用
          ⑶掌握pageContext对象设置四种属性范围的方法
     四种属性范围
          在JSP中提供了四种属性的保存范围,所谓的属性保存范围,指的就是一个设置的对象,可以再多少个页面中保存并可以继续使用
          page范围→pageContext : 只在一个页面中保存属性,跳转之后无效
          request范围→request : 只在一次请求中保存,服务器跳转后依然有效
          session范围→session : 在一次会话范围中,无论何种跳转都可以使用,但是新开浏览器无法使用
          application范围→application : 在整个服务器上保存,所有用户都可以用
          属性都有的操作方法

        

        验证各个属性范围的特点
               page: 本页面取得服务器端跳转(<jsp :forward>)后无效
               request : 服务器跳转(<jsp :forward>)有效,客户端跳转(超链接)无效
               如果是客户端跳转,则相当于发出了两次请求,那么第一次的请求将不存在了
              如果希望不管是客户端还是服务器跳转,都可以保存的话,就需要继续扩大范围。
              session : 无论客户端还是服务器端都可以取得,但是现在重新开启一个新的浏览器,则无法取得之前设置的session了,因为每一个session只保存在当前的浏览器当中,并在相关的页面取得。

              对于服务器而言,每一个连接到它的客户端都是一个session
             如果想要让属性设置一次之后,不管是否是新的浏览器打开都能取得则可以使用application
             application : 所有的application属性直接保存在服务器上,所有的用户(每一个session)都可以直接访问取得
             只要是通过application设置的属性,则所有的session都可以取得,表示公共的内容,但是如果此时服务器重启了,则无法取得 了,因为关闭服务器后,所有的属性都消失了,所以需要重新设置。
             使用哪个范围呢?在合理范围尽可能小
        page范围
               page范围是通过pageContext对象设置的,之前研究过的page属性范围中使用的是pageContext进行属性设置的,但是                 从javax.servlet.jsp.PageContext类中可以发现,有以下的一种设置属性的方法:
               public void setAttribute(String name, Object value, int scope)
               在PageContext类中存在四个表示属性范围的常量,可以直接通过这些常量指定scope:
                pageContext.PAGE_SCOPE
                pageContext.REQUEST_SCOPE
                pageContext.SESSION_SCOPE
                pageContext.APPLICATION_SCOPE
                在其它页面取值时,需要指定对应的作用域,或者通过EL表达式
                 <%=pageContext.getAttribute("a",pageContext.SESSION_SCOPE) %>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值