JSP相关内容
现有问题
通过Servlet响应客户端页面,有什么缺点?
- 显示代码麻烦。
- 代码维护麻烦。
Servlet不适合展示复杂页面数据。
Servlet的作用:处理客户端请求,调用业务逻辑层,转发和重定向。
什么是JSP?
概念:
- JSP全称:Java Server Page,Java服务器页面。
- 和Servlet一样,是SUN公司定义的一种动态网页开发技术。
特点:
- 基于HTML模版,可以在HTML模版嵌入Java代码和JSP标签。
作用:
- 适用于复杂的页面显示。
JSP语法
JSP页面
- 可以包含指令,脚本、脚本表达式、声明、静态内容等。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp基本语法</title>
</head>
<body>
<h2>jsp基本语法</h2>
<ul>
<li> 1.指令:page include taglib</li>
<li> 2.脚本:java语句 局部变量
<%
System.out.println("jsp");
String name = "lz";
out.print(name);
%>
</li>
<li> 3.脚本表达式:java代码 输出数据
<%=name%>
</li>
<li> 4.声明:方法 成员变量
<%!
public String toUpperCase(String s) {
return s.toUpperCase();
}
%>
<%=toUpperCase(name)%>
</li>
<li> 5.静态内容 : html、css、js</li>
<li> 6.JSP注释
<%-- jsp注释(不显示,既可以注释html,又可以java) --%>
<!-- html注释(显示) -->
<%--java中的注释 (不显示)
单行注释// 多行注释 /**/
--%>
</li>
</ul>
</body>
</html>
JSP与Servlet
关系:
- JSP文件在容器中会转换成Servlet。
- JSP是对Servlet的一种高级封装。
- 本质还是Servlet。
从源码角度解释:
运行tomcat,进入tomcat运行后的上述地址文件夹。其中文件有:
- conf -> Catalina -> localhost中存放了虚拟路径的配置文件
- logs 日志文件
- work工作目录 -> Catalina -> localhost -> 项目目录 进入这个目录
打开jsp基本语法_jsp.java文件:
[wppay]
看到类的定义如下省略了类主体和两个实现,这里我们暂时不分析这个文件:
public final class JSP基本语法_jsp extends org.apache.jasper.runtime.HttpJspBase
在tomcat源码文件中找到HttpJspBase这个类,如下:
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage
可以看到我们写的页面继承了HttpJspBase,而HttpJspBase又继承了HttpServlet。
也就是说我们写的JSP就是Servlet。
好了,我们再回看jsp基本语法_jsp.java这个文件,文件内容如下,可以简单看下,后面会有分析。
public final class JSP基本语法_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
public String toUpperCase(String s) {
return s.toUpperCase();
}
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 static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
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 java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
return;
}
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("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>jsp基本语法</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("<h2>jsp基本语法</h2>\r\n");
out.write("<ul>\r\n");
out.write(" <li> 指令:page include taglib</li>\r\n");
out.write(" <li> 脚本:java语句 局部变量\r\n");
out.write(" ");
System.out.println("jsp");
String name = "lz";
out.print(name);
out.write("\r\n");
out.write(" </li>\r\n");
out.write(" <li> 脚本表达式:java代码 输出数据\r\n");
out.write(" ");
out.print(name);
out.write("\r\n");
out.write(" </li>\r\n");
out.write(" <li> 声明:方法 成员变量\r\n");
out.write(" ");
out.write("\r\n");
out.write(" ");
out.print(toUpperCase(name));
out.write("\r\n");
out.write(" </li>\r\n");
out.write(" <li> 静态内容</li>\r\n");
out.write(" <li>JSP注释\r\n");
out.write(" ");
out.write("\r\n");
out.write(" <!-- html注释 -->\r\n");
out.write(" ");
out.write("\r\n");
out.write(" </li>\r\n");
out.write("</ul>\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 {
if (response.isCommitted()) {
out.flush();
} else {
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实现了不需要我们手动拼接前端页面,实现自动拼接out.write()。声明的方法、变量都可以在里面找到以java的形式。
这个JSP基本语法_jsp里面主要的方法是:
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
那_jspService这个方法有什么时候调用呢?回到我们的tomcat源码文件中的HttpJspBase这个类。里面有这样的方法:
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
private static final long serialVersionUID = 1L;
protected HttpJspBase() {
}
@Override
public final void init(ServletConfig config)
throws ServletException
{
super.init(config);
jspInit();
_jspInit();
}
@Override
public String getServletInfo() {
return Localizer.getMessage("jsp.engine.info", Constants.SPEC_VERSION);
}
@Override
public final void destroy() {
jspDestroy();
_jspDestroy();
}
/**
* Entry point into service.
*/
@Override
public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
_jspService(request, response);
}
@Override
public void jspInit() {
}
public void _jspInit() {
}
@Override
public void jspDestroy() {
}
protected void _jspDestroy() {
}
@Override
public abstract void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException;
}
其中_jspService是一个抽象方法
@Override
public abstract void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException;
说明子类的_jspService把父类的_jspService进行了重写。又有下面的service方法:
@Override
public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
_jspService(request, response);
}
可以看到service方法调用了抽象方法_jspService,但_jspService方法被子类JSP基本语法_jsp给重写了,实际调用的是子类JSP基本语法_jsp重写后的方法。
那 service 又是什么时候会被调用呢?被忘了HttpJspBase类继承了HttpServlet。
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage
在被请求后会调用。(Servlet的生命周期)
再看两者的关系,就可以明白确实如此:
- JSP文件在容器中会转换成Servlet。
- JSP是对Servlet的一种高级封装。
- 本质还是Servlet。
区别:
- JSP可以很方便的编写或者修改HTML网页而不用去面对大量的println语句。
JSP实现原理
Tomcat里面有个JSP引擎会将xxx.jsp转换成Java代码,进而编译成.class文件运行,最终将运行结果通过response响应给客户端。
JSP指令
JSP指令用来设置与整个JSP页面相关的属性。
page指令
page指令:
- 为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令。
- 语法:<%@ page attribute1="value1" attribute2="value2" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="message.jsp"
isErrorPage="true" session="false" pageEncoding="utf-8" buffer="8kb" %>
<html>
<head>
<title>page指令</title>
</head>
<body>
<h2>page指令</h2>
<ul>
<li>contentType:设置页面的MIME类型和字符编码格式</li>
<li>language:页面的语言 默认java</li>
<li>import:导入类</li>
<li>errorPage:当页面发送错误时跳转的页面</li>
<li>isErrorPage:指定当前页面是否可以作为另一个JSP页面的错误处理页面</li>
<li>session:是否创建session对象,默认为true</li>
<li>pageEncoding:指定jsp页面本身编码</li>
<li>buffer:页面的缓冲区 默认8kb</li>
</ul>
<%
ArrayList<Object> list = new ArrayList<>();
//int i = 10 / 0;
%>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
<title>提示页面</title>
</head>
<body>
出现了错误.
<%-- isErrorPage="true" 不写下面的式子获取不到--%>
<%
System.out.println(exception.getMessage());
%>
</body>
</html>
include指令
- 通过include指令来包含其他文件。
- 被包含的文件可以是JSP文件、HTML文件或文本文件。
- 包含的文件就好像是当前JSP文件的一部分,会被同时编译执行。
- include指令包含称为静态包含。
- 包含的内容里面不要有<html>等标签直接是内容
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>指令include</title>
</head>
<body>
<%@include file="header.jsp"%>
<h3>include:实现静态包含,把另一个页面中的内容直接复制到当前页面</h3>
<%@include file="footer.jsp"%>
</body>
</html>
header.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div>
页面头部
</div>
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div>
页面尾部
</div>
对应的java代码如下:
taglib指令
- 引入JSP的标准标签库。
- 语法:<%@ taglib uri="外部标签库路径" prefix="前缀" %>
内置的动作标签
动作标签指的是JSP页面在运行期间执行的命令。
- jsp:include:
- 动作元素会将外部文件输出结果包含在JSP中。
- 动作元素称为
动态包含
。
<jsp:include page="header.jsp"></jsp:include>
注意:
- include指令是将外部文件的输出代码复制到了当前JSP文件中。
- 而jsp:include动作不同,是将外部文件的执行结果引入到了当前JSP文件中。
对应的java代码如下:
再从生成的文件来看,include指令不会生成header.jsp和footer.jsp文件,但是<jsp:include>会生成。
- jsp:useBean:
- 用来创建一个将在JSP页面中使用的JavaBean。
User类
public class User {
private String name;
private int age;
........
}
手工创建对象:
<%
User user1 = new User("lz", 22);
%>
使用jsp:useBean:
<jsp:useBean id="user" class="com.qf.domain.User"></jsp:useBean>
输出:
<%=user.toString()%>
对应的java代码:
- jsp:setProperty:
- 在jsp:useBean元素之后使用jsp:setProperty进行属性的赋值。
<jsp:setProperty name="user" property="name" value="wl"></jsp:setProperty>
<jsp:setProperty name="user" property="age" value="20"></jsp:setProperty>
对应的java代码:
- jsp:getProperty:
- jsp:getProperty动作获取指定Bean属性的值,转换成字符串,然后输出。
<jsp:getProperty name="user" property="name"/>
- jsp:forward:
- jsp:forward动作把请求转到另外的页面。
- jsp:param:
- 在转发动作内部使用,做参数传递。
<%
request.setCharacterEncoding("utf-8");
//之前转发
//request.getRequestDispatcher("/index.jsp").forward(request,reponse);
%>
<jsp:forward page="index.jsp">
<jsp:param name="address" value="北京"/>
</jsp:forward>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
首页
<%
String address = request.getParameter("address");
out.print(address);
%>
</body>
</html>
内置对象(重点)
JSP自动创建的对象,可以直接使用。
这九个对象在什么地方创建好的?可以看JSP与Servlet的关系我们找到了jsp转换成的java文件,其中这八个对象就定义在_jspService里面。
少了一个exception,将jsp代码修改如下运行tomcat重新找到那个文件就会找到:
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
out 对象
- 页面中输出内容使用out对象。
<%
//以下四句在不加out.flush();情况下
//PrintWriter跑到最上面去了, 因为out有8kb的缓存,PrintWriter的直接进入了响应体
//而out写完后等页面自动刷新后才写入响应体,加 out.flush();进行刷入
out.print("测试out输出内容到界面!<br/>");
out.flush();
PrintWriter out2 = response.getWriter();
out2.print("测试另一种输出方式<br/>");
%>
jsp的out和getWriter()方法的区别
- out是JspWriter类型,getWriter()是PrintWriter类型。
- out输出到8k缓冲区中,没有写到response中,getWriter()直接写到response中。
- out一般用在jsp中,getWriter()用在Servlet中
- 如果混用,要及时刷新缓冲区。
pageContext 对象
- pageContext:
- 代表整个JSP页面,当前页面的作用域对象,只在当前页面中使用。
- 作用:
- 作为域(容器)对象。
- 用于获取其他八个内置对象。
- 操作当前页面域
- pageContext.setAttribute("name",value);
- pageContext.getAttribute("name");
- pageContext.removeAttribute("name");
String name = "lz";
pageContext.setAttribute("username", name);
String username = (String) pageContext.getAttribute("username");
out.print(username);
pageContext.removeAttribute("username");
- 操作其他域对象:
- pageContext.setAttribute("name",value,域范围)。
- 域范围:
- REQUEST_SCOPE
- SESSION_SCOPE
- APPLICATION_SCOPE
- PAGE_SCOPE
<%
//操作其他三个与对象 request response application(ServletContext)
pageContext.setAttribute("requestData", "beijing", PageContext.REQUEST_SCOPE);
pageContext.setAttribute("sessionData", "wl", PageContext.SESSION_SCOPE);
pageContext.setAttribute("applicationData", "lz", PageContext.APPLICATION_SCOPE);
//做一个转发,在data.jsp页面接收数据打印
request.getRequestDispatcher("data.jsp").forward(request, response);
%>
data.jsp
<%
String requestData = (String) request.getAttribute("requestData");
String sessionData = (String) session.getAttribute("sessionData");
String applicationData = (String) application.getAttribute("applicationData");
out.print(requestData);
out.print(sessionData);
out.print(applicationData);
%>
<%
//移除数据 page request response application
//不用指定域,它会从这四个域中挨个移除
pageContext.removeAttribute("requestData");
pageContext.removeAttribute("sessionData");
pageContext.removeAttribute("applicationData");
%>
- pageContext.findAttribute("name");
- 从四个域中依次查找:从pageContext、request、session、application,找到为止。
- 如果都没有则返回null。
<%
//查找数据依次从 page -> request -> response -> application
//中查找数据,pageContext.findAttribute("");
String requestData = (String) pageContext.findAttribute("requestData");
String sessionData = (String) pageContext.findAttribute("sessionData");
String applicationData = (String) pageContext.findAttribute("applicationData");
%>
四大域对象
四大作用域对象,存储和获取数据的方式一样,不同的是取值的范围有差别。
使用原则:能用小范围,就不使用大范围。
EL表达式
概念:
- EL使JSP写起来更简单、简洁。主要用于获取作用域中的数据。减少在JSP中java的代码。
- java代码和前端代码柔和在一起也不利于代码的维护。
作用:
- 用于替换:域对象.getAttribute("name")。
应用:
- ${scope.name} 获取具体某个作用域中的数据。
- ${name} 获取作用域中的数据,四个域逐级查找。
EL获取简单数据
从域中取数据前,必须先数据放入域中。
获取简单的数据:
<%
pageContext.setAttribute("username", "lz");
%>
<%--不使用 EL表达式--%>
<%=pageContext.findAttribute("username")%>
<%--使用 EL表达式--%>
<%--${"username"} 打印username--%>
${username}
获取对象的属性
User
public class User {
private String name;
private int age;
private Address address;
}
Address
public class Address {
private String address;
}
<%
User user = new User("wl", 20);
pageContext.setAttribute("user", user);
user.setAddress(new Address("泰国"));
pageContext.setAttribute("user", user);
%>
${user.name}
${user.age}
${user.address.address}
获取数组、List\Map集合的内容:
<%
int[] arr = {1, 2, 3, 4};
pageContext.setAttribute("arr", arr);
ArrayList<Address> list = new ArrayList<>();
list.add(new Address("beijing"));
pageContext.setAttribute("list", list);
HashMap<String, String> map = new HashMap<>();
map.put("cn", "中国");
pageContext.setAttribute("map", map);
%>
${arr[0]}
${list[0]}
${list.get(0)}
${map['cn']}
${map.cn}
${map.get('cn')}
EL和JSP脚本的区别
- <%=request.getAttribute(name) %>,没有找到返回null
- ${name},没找到返回""。
EL运算符
<%
pageContext.setAttribute("address1", new String("北京"));
pageContext.setAttribute("address2", new String("北京"));
pageContext.setAttribute("address3", "");
pageContext.setAttribute("list", new ArrayList<>());
%>
<h1>EL表达式运算符的使用</h1>
<h2>算术运算符</h2>
${100+200}<br/>
${100-20}<br/>
${100*5}<br/>
${10/4}<br/>
${10%3}<br/>
<h2>关系运算符</h2>
${10==15}<br/>
${"abc"=="abc"}<br/>
${"abc" eq "abc"}<br/>
<!-- true -->
${address1==address2}<br/>
${10>8}<br/>
${10 gt 8}<br/>
${10<8}<br/>
${10 lt 8}<br/>
${10 >=8}<br/>
${10 ge 8}<br/>
${10 <=8}<br/>
${10 le 8}
<h2>逻辑运算符</h2>
${true&&false}<br/>
${true||false}<br/>
${!true}<br/>
<h2>三目运算符</h2>
${user==null ? "没有登录":user.username}<br/>
${flag==1?"激活":"没有激活"}<br/>
<h2>empty:判断为空 (1)对象为null (2)字符串空 null or "" (3)集合没有元素</h2>
${empty user? "没有登录":user.username}<br/>
<!-- true -->
${empty address3}<br/>
<!-- true -->
${empty list}
隐式对象
EL 表达式语言定义了11个隐式对象。
<h1>EL表达式的11个隐式对象</h1>
<ul>
<li>pageScope:pageContext域里的集合</li>
<li>requestScope:request域</li>
<li>sessionScope:session域</li>
<li>applicationScope:application域</li>
<li>param:request的参数</li>
<li>paramValues: request的参数</li>
<li>header:请求头</li>
<li>headerValues:请求头 数组</li>
<li>initParams:ServletContext参数</li>
<li>cookie:获取cookie</li>
<li>pageContext:页面上下文对象本身</li>
</ul>
前四个使用格式:
<%
pageContext.setAttribute("username", "hello");
%>
${pageScope.username}<br/>
param:获取request中的参数
<%
String gender = request.getParameter("gender");
out.println(gender);
%>
${param.gender}<br/>
paramValues: 获取多个request的参数
${paramValues.hobby[0]}
${paramValues.hobby[1]}
header:获取请求头里的参数
${header.accept}等
initParams:ServletContext参数
web.xml
<!--全局ServletContext参数-->
<context-param>
<param-name>appName</param-name>
<param-value>我的淘宝</param-value>
</context-param>
${initParam.appName}
cookie:获取cookie
${cookie.JSESSIONID.name}... ${cookie.JSESSIONID.value}
pageContext:页面上下文对象本身
${pageContext.request}<br/>
<%--${pageContext.response}<br/>--%>
<%--${pageContext.session}<br/>--%>
<%--${pageContext.servletContext}<br/>--%>
<%--${pageContext.servletConfig}<br/>--%>
<%--${pageContext.out}<br/>--%>
<%--${pageContext.exception}<br/>--%>
<%--${pageContext.page}<br/>--%>
作用 作为参数传递
public class JspUtils {
public static void process(PageContext pageContext){
}
}
获得应用上下文路径(/web1)${pageContext.request.contextPath}
路径分类
问题描述:在项目web目录下创建images文件夹,放入两张照片,在web目录下
创建一个JSP页面引入头部、尾部
header.jsp于footer.jsp中分别添加图片
启动tomcat这时可以正常访问,但若将创建的JSP文件访问非web根目录下的其他文件夹中,这时访问不到图片,运行结果网页源码如下图。
可以看到地址是相对路径在当前目录下寻找,而图片在他的上一级目录中。
那怎么办呢? 继续看下去吧。
- 1.使用绝对路径: 用在不同网站之间的跳转。
- 比如:http://localhost:8080/images/1.jpg
- 有些参数没有必要去写
- 2.相对路径: 用在同一个主机或域名中, aaa/1.jpg。
- 如果页面比较多,并且在不同的目录下,并且使用框架或模板,会出现混乱。
- 相对就会有参照,不同的页面可能参照点不同,会出现找到不到的情况
- 3.根路径: 特殊的相对路径,相对整个网站的根目录(域名或主机名)。
- 如果在浏览器中使用,/ 表示主机名或域名,比如http://localhost:8080/
- 如果在服务器中使用, / 表示上下文路径,比如/myweb
红圈部分表示http://localhost:8080/web1 ,其中web1是你tomcat自己配置的。所以固定性是不好的选择,需要动态的获取你配置的路径:
前面不需要再写/,因为返回的就是 /web1这种格式。
转发:
//转发时路径写上/ , /表示web应用上下文路径,/的前面已经有了 day40web1
//在服务器转发,服务器是知道应用在哪里
request.getRequestDispatcher("/index.jsp").forward(request,response );
重定向
//1.相对路径
response.sendRedirect("index.jsp");
//2.根路径
//重定向时路径写/ , /表示主机名或域名 localhost:8080
//没有项目名所以找不到
response.sendRedirect("/index.jsp");
解决方法:写上项目名
response.sendRedirect("day40web1/index.jsp");
同样不能写死:
response.sendRedirect(request.getContextPath()+"/index.jsp");
EL问题?
- EL主要用于域对象获取数据。
- EL不存在流程控制,比如判断。
- EL对于集合只能元素单独访问,不能实现遍历操作,比如循环。
<%
List<String> list=new ArrayList();
list.add("华为");
list.add("苹果");
list.add("小米");
list.add("vivo");
list.add("oppo");
pageContext.setAttribute("list", list);
%>
${list[0]}<br/>
${list[1]}<br/>
${list[2]}<br/>
${list[3]}<br/>
${list[4]}<br/>
数据少还可以一个一个打印,但是多了就麻烦了。
JSTL
- JSP标准标签库:
- 是一个JSP标签集合。
- 是由JCP(Java Community Process)所制定的标准规范,它主要提供给Java Web开发人员一个标准通用的标签库,并由Apache的Jakarta小组来维护。
- 开发人员可以利用这些标签取代JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度。
Java Server Pages Standard Tag Library : JSTL标准标签库
作用:
- 可对EL获取到的数据进行逻辑操作。
- 与EL配合完成数据的展示。
JSTL不在tomcat中去maven仓库里找。添加完依赖后,在JSP页面中导入依赖:
<!-- prefix 前缀 可以自定义 -->
<!-- uri 统一资源标识符 -->
<!-- 核心内容 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- 格式化内容 -->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
set、out、remove
三个通用的标签:set、out、remove
set:向域中添加数据
<%--
set标签:
var:变量名
value:值
scope: 域范围 默认page
--%>
<c:set var="username" value="admin"></c:set>
<!-- 相当于 -->
<%
pageContext.setAttribute("username","admin");
%>
out:从域中获取数据
${username}<br/>
<%--
value:输出谁的值
--%>
<c:out value="${username}"></c:out><br/>
既然有了${},那为什么还要用<c:out>呢?当然是为了防止攻击。
<c:set var="myjs" value="<script>while(true){alert('点击我中奖了...')}</script>"></c:set>
${myjs}
<c:out value="${myjs}"></c:out>
当使用${myjs}会执行JS代码,而<c:out>显示的字符串。
这种攻击称为XSS攻击,跨站脚本攻击。扩展SQL注入。
remove:从域中删除数据
<%--
var: 删除的变量名
--%>
<c:remove var="username"></c:remove>
${username}
条件标签if
<c:if>标签判断表达式的值,如果表达式的值为true。
语法:<c:if test = "条件">< /c:if>
<c:if test="${10>8}">
<p>日照香炉生紫烟</p>
</c:if>
<c:if test="${empty user}">
没有登录
</c:if>
多分支标签choose
<c:choose>标签与多重if语句功能一样,用于在众多选项中做出选择。
<h2>3 多分支标签choose的使用</h2>
<c:set var="score" value="61"></c:set>
<c:choose>
<c:when test="${score>90}">优秀</c:when>
<c:when test="${score>80}">良秀</c:when>
<c:when test="${score>60}">一般</c:when>
<c:otherwise>
较差
</c:otherwise>
</c:choose>
迭代foreach标签
foreach封装了Java中的for,while,do-while循环。
语法:
<%
List<String> list=new ArrayList();
list.add("华为");
list.add("苹果");
list.add("小米");
list.add("vivo");
list.add("oppo");
pageContext.setAttribute("list", list);
%>
<h2>4 forEach标签的使用</h2>
<%--
items: 遍历的集合或数组
var:变量名
begin: 开始数字
end: 结束数字
step: 步长
varStaus: 变量状态
index:下标
count:个数
--%>
<c:forEach items="${list}" var="con" varStatus="vs">
${con}....${vs.index}...${vs.count}...${vs.first}....${vs.last}<br/>
</c:forEach>
<!-- 输出1-10 步长为2 -->
<c:forEach begin="0" end="10" var="n" step="2">
${n}<br/>
</c:forEach>
url标签
- <c:url>标签将URL格式化为一个字符串,然后存储在一个变量中。
- 自动重写URL,如果有中文自动编码。
- var属性用于存储格式化后的URL。
<c:url var="myurl" value="index.jsp?address=北京">
<c:param name="username" value="张三"></c:param>
</c:url>
<a href="${myurl}">跳转到首页</a>
fmt标签
fmt:formatDate 格式时间标签
<%
pageContext.setAttribute("bornDate", new Date());
%>
${bornDate}<br/>
<fmt:formatDate value="${bornDate}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate>
MVC模式
MVC与三层架构对应关系
- Web层对应MVC中的Controller(Servlet)和View(JSP、Html)
- 其他层都属于MVC中的Model
项目
- day41
- 事务转账
- CRUD操作
- 重复提交问题
- day42
- 分页
- 上传下载文件
- day43
- 过滤器
- 禁用浏览器缓存
- 过滤脏词
- 内容压缩
- day44
- 监听器
[/wppay]