1. jsp的介绍
JSP全名为Java Server Pages,中文名叫java服务器页面,本质是一个简化的Servlet设计,它是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。
它实现了Html语法中的java扩张(以 <%, %>形式)。JSP与Servlet一样,是在服务器端执行的。通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览。
jsp的作用:将内容的生成和显示进行分离
组成:html+java代码+jsp特殊标签
用JSP技术,Web页面开发人员可以使用HTML或者XML标识来设计和格式化最终页面,并使用JSP标识或者小脚本来生成页面上的动态内容
2. jsp的原理
jsp原理
上图描述的是一个jsp页面hello.jsp在服务器中处理的过程。
创建web工程day10,创建一个hello.jsp页面。
1.在浏览器中输入 http://localhost/day10/hello.jsp
2.服务器得到请求,会通过jsp引擎查找到hello.jsp页面
3.服务器将查找到的hello.jsp页面翻译成hello_jsp.java(其本质就是一个servlet)
4.jvm会将hello_jsp.java文件编译成hello_jsp.class
5.服务器运算hello_jsp.class文件
6.服务器生成响应结果
jsp执行原理
1.浏览器发送请求
2.服务器接受请求 处理请求
3.找到对应的jsp文件,然后将其转成java文件(hello_jsp.java)
4.jvm将java文件编译成class文件
5.服务器运行class文件,生成动态的内容,
6.将生成的内容转给服务器,服务器将响应信息返回给浏览器
7.浏览器解析
jsp对应java文件分析
上述是我们对于一个jsp运行的原理的简单分析,我们可以通过查看hello.jsp文件翻译后的.java文件来了解具体内容,生成的hello.jsp页面的java源文件存在于tomcat/work目录 下。
hello.jsp页面源代码
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>hello.jsp</title>
</head>
<body>
hello jsp
</body>
</html>
hello_jsp.java文件源代码
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;
public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=utf-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write(" <head> \r\n");
out.write(" <title>hello.jsp</title>\r\n");
out.write(" </head>\r\n");
out.write(" \r\n");
out.write(" <body>\r\n");
out.write(" hello jsp\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer(); } catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
通过上面的内容,大家会发现在jsp页面中的所有的html代码,最终都会被流写回到浏览器端,所以我们可以在浏览器上查看到jsp页面上的html内容
3. jsp的脚本与注释
jsp中三种脚本元素
有三个基本的脚本元素,作用是使JAVA代码可以直接插入到HTML代码中
声明标签
格式:<%! int a = 1; %>
作用:声明的变量在类的成员位置上
脚本片断
格式:<% int a = 1; out.println(a); %>
作用:内容会生成在_jspService()方法中
脚本表达式(输出脚本)
格式:<%="hello " + a%>
作用:它就相当于是out.println()将内容直接输出到页面中,内容会生成在_jspService()方法中注意表达式不能以分号结尾
jsp中的注释
在jsp页面中可以使用三种注释
可以使用html中注释
<!-- html的注释 -->在java源码和html源文件中都有
可以对jsp脚本内容使用java注释
//单行注释 /* 多行注释 */ / ** 文档注释 */ 在java源码中有,在html源文件中没有
可以使用jsp注释(推荐)
<%-- jsp注释 --%>在Java源码和html源文件中都没有
4. jsp与servlet的结合使用
Jsp实现登录案例
把昨天的登录操作使用jsp实现一下,流程稍稍改变一下:
创建数据库与表
CREATE DATABASE day10;
USE day10;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
PASSWORD VARCHAR(20),
email VARCHAR(50),
sex VARCHAR(20),
telephone VARCHAR(20),
introduce VARCHAR(200)
)
INSERT INTO USER VALUES(NULL,"tom","123","tom@itcast.cn","男","13888888888","good boy");
导入mysql驱动jar包
创建JdbcUtils工具类及jdbc.properties配置文件
创建User类
public class User {
private int id;
private String username;
private String password;
private String email;
private String sex;
private String telephone;
private String introduce;
get/set方法省略
}
login.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登陆窗口</title>
</head>
<body>
<%=request.getAttribute("loginmsg") %>
<form action="/day10/login" method="post">
USERNAME:<input type="text" name="username"><br>
PASSWORD:<input type="password" name="password"><br>
<input type="submit" value="登陆">
</form>
</body>
</html>
LoginServlet类
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.获取请求参数 username password
String username = request.getParameter("username");
String password = request.getParameter("password");
// 2.调用UserOperation类中的login方法
UserOperation uo = new UserOperation();
User user = uo.login(username, password);
//3.判断user是否为null来确定是否登陆成功
if(user==null){
//登陆失败,请求转发到login.jsp页面
request.setAttribute("loginmsg", "登陆失败");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}else{
//登陆成功,重定向到success.jsp
response.sendRedirect("/day10/success.jsp");
}
}
UserOperation操作类
public User login(String username, String password) {
User user = null;
// 1.定义sql语句
String sql = "select * from user where username=? and password=?";
// 2.查找数据库操作
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
// 2.1获取Connection对象
con = JdbcUtils.getConnection();
// 2.2 获取执行sql语句的PreparedStatement对象
pst = con.prepareStatement(sql);
// 2.3对占位符赋值
pst.setString(1, username);
pst.setString(2, password);
// 2.4执行sql获取ResultSet
rs = pst.executeQuery();
// 2.5操作ResultSet
if (rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setEmail(rs.getString("email"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setSex(rs.getString("sex"));
user.setTelephone(rs.getString("telephone"));
user.setIntroduce(rs.getString("introduce"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 2.6关闭资源
JdbcUtils.closeResource(con,pst,rs);
}
return user;
}
success.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登陆成功窗口</title>
</head>
<body>
<h1>登陆成功</h1>
</body>
</html>
首次进入登录页面的时候发现最上面显示为null,需要先判断一下loginmsg是否为空,在输出.这段代码用el表达式(明天讲)实现起来特别简单.
EL 全名为Expression Language
语法:${标识符}
常用功能:获取各种域中存储的数据
jsp写法:<%=request.getAttribute("loginmsg");>
el写法:${requestScope.loginmsg}
修改之后的login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登陆窗口</title>
</head>
<body>
${requestScope.loginmsg}
<form action="/day10/login" method="post">
USERNAME:<input type="text" name="username"><br>
PASSWORD:<input type="password" name="password"><br>
<input type="submit" value="登陆">
</form>
</body>
</html>
会话的介绍:
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话
会话的作用:
每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据。
例如:用户点击超链接通过一个servlet购买了一个商品,程序应该保存用户购买的商品,以便于用户点结帐servlet时,结帐servlet可以得到用户商品为用户结帐
会话技术会为两类
Cookie
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
Session
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
1. cookie的介绍
什么是cookie
Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。
Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,对于JSP而言也可以直接写入jsessionid,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等,服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。
cookie与http
cookie与http协议关系
Cookie是Http协议制定的,并不是Java语言独有的,PHT、.NET中也使用了cookie技术,因此只要是和HTTP协议相关,那么就可以使用cookie技术。
我们知道cookie是服务器创建的一个键值对,并保存在浏览器端。那么服务器是如何将cookie发送给浏览器的呢?
在服务器端先创建cookie,如 Cookie cookie=new Cookie(String name,String value),其中Cookie可以在javaeeAPI中查到的,详情可参考java_ee API。然后再通过response对象将cookie信息作为响应头发送到浏览器端。我们可以通过HttpWatch抓包工具查看响应信息,可以发现cookie是基于一个Set-Cookie响应头工作的,由于Set-Cookie响应头可以有多个,所以我们可以通过response.addHeader(String name,String value)方法发送Set-Cookie响应头,例如,有两个cookie,分别为one=aaa,two=bbb,其中one、two是cookie的名称,aaa、bbb是cookie的值。发送响应头如下所示:
response.addHeader(“Set-Cookie”,”one=aaa”);
response.addHeader(“Set-Cookie”,”two=bbb”);
当浏览器再次访问服务器时,会将cookie送还给服务器。那么浏览器是如何将cookie带给服务器的呢?其实通过Cookie请求头传递过去的。请求头Cookie与响应头Set-Cookie有区别,多个cookie对应多个Set-Cookie响应头,但是只对应一个Cookie请求头,格式为:Cookie:one=aaa; two=bbb。即多个cookie之间用分号和空格隔开。
需要注意的是:cookie是不能跨浏览器的。例如,张三首先使用IE浏览器访问服务器,服务器发送了一个cookie,这个cookie只会保存在IE浏览器,如果再使用火狐浏览器访问服务器,服务器会再发送一个cookie个火狐浏览器,在火狐浏览器中不能获取IE浏览器中的cookie,同理IE浏览器也获取不到火狐浏览器中的cookie。