jsp
java server page
java 页面技术
sun公司制定额一种服务器端动态页面生成技术规范
jsp实际上是一个以.jsp为后缀的文件,该文件主要由html和少量的java代码组成,容器会将jsp文件先转换成一个对应额servlet然后再去执行.
jsp文件:
注释<!-- 注释内容-->注释的内容可以是java 代码 如果是java代码会被容器执行
<%--z注释内容--%> 注释的内容不能有java 代码,如果有 会被容器忽略
html(css javascript)
java代码
java代码片段
<% java代码 %>
jsp表达式
<%= java表达式 %>
jsp 声明 <%! %> 可以写方法
jsp隐含对象
在jsp 文件里面,不用声明和创建,就以直接使用的对象
容器会自动添加声明 创建这些对象的语句
容器将jsp转换为 servlet 会自动添加
1. 与输入/输出有关的对象: request、response、out
2. 与属性作用域有关的对象:session、application、pageContext
3. 与Servlet 相关对象:page、config
4. 与错误处理有关的:exception
requestHttpServletRequest类的实例
responseHttpServletResponse类的实例
outPrintWriter类的实例,用于把结果输出至网页上
sessionHttpSession类的实例
applicationServletContext类的实例,与应用上下文有关
configServletConfig类的实例
在web.xml
<servlet> <servlet-name>one</servlet-name> <jsp-file>/one.jsp</jsp-file> <init-param> <param-name>name</param-name> <param-value>lmdtx</param-value> </init-param> </servlet> <serlvet-mapping> <servlet-name>one</servlet-name> <url-pattern>one</url-pattern> </servlet-mapping>
pageContextPageContext类的实例,提供对JSP页面所有对象以及命名空间的访问,容器会为每一个jsp实例 jsp 对应的那个servlet对象 创建唯一的一个pasgeContext对象,这个对象会一直存在,除非jsp实例被销毁 类似 sessionContext 可以绑定数据 这个数据只有对应的jsp实例可以访问 他还可以找到其他的8个隐含对象
page类似于Java类中的this关键字(基本不用)
ExceptionException类的对象,代表发生错误的JSP页面中对应的异常对象(必须是一个错误处理页面才能用) 也就是<%@ isErrorPage="true"%>
jsp执行
容器要将jsp文件装换成一个java类 就是一个servlet
html(css,js) 放在service 方法里面 用out.write 输出
java代码片段 放在service 方法里面 照搬
容器对这个servlet 类尽心编译,实例化,初始化 调用servlet 方法处理请求
java 表达式 使用out.println()
指令
告诉容器在将jsp文件装换为java类时做的一些额外的处理
比如导包
<%@ 指令名称 属性名称=属性值 %>
page定义网页依赖属性,比如脚本语言、error页面、缓存需求等等
<%@ page import ="java.util.*" %>
buffer 指定out对象使用缓冲区的大小
autoFlush 控制out对象的 缓存区
pageEncoding 告诉容器这个jsp文件的编码格式utf-8格式 有部分的容器默认使用iso-8859-1解码 添加这个属性,容器可以进行正确的解码
contentType 设置response.setContentType的内容指定当前JSP页面的MIME类型和字符编码
errorPage 指定当JSP页面发生异常时需要转向的错误处理页面
isErrorPage 指定当前页面是否可以作为另一个JSP页面的错误处理页面
extends 指定servlet从哪一个类继承
import 导入要使用的Java类
info 定义JSP页面的描述信息
isThreadSafe 指定对JSP页面的访问是否为线程安全
language 定义JSP页面所用的脚本语言,默认是Java
session 指定JSP页面是否使用session
isELIgnored 指定是否执行EL表达式
isScriptingEnabled 确定脚本元素能否被使用
include包含其他文件
作用 将file 属性所指定的文件的内容插入到指令所在的位置
<%@include file="要包含的文件(jsp;html 都可以 )"%>
taglib引入标签库的定义
<%@ page session="true" %> true/false 默认 true
当值为false ,容器就不再添加获得session对象的代码.
<%@ errorPage = "xxx.jsp"%>
<%@ isErrorPage="true"%> true/false
转发 Servlet 调用 jsp
1个web 组件servlet 或者jsp 之类的 将未完成的处理 通过容器交给另外一个web组件继续完成
常用 一个servlet 获得数据之后 转发给 jsp 由 这个 jsp 来负责展现这些数据
1绑定数据到request 对象上
reuest.setAttribute(String name,Objetct obj);
url 转发的目的地址
2获得转发器 RequestDispatcher rd = request.getRequestDispatcher(String url);
3转发 rd.forward(request,response);
Object request.getAttribute(String name);//根据绑定名称找到绑定值, 如果值不存在 返回null
转发的特点,
转发后 浏览器的地址栏的地址是不变的
转发的目的地 仅限于同一个应用.
转发需要注意的问题. 转发之前,不能调用 out.close()
转发之前 容器会先清空response 对象上的缓存的数据
处理 servlet 运行的时候产生的异常
使用转发
将异常交给servlet 容器来处理
将异常抛给容器, throw new ServletException(e);
配置一个错误处理页面 告诉容器,捕获到指定的异常以后调用location指定的页面
<error-page> <exception-type>javax.servlet.ServletException</exception-type> <location>/error.jsp</location> </error-page>
路径问题
链接地址 表单提交地址 重定向地址 转发的地址
相对路径 不以 "/" 的路径
绝对路径 以"/"开头的路径
链接地址 表单提交地址 重定向地址从应用名开始写,
转发从应用名之后开始写
获得应用名: 返回 /应用名
String request.getContextPath()
状态管理
将浏览器与web服务器之间多次交互当做一个整体来看待 并且 将多次交互所涉及的数据 保存下来
如何进行状态管理:
客户端的状态管理
将状态保存在客户端,比如 cookie
服务器端的状态管理
将状态保存在服务器端 session
cookie
当流浪器访问服务器时,服务器会发送少量的数据给浏览器 使用 set-cookie 消息头
浏览器会将这些数据保存下来(可以是内存,也可以是硬盘上)当浏览器再次访问服务器时,会将之前保存的这些数据发送给服务器(使用 cookie 消息头)
创建cookie
Cookie c = new Cookie(String name,String value);
response.addCookie(c);
查询cookie
Cookie[] cookies = request.getCookies();
注意:该方法有可能返回null
String cookie.getName();
String cookie.getValue();
cookie 的生存时间
cookie.setMaxAge(int seconds);
seconds 单位是秒
可以 >0 浏览器会把cookie 保存到硬盘上超过指定的时间 浏览器会删除这个cookie
<0缺省值 浏览器会把cookie保存在内存里面 只要关闭浏览器cookie就会被销毁
=0 删除cookie
要删除一个名叫user的cookie
Cookie c = new Cookie("user","");
c.setMaxAge(0);
response.addCookie(c);
编码问题
cookie 只能保存合法的ascii字符
中文不是ascii 字符 需要将其转换成合法的ascii字符
String URLEncoder.encode(String str,String code);
URLDecoder.decode(String str,String code);
路径问题
浏览器在访问服务器的某个地址的时候,会比较cookie的路径是否与该地址匹配只有匹配的cookie才会发送
匹配的规则 cookie 有一个缺省的路径,值等于创建该cookie的web组件的路径
要访问的地址必须是cookie的路径或者其子路径
缺省的路径 可以用 cookie.setPath(String path); 一般情况下 将path设置为应用名
创建一个cookie
创建一个cookie 对象
Cookie c = new Cookie("user","lmdtx");//英文
Cookie zc = new Cookie("user",URLEncoder.encode("中文","utf-8"));
c.setMaxAge(3600);
c.setPath("/应用名");
response.addCookie(c);
cookie 的限制
cookie 可以被用户禁止
cookie 保存在客户端,不安全,敏感数据需要加密
cookie 保存的数据大小有限制 大约是4k左右 和浏览器有关
浏览器保存的cookie的数量也有限制,大约是300个左右 和浏览器有关
session 会话 浏览器 访问服务器的时候服务器会创建一个session对象这个对象有一个唯一的id sessionId 服务器在默认情况下 会使用cookie机制将sessionId 发送给浏览器 浏览器再次访问服务器时 会将sessionId发送给服务器,服务器依据sessionId 找到之前创建的session对象
获得一个session对象
接口 工厂
HttpSession s = request.getSession(boolean flag);
当flag = true 先查看请求当中是否有sessionId 如果没有册创建一个session对象,如果有 就根据sessionId 查找对应的session对象 如果找到 就返回,找不到,就创建一个新的session对象
当flag=false 先查看请求当中是否有sessionId 如果没有,返回null 如果有 就根据sessionId 查找对应的session对象, 找到 返回,找不到 返回null
HttpSession s = request.getSession()
等于 HttpSession s = requset.getSession(true);
常用方法
String session.getId();//获得sessionId
setAttribute(String name,Object obj); //绑定
Object getAttribute(String name);//获取
removeAttribute(String name);//移除绑定
绑定的是对象....
session 超时
容器会将空闲过长的session对象删除掉
容器默认超时时间限制一般是30分钟
修改容器缺省的超时限制
tomcat conf/web.xml session-config session-timeout
也可以放到 应用中的web.xml 缩小改动范围
<session-config> <session-timeout>30</session-timeout> </session-config>
//空闲时间
setMaxInactiveInterval(int seconds);
删除session
invalidate()
session 验证
登录
建表
验证码
package util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class CheckcodeServlet extends HttpServlet {
private int width=80;
private int height = 30;
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//绘图
//创建一个内存映像对象
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
//获得 画笔
Graphics g = image.getGraphics();
//给画笔设置颜色
Random r = new Random();
g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));
//给画布设置背景颜色
g.fillRect(0, 0, width, height);
//将一个随机数画在画布上
String str= "QAZWSXEDCRFVTGBYHNUJMIKOLP1234567890";
String number = "";
for(int i=0;i<4;i++){
number += str.charAt(r.nextInt(str.length()));
}
//把验证码绑定到session对象上
HttpSession session = request.getSession();
session.setAttribute("number", number);
g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));
//设置字体
g.setFont(new Font(null,Font.ITALIC,20));
g.drawString(number, 10,20);
for(int i =0;i<8;i++){
g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
}
//将图片压缩输出到浏览器
response.setContentType("image/jpeg");
OutputStream ops = response.getOutputStream();
//write方法将原始图片压缩,然后发送给response对象
javax.imageio.ImageIO.write(image, "jpeg", ops);
}
}
String number1 = request.getParameter("number");
HttpSession session = request.getSession();
String number2 = (String)session.getAttribute("number");
System.out.println(number1);
System.out.println(number2);
if(!number1.equalsIgnoreCase(number2)){
//验证码错误
request.setAttribute("number_error", "验证码错误");
request.getRequestDispatcher("login.jsp").forward(request, response);
return;
}
<tr>
<td valign="middle" align="right">
验证码:
</td>
<td valign="middle" align="left">
<input type="text" class="inputgri" name="number" /><br/>
<img src="checkcode" onclick = "this.src='checkcode?'+Math.random();">
<%
String msg2 = (String) request.getAttribute("number_error");
%>
<span style="color:red;"><%=((msg2 == null)?"":msg2)%></span>
</td>
</tr>
加密
保存 密码使用摘要加密
不可逆性:按照摘要加密算法生成的密文(也叫摘要)即使知道了加密算法,也不能够反推出明文
唯一性:不同的明文,对应唯一的摘要
package util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.misc.BASE64Encoder;
public class MD5Util {
public static String encrypt(String str) throws NoSuchAlgorithmException{
MessageDigest md = MessageDigest.getInstance("md5");
byte[] buf = md.digest(str.getBytes());
//要将字节数组转换成一个字符串
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(buf);
}
}
session 默认是 使用 cookie 的 如果 cookie 被禁止 还要使用 session 也是可以的
可以使用URL 重写来解决 这个问题.使链接中有 jsessionid
浏览器访问服务器上的某个地址时,需要使用 服务器提供的地址 这个地址后面 会添加sessionId
1==>response.encodeURL(String url); 这种方法用于链接地址,表单提交地址的处理
2==> response.encodeRedirectURL(String url); 这个用于重定向地址的处理
response.redirect(response.encodeRedirectURL("重定向地址"));
3==> 转发不需要考虑, 转发是服务器内部的
session 和cookie 相比
session 安全(状态保存在服务器端)
cookie 将状态保存在浏览器端
session 保存的数据更大
cookie 保存的大约4k
session 保存的数据类型是任意的
cookie 只能保存字符串
session 对服务器的要求高,保存在服务器端,会占用服务器更多的内存空间
cookie 在浏览器,不会占用服务器
过滤器
servlet 规范当中定义的一种特设的组件,用来拦截servlet 容器的调用过程并进行相应的处理
写一个java类实现Filter接口
在doFilter 方法里面 编写相应的拦截处理
配置过滤器 在web.xml 让容器哪一些请求需要拦截
容器启动,就会将过滤器实例化 容器会立刻 调用init方法 初始化 init方法只会执行一次容器会事先创建好一个符合 FilterConfig接口要求的对象 FilterConfig提供了getInitParameter 方法来访问过滤器的初始化参数
容器收到请求之后,会调用doFilter 方法来处理 类似 servlet的service方法
容器会将事先创建好的requset 和response对象作为参数传递进来 如果调用了FilterChain的doFilter方法表示让容器继续调用后续的过滤器 如果没有过滤器了 就 调用servlet
容器在销毁过滤器之前, 会调用destroy方法 这个方法也只会执行一次
过滤器 web.xml 配置 一般写在 servlet 前面
<url-pattern>/*</url-pattern>
所拦截的地址 /* 所有
<filter> <filter-name>filter1</filter-name> <filter-class>web10.CommentFilter1</filter-class> </filter> <filter-mapping> <filter-name>filter1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
过滤器的优先级
当有多个过滤器都满足过滤条件,则容器按照 <filter_mapping>出现的先后顺序来调用哥哥过滤器
初始化参数
filter 可以接受一些参数。
init-param的param-name 就是参数名
param-value就是参数值,支持多个参数
每一个 filter 都有一个 init 方法
可以再这个 方法中通过 getInitParamter("key");
key 就是 param-name的值,来获取对应的参数值
String FilterConfig.getInitParamenter(String paramNmae);
常用的就是设置编码过滤器
例如
<init-param>
<param-name>encoding</param-name>
<parma-value>UTF-8</param-vaue>
</init-param>
过滤器
可以实现代码的 可插拔性 增加或者减少某个功能模块,不会影响程序的正常执行
可以将多个模块相同的处理逻辑几种卸载过滤器里面,方便代码的维护
监听器
servlet 规范当中定义的一种特殊的组件,用于监听servlet容器产生的事件并进行相应的处理
容器产生的事件主要有两大类
声明周期相关的事件 容器创建或者销毁 request session servlet上下文产生的时间
绑定相关的事件 容器调用了 request session servlet 上下文的setAttribute removeAttribute 产生的事件
写一个java类 实现相应的监听器
将监听处理逻辑卸载相应的方法里面
注册监听器
<listener> <listener-class>web.CountListener</listener-class> </listener>
servlet 上下文
容器在启动的时候 会为每一个web 应用 都创建一个符合ServletContext接口要求的对象,这个对象就是servlet上下文 这个对象有 唯一性,一个web应用 一个servlet上下文 ;一直存在 只要容器不关闭 servlet上下文会一直存在
如何获得servlet上下文
ServletConfig
FilterConfig
GenericServlet
HttpSession
都提供了getServletContext方法 来获得上下文
servlet的上下文的作用
绑定数据
setAttribute removeAttribute,getAttribute
request
session
servlet
都可以绑定数据 但是存在的时间不一样 request<session<servlet 上下文
尽量使用时间短的
访问的范围不一样
request 对象上绑定的数据可以被同一个请求中所涉及的各个组件访问
session 绑定的数据可以被同一个会话所涉及的组件访问
servlet上下文绑定的数据可以被同一个应用所涉及的所有组件访问
访问全局的初始化参数
同一个应用所包含的各个组件都可以访问的初始化参数
web.xml 中
<context-param>
<param-name></param-name>
<param-value></param-value>
</context-param>
使用 servlet 上下文方法
ServletContext.getInitParamenter("String paramName");
根据逻辑路径 获得实际部署时的物理路径.
String getRealPath(String path);
web.xml 配置
全局初始化参数
过滤器
监听器
servlet
错误处理页面
首页
启动容器马上开始执行相关任务 之后每间隔5S 执行一次任务
package web12;
import java.util.Timer;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class TaskListener implements ServletContextListener{
private Timer timer = new Timer();
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("销毁");
timer.cancel();
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("创建");
timer.schedule(new MyTask(), 0,5000);
}
}
package web12;
import java.util.Date;
import java.util.TimerTask;
public class MyTask extends TimerTask{
@Override
public void run() {
System.out.println(new Date());
}
}
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>web11</display-name> <listener> <listener-class>web12.TaskListener</listener-class> </listener> </web-app>
上传文件
设置表单的提交方式为post
设置表单的enctype属性为 "multipart/form-data"
<form action ="" method="post" enctype="multipart/form-data">
在服务器端,不能使用request.getParameter 方法. 使用 这个方法 返回值 是null
使用InputStream request.getInputStream 方法 自己分析InputStream 还和浏览器有关系,一般使用一些工具来分析这个流 不自己分析 工具:apache commons-fileupload
在Servlet 中使用commons-io和commons-fileupload 上传文件
报错:Java.lang.NullPointerException: No FileItemFactory has been set.
ServletFileUpload sfu = new ServletFileUpload(factory);
未传入 factory
package web12;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class FileUpload extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
//factory 对象为解析器提供解析时的一些缺省的配置
DiskFileItemFactory factory =new DiskFileItemFactory();
//创建一个解析器
ServletFileUpload sfu = new ServletFileUpload(factory);
//使用解析器解析inputStream
try {
//解析器将每一个表单域中的数据封装到一个FileItem对象里面
List<FileItem> items = sfu.parseRequest(request);
//遍历 items 集合 就可以读取每一个表单域的数据
for(int i =0;i<items.size();i++){
FileItem item = items.get(i);
if(item.isFormField()){
//普通的表单域
String name =item.getString();
System.out.println(name);
}else{
//上传文件域
ServletContext sctx = getServletContext();
//根据逻辑路径,获得实际部署的时候的物理路径
String path = sctx.getRealPath("upload");
String fileName = item.getName();
File file = new File(path+File.separator+fileName);
item.write(file);
System.out.println("ok");
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PrintWriter out = response.getWriter();
out.close();
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<form action="fileUpload" method="post" enctype="multipart/form-data">
name:<input name="name"/><br/>
file: <input type="file" name="file"/><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
apache 的fileupload 工具有bug 在某些操作系统上运行时,filename会包含路径
servlet 的线程安全
servlet 存在线程安全问题
容器收到一个请求 就会启动一个线程来处理该请求
容器在默认情况下,对于某个servlet类型,只会创建一个实例
当容器收到多个请求就会有多个线程同时访问某个servlet实例的情况,就有可能产生线程安全问题 多个线程同时修改servlet实例的属性
解决方法:
加锁 使用synchronized 对有线程安全问题的代码加锁
让servlet 实现SingleThreadModel接口(不建议使用)容器会为servlet 创建多个实例(1个线程1个实例)因为有可能会产生过多的实例,影响性能
jsp 标签
jstl 框架 自己的 公司的
jstl apache 开发的
将标签对应的jar文件放到WEB-INF/lib下
使用taglib指令导入标签
taglib指令 <%@taglib uri="" prefix=""%>
uri 指定命名空间 看.tld文件中 的<uri>
prefix 命名空间的前缀
核心标签 if choose forEach
if 当test属性为true时,容器会执行标签体的内容
test属性可以使用el表达式
<c:if test="">
标签体 可以是html 或者java 代码
</c:if>
<c:choose>
<c:when test=""> when 分支
</c:when>
<c:when test="">
</c:when>
<c:when test="">
</c:when>
<c:otherwise> 全部不满足
</c:otherwise>
</c:choose>
forEach 用来遍历集合
items 属性指定要遍历的集合,可以使用el表达式来赋值
var 属性指定绑定名称 绑定范围是pageContest 绑定值是集合中的一个对象
varStatus 属性指定绑定名 绑定范围是pageContest 对应容器创建的对象 这个对象封装了当前迭代的状态 getIndex() 返回当前正在被迭代的对象的下标 从0 开始
getCount() 返回当前被迭代的次数
<c:forEach items="" var="" varStatus="">
</c:forEach>
一种用来代替jsp文件中java 代码的技术 容器在执行的时候,依据jsp标签可以找到对应的标签类,然后调用标签类中的代码 直接在jsp文件中写java代码,不利于jsp文件的维护
容器根据标签的命名空间找到标签的描述文件.tld文件 然后依据标签的名称 找到标签类的名称 创建标签类的实例并调用相应的方法
自定义标签
写一个java类 继承SimpleTagSupport 类
覆盖doTag,标签类的属性与标签的属性要一致,属性必须有set方法
在doTag方法里面编写相应的处理逻辑
描述标签,要在.tld文件里面描述,并将 .tld 文件放到web-inf 文件下
body-content用来告诉容器,标签有没有标签体 如果有 可以出现哪些内容
empty 没有标签体
scriptless 可有标签体 但是 标签体的内容不能出现java代码 (<%%>)
JSP 有标签体 标签体的内容可以重新啊java 代码
复杂标签技术才能支持JSP
简单标签技术只支持empty和scriptless
el表达式
<%@ page isELIgnored="false" %>
不能使用 就在jsp中添加
一套简单的计算规则,用于给jsp标签的属性赋值,也可以脱离jsp标签,直接运行
访问bean的属性
${user.name} 两个相等 ${user["name"]}这个[]里面可以是绑定名也可以出现下标给数组访问
容器会依次从pageContext,request,session,application 中查找(getAttribut)绑定名为"user"的对象, 找到后就不再向后找,调用对象个getName(),然后输出
会将 null 转换为空字符串 如果找不到对应的对象,会输出空字符串
如果需要制定查找范围可以使用 pageScope requestScope sessionScope,applicationScope
${sessionScope.user.name}
进行简单的计算
算术运算,+ - * / % +在这里只是求和
关系运算 > >= < <= == !=
逻辑运算 && || !
empty运算 字符串是否为空 集合是否为空 空字符串 空集合 null 找不到值
获取 url中 参数
${param.name} 等价于 request.getParameter("name");
${paramValues.name}等价于 request.getParameterValues("name");
ajax
用来改善用户体验的技术,利用浏览器内部的一个特殊的对象 XMLHttpRequest对象想服务器发请求 在发请求的时候浏览器不会销毁当前页面,用户还是可以对当前页面做其他的任何操作 ,服务器返回部分数据 不是一个完整的页面 在浏览器端,利用服务器返回的这些数据更新当前的页面 整个过程页面不刷新 标准化的技术 不需要下载插件
IE和非IE有不同的获取方式
1 onreadystatechange 绑定事件处理函数 处理 readystatechange事件 当 readyState 发生改变 就会产生 readyStatechange事件
2 resposeText 获得服务器返回的文本
3 responseXML 获得服务器返回的xml文档
4 status 获得服务器返回的状态码
5 readyState 表示 ajax对象和服务器进行通信的状态 有5个值 0,1,2,3,4
4表示 ajax对象已经获取了服务器返回的所有的数据
获得ajax 对象
function getXhr(){
var xhr = null;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObjext('MicroSoft.XMLHttp');
}
return xhr;
var xhr =getXhr();
发请求get post 都可以
get
xhr.open('get','check_username.do?username=tom',true);
true:发送异步请求 大部分的时候使用true
false:发送同步请求 发送同步请求时, 浏览器会锁定当前页面,用户不能对当前页面进行其他的操作
绑定一个事件处理函数
xhr.onreadystatechange=f1;
send 方法会将请求数据包发送出去
xhr.send(null);//get 使用null
post
服务端的处理逻辑 一般只需要返回部分的数据
事件处理函数 处理服务器返回的数据
function f1(){
// 只用 readyState 等于4 才能获得服务器返回的所有数据
if(xhr.readState == 4){
var txt = xhr.responseText;
dom 操作
}
}
编码
发送get请求 ie浏览器对应的ajax对象对中文参数值会使用gbk进行编码 其他的浏览器会使用utf-8编码 web服务器默认使用 iso8859-1解码 这样就出现了乱码
是用encodeURI函数对请求地址进行编码该函数会对其中的中文参数值按照utf-8进行编码
或者 tomcat server.xml
Connector 中 添加一个
URIEncoding="utf-8"
post 请求
xhr.open('post','check_username.do',true);
//添加一个content-type 消息头
xhr.setRequestHeader('content-type','appliction/x-www-form-urlencoded');
xhr.onreadystatechange=f1;
xhr.send('username=lmdtx&age=18');
编码
所有浏览器 对应的ajax 对象对中文参数都使用utf-8进行解码 服务器使用 iso-8859-1解码 so 会有乱码
request.setCharacterEncoding(utf-8);
json
javascript object notation
是一个轻量级的数据交换标准
将数据转换成一种与平台无关的数据格式并传递给接收方
{属性名1:属性值1,属性名2:属性值2}
属性名必须要用引号
属性值 可以是 number string boolean null object
数组 [{},{},{}]
使用json 编写 ajax应用
先将 java 对象转换成json 字符串 使用 json 提供的工具 JSONObjec JSONArray
将json 字符串 转换为 javascript 对象 使用js框架提供额函数
prototype 框架 提供的evalJSON函数
$(id) document.getElementById(id)
$F(id) $(id).value
$(id1,id2,id3); 分别查找id 为id1 id2 id3 的节点 返回一个由这些节点组成的数组
strip() 除掉字符串两端的空格 和trim 一样
evalJSON 将json 字符串转换成相应的js对象或者js对象组成的数组
jQuery 框架
当ajax 对象 想服务器发请求时, 浏览器会锁定当前页面,用户不能对当期页面做其他的操作
同步异步
同步请求 浏览器会等待服务的响应 浏览器不会向下执行
在open(请求方式,请求地址,false); 发送同步请求
jQuery 基础
jQuery 是一个js框架 最大的特点是 利用 选择器查找到操作的节点,并且将找到的节点封装成一个jQuery对象。 这样封装的好处有两个 一个是可兼容不同的浏览器 代码也会变得简洁
利用 选择器(jQ 借鉴了css选择器的语法) 查找到要操作的dom节点 这些节点会被封装成一个jQ对象 调用jQ对象的属性或者方法 jQ对象与dom对象的转换
dom对象-》jQ对象 $(dom对象)
jQ对象-》dom对象 $obj.get(0); 或者 $obj.get()[0];
选择器 :
基本选择器:
#id -》 根据id
.class 根据 class
element 根据元素
select1,select2..selectn 根据多个
* 所有
<!DOCTYPE html>
<html>
<head>
<title>s1.html</title>
<meta name="keywords" content="keyword1,keyword2,keyword3">
<meta name="description" content="this is my page">
<meta name="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<script type="text/javascript" src="../js/jquery-1.11.1.js"></script>
<script type="text/javascript">
function f1() {
$('#d1').css('font-size','100px');
}
function f2(){
$('.s1').css('font-size','200px');
}
function f3(){
$('div').css('font-size','200px');
}
function f4(){
$('#d1,p').css('font-size','200px');
}
function f5(){
$('*').css('font-size','200px');
}
</script>
</head>
<body>
<div id="d1">this id </div>
<div class="s1">this class</div>
<p class="s1">this class</p>
<input type="button" value="1" οnclick="f1()"/>
<input type="button" value="2" οnclick="f2()"/>
<input type="button" value="3" οnclick="f3()"/>
<input type="button" value="4" οnclick="f4()"/>
<input type="button" value="5" οnclick="f5()"/>
</body>
</html>
层次选择器 selector
select1 select2 select1 下的 所有 select2节点
select1>select2 select1 子节点中 是 select2 的节点
select1+select2 找到select1 的下一个满足条件的节点
select1~select2 找到select1 后面的所有满足条件的节点
过滤选择器
基本过滤选择器
:first 第一个
:last 最后一行
:not(selector) 反选
:even 偶数行
:odd 奇数行
:eq(index) 等于
:gt(index) 大于
:lt(index) 小于
内容过滤选择器
:contains(text) 匹配包含给定文本的元素
:empty 匹配所有不包含子元素或者文本的空元素
:has(selector) 匹配含有选择器所匹配的元素中有selector 的元素
:parent 匹配含有子元素或者文本的元素
可见性过滤选择器
:hidden 匹配所有不可见元素
或者type为hidden的元素
:visible 匹配所有的可见元素
属性过滤选择器
[attribute] 属性是
[attribute=value] 属性的值是
[attribute!=value] 属性的值不是
子元素过滤选择器
:nth-child(index/even/odd)
表单对象属性过滤选择器
:enabled
:disabled
:checked
:selected
表单选择器
:input
:text
:pasword
:radio
:checkbox
:submit
:image
:reset
:button
:file
:hidden
<!DOCTYPE html>
<html>
<head>
<title>1.html</title>
<meta name="keywords" content="keyword1,keyword2,keyword3">
<meta name="description" content="this is my page">
<meta name="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/jquery-1.11.1.js"></script>
<script type="text/javascript">
function f1(){
$('#t1 tbody tr:even').css('background-color','red');
$('#t1 tbody tr:odd').css('background-color','yellow');
}
function f2(){
$('tbody tr:contains(4)').css('background-color','#005500');
}
function f3(){
$('#t1 tbody tr:eq(1) td:eq(1)').css('background-color','#550055');
}
</script>
</head>
<body οnlοad="f1();" style="font-size:30px;">
员工信息
<table id = "t1" cellpadding="0" cellspacing="0" width="60%" border="1">
<thead><tr><td>name</td><td>salary</td><td>age</td></tr></thead>
<tbody> <tr><td>1</td><td>100</td><td>100</td></tr></tbody>
<tbody> <tr><td>2</td><td>200</td><td>100</td></tr></tbody>
<tbody> <tr><td>3</td><td>300</td><td>100</td></tr></tbody>
<tbody> <tr><td>4</td><td>400</td><td>100</td></tr></tbody>
<tbody> <tr><td>5</td><td>500</td><td>100</td></tr></tbody>
</table>
<input type="button" value="2" οnclick="f2();"/>
<input type="button" value="3" οnclick="f3();"/>
</body>
</html>
dom 操作
1查询
利用选择器找到节点之后 可以获取节点的html内容,文本内容属性值 value值
html() innerHTML 包含节点之间的所有内容
text() innerText 只有文本
attr() 访问某个属性
val() value 属性值
也可以修改
2创建
$(html)
3插入节点
append(); 作为最后一个孩子
prepend() 在每个匹配的元素之后插入内容
after() 在每个匹配的元素之后插入内容
before()在每个匹配的元素之前插入内容
4删除节点
remove()
remove(selector)
empty() 清空节点
5数据与行为分离
将javascript代码写到 .js 文件里面, 然后在html 文件中引入相应的js文件方便维护
$(fn);
fn是一个函数 常用 匿名函数
$(function(){
//当整个页面加载完毕后。就会执行这里的代码
});
复制节点
clone()
clone(true) 是复制的节点也具有行为 将事件处理代码一块复制
属性操作
读取 attr('')
设置 attr('','')
设置多个 attr({"class":"s1","style":"color:red"});
删除removeAttr('')
样式操作
获取和设置attr("class","")
追加addClass('')
是否含有hasClass('')
移除 removeClass('') removeClass('s1 s2') removeClass()//删除所有
切换样式toggleClass 有这个就删除,没有就添加
遍历节点
children() 只考虑子元素,不考虑其他后代元素 () 中可以添加选择器
next() 下一个
prev() 上一个
siblings() 其他的兄弟
find(expr) 查找
parent() 遍历
mvc
模型封装业务逻辑 加工数据
视图表示逻辑展现数据
控制器协调 模型和视图 视图 向控制器发请求 由控制器调用相应的模型来处理,模型返回的处理结果也要给控制器 有控制器选择合适的视图来展现
模型:java类
视图:jsp 或者 模板
控制器:servlet 或者filter
模型复用 维护 方便测试
增加难度 代码量加大