1.JSP
JSP——Java Server Page:Java服务器页面,在HTML页面中编写Java代码的页面。
绝大多数时候,我们希望响应的不是简简单单一句话,而是一个页面,我们用PrintWriter对象去写一个页面也是可以的,但缺点太明显。
所以直接返回一个页面,并且能够写Java代码就能大大简化我们的开发,这就是——JSP
当前不提倡在jsp页面中写Java代码,代替使用EL表达式。
JSP是简化Servlet编写的一种技术,它将Java代码和HTML语句混合在同一个文件中编写,只对网页中的需要动态产生的内容采用Java代码来编写,而对固定不变的静态内容采用普通静态HTML页面的方式编写。
2.JSP的认识
在JSP页面中编写的Java代码需要嵌套在<% 和 %> 中,嵌套在<% 和 %>之间的Java代码被称为脚本片段,没有嵌套在<% 和 %>之间的内容被称为JSP的模板元素。
WEB容器(WEB服务器)(Servlet引擎)(Tomcat)接收到以 .jsp为扩展名的URL的访问请求时,它将把该访问请求交给JSP引擎(Tomcat)去处理。
每个JSP页面在第一次被访问时,JSP引擎将它翻译成一个Servlet源程序(Java类),接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器(Servlet引擎)(Tomcat)像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序——JSP本质上就是一个Servlet。
当Tomcat服务器一运行index.jsp的页面时,此时的index.jsp将会翻译成index_jsp.java类,当运行成功后index_jsp.java类会编译成index_jsp.class。 将index_jsp.java类拖拽到idea中发现,该Java类继承了HttpJspBase,而HttpJspBase是HttpServlet的子类,所以可以说明JSP本质上就是一个Servlet。
3.JSP中九个隐式对象
隐式对象(或隐含对象):在JSP当中我们没有手动声明创建,但实际存在,可以直接使用的对象。
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;
//还有request和response以及exception对象,一共9个
(1)request:客户端的请求信息被封装在request对象中,通过它才能了解用户的需求。然后做出响应
(2)response:包含了响应客户请求的有关信息,但在JSP中使用很少
(3)pageContext:页面的上下文,是PageContext的一个对象,可以从该对象中获取到其它8个隐含对象,也可以获取到当前页面的其它信息
(4)session:指的是客户端与服务器端的一次会话,从客户端连到服务器端的一个WebApplication开始,直到客户端与服务器端断开连接为止
(5)application:代表当前web应用,是ServletContext对象,能实现用户间数据的共享,可存放全局变量,它开始于服务器的启动,直到服务器的关闭,在此期间,此对象一直存在;这样在用户的前后连接或不同客户之间的连接中,可以对此对象的同一属性进行操作;在任何地方对此对象属性的操作,都将影响到其它用户对此的访问。服务器的启动和关闭决定了application对象的生命周期
(6)config:当前JSP对应的Servlet的ServletConfig对象,可获取该Servlet的初始化参数(开发时基本不用),需要通过映射的地址才可以
(7)out:JspWriter对象,调用out.println()可以直接把字符串打印到浏览器上
(8)page:page对象就是指向当前JSP页面本身,类型为Object,有点类似于类中的this,几乎不使用
(9)exception:该对象是一个例外对象,只有页面是一个错误页面,即isErrorPage设置为true的时候(默认为false)才能使用,否则无法编译
注意:JSP可以放置在WEB应用程序中的除了WEB-INF及其子目录外的其它任何目录中
4.JSP模板元素
JSP页面中的静态HTML内容称之为JSP模板元素(比如html,body等等),在静态的HTML内容之中可以嵌套JSP的其他各种元素来产生动态内容和执行业务逻辑。
JSP模板元素定义了网页的基本骨架,即定义了页面的结构和外观。
5.JSP表达式
JSP表达式(expression)提供了将一个java变量或表达式的计算结果输出到客户端的简化方式,它将要输出的变量或表达式直接封存在<%= 和 %>之中。
在JSP表达式中嵌套的变量或表达式后面不能有分号。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
Date date = new Date();
%>
<%= date %>
</body>
</html>
6.JSP脚本片段
像片段一样的JSP表达式,嵌套在<% 和 %>中,必须全部是符合java语法的语句。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
String username = request.getParameter("username");
response.getWriter().println("Hello:"+username);
%>
</body>
</html>
7.**页面间跳转的2种方式---请求转发和请求重定向
(1)请求转发
请求转发需要借助于一个接口,RequestDispatcher接口,利用这个接口的forward方法实现请求转发
第一种方法(带有EL表达式${ })
前端请求页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="login2" method="post">
user:<input type="text" name="username">
password:<input type="password" name="password">
<input type="submit">
</form>
</body>
</html>
Servlet处理请求
package servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "Login2Servlet" , urlPatterns = "/login2")
public class Login2Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理请求中文乱码问题
request.setCharacterEncoding("utf-8");
//处理回应中文乱码问题
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
request.setAttribute("user_name" , username);
request.setAttribute("psd" , password);
if(username.equals("zhangsan")) {
RequestDispatcher dispatcher = request.getRequestDispatcher("/success.jsp");
dispatcher.forward(request , response);
}else{
// RequestDispatcher dispatcher = request.getRequestDispatcher("error.jsp");
// dispatcher.forward(request , response);
request.getRequestDispatcher("/error.jsp").forward(request , response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
body{
color:green;
}
</style>
</head>
<body>
<%
String username = (String)request.getAttribute("user_name");
%>
<%=username%>
登录成功
${user_name}
登录成功
你的密码是${psd}吧
</body>
</html>
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
body{
color: red;
}
</style>
</head>
<body>
${user_name}
登录失败
你的密码是${psd}吧
</body>
</html>
第二种方法,用对象进行封装和传递参数(带有EL表达式${ })
java类
package domain;
public class UserInfo {
private String username;
private String password;
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;
}
}
前端请求页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="login2" method="post">
user:<input type="text" name="username">
password:<input type="password" name="password">
<input type="submit">
</form>
</body>
</html>
Servlet处理请求
package servlet;
import domain.UserInfo;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "Login2Servlet" , urlPatterns = "/login2")
public class Login2Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理请求中文乱码问题
request.setCharacterEncoding("utf-8");
//处理回应中文乱码问题
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
UserInfo userInfo = new UserInfo();
userInfo.setUsername(username);
userInfo.setPassword(password);
if(username.equals("zhangsan")) {
request.setAttribute("user_info" , userInfo);
RequestDispatcher dispatcher = request.getRequestDispatcher("/success.jsp");
dispatcher.forward(request , response);
}else{
request.setAttribute("user_info" , userInfo);
// RequestDispatcher dispatcher = request.getRequestDispatcher("error.jsp");
// dispatcher.forward(request , response);
request.getRequestDispatcher("/error.jsp").forward(request , response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
body{
color:green;
}
</style>
</head>
<body>
<%
UserInfo userInfo = (UserInfo) request.getAttribute("user_info");
%>
<%=userInfo.getUsername()%>
登录成功
${user_info.username}
登录成功
你的密码是${user_info.password}吧
</body>
</html>
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
body{
color: red;
}
</style>
</head>
<body>
${user_info.username}
登录失败
你的密码是${user_info.password}吧
</body>
</html>
(2)请求重定向
用HttpServletResponse的sendRedirect方法实现请求重定向
请求重定向既可以返回一个jsp还可以返回一个Servlet
java类
package domain;
public class UserInfo {
private String username;
private String password;
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;
}
}
前端请求界面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="login2" method="post">
user:<input type="text" name="username">
password:<input type="password" name="password">
<input type="submit">
</form>
</body>
</html>
Servlet处理请求
package servlet;
import domain.UserInfo;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "Login2Servlet" , urlPatterns = "/login2")
public class Login2Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理请求中文乱码问题
request.setCharacterEncoding("utf-8");
//处理回应中文乱码问题
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
UserInfo userInfo = new UserInfo();
userInfo.setUsername(username);
userInfo.setPassword(password);
if(username.equals("zhangsan")) {
request.setAttribute("user_info" , userInfo);
response.sendRedirect("/test");
}else{
request.setAttribute("user_info" , userInfo);
response.sendRedirect("/test");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
重定向返回一个Servlet或者Jsp 这里返回的是Servlet
重定向时 发送的请求一定是Get请求
package servlet;
import domain.UserInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "TestServlet" , urlPatterns = "/test")
public class TestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("TestServlet doGet");
response.setContentType("text/html;charset = UTF-8");
PrintWriter printWriter = response.getWriter();
printWriter.println("\r\n");
printWriter.println("<html>\r\n");
printWriter.println("<head>\r\n");
printWriter.println(" <title>Title</title>\r\n");
printWriter.println("</head>\r\n");
printWriter.println("<body>\r\n");
printWriter.println("<h2>编程语言</h2>\r\n");
printWriter.println("<ul>\r\n");
printWriter.println(" <li>php</li>\r\n");
printWriter.println(" <li>c++</li>\r\n");
printWriter.println(" <li>java</li>\r\n");
printWriter.println("</ul>\r\n");
printWriter.println("</body>\r\n");
printWriter.println("</html>\r\n");
}
}
注意:貌似重定向与请求转发没什么区别,但实际区别非常之大。
观察用请求转发和请求重定向时地址栏的变化:请求转发时地址栏没变;请求重定向时地址栏变化了。
说明一个重要问题(本质区别):
请求转发只发出了一个请求
请求重定向发出了俩个请求
请求转发和请求重定向的目标可以是一个Servlet也可以是一个jsp
request.getRequestDispatcher("/XXXServlet").forward(request,response); 和 response.sendRedirect("/XXXServlet");只能在doGet或doPost方法中调用一次,即,在doGet或doPost方法中,只能转发或重定向到一个页面,不能到多个页面。
8.EL表达式
EL能够极大的简化我们的开发
EL全名为Expression Language,它原本是JSTL1.0为方便存取数据所自定义的语言。当时EL只能在JSTL标签中使用。到了JSP2.0之后,EL已经正式纳入成为标准规范之一。
语法
EL语法很简单,它最大的特点就是使用上很方便。接下来介绍EL主要的语法结构
${sessionAttr} // 对应的值是字符串
${user.name} // 通过user对象.对象属性的方式
所有EL都是以 ${ 起始、以 } 为结尾的。
EL隐含对象
如果我们在request和application中设置了同名属性怎么办?
与范围有关的隐含对象
applicationScope
sessionScope
requestScope
pageScope
请求界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="login.do">登录</a>
</body>
</html>
servlet处理请求
package servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "LoginServlet" , urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("user" , "lisi");
request.getSession().setAttribute("user" , "zhangsan");
request.getRequestDispatcher("user.jsp").forward(request , response);
}
}
转发页面 user.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--使得输出结果为zhangsan--%>
${sessionScope.user}
</body>
</html>
9.属性相关方法
(1)设置属性:void setAttribute(String name , Object o)
(2)获取指定属性:Object getAttribute(String name)
能够使用这些方法的对象有4个:pageContext,request,session,application---->这4个对象也称为域对象。
10.**域对象
域:2个维度:一份数据可以在多少个页面共享,可以在多长的时间范围内共享。
pageContext:属性的作用范围仅限于当前servlet或JSP页面
request:属性的作用范围仅限于同一个请求(考虑页面转发的情况)
session:属性的作用范围限于一次会话(浏览器打开直到关闭,称为一次会话,前提是在此期间会话没有失效),数据是用户独立的
application:属性的作用范围限于当前WEB应用,是范围最大的属性作用范围,只要在一处设置属性,在其他各处的JSP或Servlet中都可以获取,直到服务器关闭。数据所有用户共享。
package servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet(name = "ServletA", urlPatterns = "/aaa")
public class ServletA extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// pageContext代表的是当前页面(本servlet),平时几乎不用
javax.servlet.jsp.PageContext pageContext = javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this, request, response, null
, true, 8192, true);
pageContext.setAttribute("pageAttr", "pageValue");
// request域,代表一次请求,如果存在转发的情况,转发经过的各个页面,都算是本次请求
request.setAttribute("reqAttr", "reqValue");
// session会话作用域,从用户打开浏览器,到关闭浏览器之间
HttpSession httpSession = request.getSession();
httpSession.setAttribute("sessionAttr", "sessionValue");
// application应用作用域,直到Tomcat服务器关闭,卸载本网站项目
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("appAttr", "appValue");
// 转发到 ServletB
// request.getRequestDispatcher("/bbb").forward(request , response);
//重定向到 ServletB
response.sendRedirect("/bbb");
}
}
package servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet(name = "ServletB", urlPatterns = "/bbb")
public class ServletB extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
javax.servlet.jsp.PageContext pageContext = javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this, request, response, null
, true, 8192, true);
System.out.println(pageContext.getAttribute("pageAttr"));
System.out.println(request.getAttribute("reqAttr"));
HttpSession httpSession = request.getSession();
System.out.println(httpSession.getAttribute("sessionAttr"));
ServletContext servletContext = request.getServletContext();
System.out.println(servletContext.getAttribute("appAttr"));
}
}
servlet中通过getAttribute(String name),获取指定属性。而jsp中使用EL表达式。
11.MVC模式
MVC
model(模型) : DataBase
view(视图):jsp页面
controller(控制器):Servlet