一、jsp基础
1、jsp简介
JSP即:Java Server pages(java 服务器页面),运行在服务端的页面,是sun公司和多家大公司共同开发的一种动态网页技术,它是在静态的html文件中插入java代码段和jsp标签形成的文件,后缀为.jsp
当用户第一次访问jsp页面的时候,会由tomcat服务器生成一个servelt文件,用户访问的页面其实就是访问的这个servlet
idea下jsp访问产生的路径C:\Users\79894.IntelliJIdea2019.3\system\tomcat_javeWeb\work\Catalina\localhost\JSP\org\apache\jsp
里面的内容
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.5.65
* Generated at: 2021-04-30 06:43:43 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
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("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>$Title$</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write(" 这是一个jsp文件\n");
out.write(" </body>\n");
out.write("</html>\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);
}
}
}
2、jsp注释
1.html注释
<!--这是html注释,html注释会显示在页面的源代码上-->
2.jsp注释
<%--这是jsp注释,jsp注释不显示在前台页面上,仅仅显示在jsp源码中--%>
例如:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
这是一个jsp文件
<!--html注释-->
<%--jsp注释,仅在这个文件下显示--%>
</body>
</html>
前台页面源码:
<html>
<head>
<title>$Title$</title>
</head>
<body>f
这是一个jsp文件
<!--html注释-->
</body>
</html>
3、jsp的java代码块
语法:
<%
System.out.println("java代码块");
%>
注意:不可以写方法,变量名前不可以加访问修饰符,因为这些代码都会被插入到jsp_service()方法中
4、jsp的声明语句块
语法:
<%=
表达式,可以将变量写在这里,然后会在浏览器中显示
%>
这行代码会被插入到service方法中
6、jsp内置对象
在jsp的java代码块、表达式块等可以直接使用的被成为jsp内置对象,常用的内置对象有9个
1.pageContext
页面上下文,四大域中的一个,虽然是域,但一般不用,因为作用域只能在当前页面有效
但是可以通过它获取其他八个内置对象
2.out
out是JspWriter的子类,是一个输出流,可以将数据输出到浏览器
7、jsp指令
jsp指令作用:为当前页面提供一些基础属性设置,为当前页面的运行体提供基础的环境
一共有三种指令:page指令,include指令,taglib指令。这里暂时先描述前两种
语法:<%@ 指令名称 属性名=属性值 属性名=属性值 …%>
1、page指令
**pageEncoding:**指定当前页面编码方式,如果使用这个,那么contentType默认是text/html
contentType:可以指定text/html解析方式,与pageEncoding用一个就行
**import:**导包
<%@ page import="java.util.*"%>
<%@ page import="java.util.*,java.text.*"%>
errorPage:
页面出错后跳转到指定页面
<%@ page errorPage="error.jsp"%>
isErrorPage:
指定当前页面为错误处理页面,那么就会显示错误信息
<%@ page isErrorPage="true"%>
ex= <%= exception.getMessage()%>
**session:**一般读数据的时候设置成false,否则没有读取到的话就会创建一个新的session,占内存
session的使用原则:存:getSession(),取:getSession(false);有老的就用老的,没老的也不建新的
<%@ page session="false"%>
<%
HttpSession session = request.getSession(false);
if(session!=null){
String user = (String)session.getAttribute("user");
out.print(user);
}
%>
2、include指令
<%@ include file="/test.jsp"%>
这叫做静态联编:编译之前就将内容合并到了一起
作用:一个页面可以多次使用
8、jsp动作
由于大量的使用java代码块,表达式块等内容,使得页面杂乱无章
有些公司明文规定不可以使用java代码块和表达式块
推荐使用EL表达式 JSTL标签,jsp动作
语法:
<jsp:动作名称 属性=属性值 属性=属性值 ......></jsp:动作名称>
或者
<jsp:动作名称 属性=属性值 属性=属性值 ....../>
1、forword动作
不可以向标准输出流写入数据
<jsp:forward page="/next.jsp"/><%--会直接跳到next.jsp--%>
2、include动作
可以向标准输出流写入数据
<jsp:include page="/next.jsp"/><%--页面会合并起来--%>
动态联编:编译的时候会生成多个servlet,不可以共享变量
推荐使用静态联编,因为只会生成一个servlet,对资源的消耗比较小
二、EL表达式(重点)
定义:是一种获取数据的简单方式(只能从四大域获取)
语法:${exprition}
1、获取数据
1.从四大域中查找值
<%
String user = "张三";
pageContext.setAttribute("user",user);
requset.setAttribute("user",user);
session.setAttribute("user",user);
application.setAttribute("user",user);
%>
user = ${user}
获取值的时候会从四大域由小到大查找
查找数据的顺序:pageContext,requset,session,application
2.从指定域获取值
${pageScope.value}<%--指定从pageContext获取值--%>
${requestScope.value}<%--指定从request获取值--%>
${sessionScope.value}<%--指定从session中获取值--%>
${applicationScope.value}<%--指定从application中获取值--%>
3.访问bean的属性
EL表达式如果使用为null的对象的属性,EL是不会抛出空指针异常的,其仅仅是不显示而已
<% page import="com.bean.*"%>
schoolName = ${student.school.schoolName}
4.EL访问数组
<%
String[] names = ["test01","test02"];
pageContext.setAttribute("names",names);
%>
names[0] = ${names[0]}
names[1] = ${names[1]}
若访问的数组下标超出了长度,EL不会抛出数组越界异常
5.EL访问List
<%
List<String> names = new ArrayList<>();//jdk8支持这样写
names.add("张三");
names.add("李四");
pageContext.setAttribute("names",names);
%>
names[0] = ${names[0]}
EL无法访问Set
6.EL访问Map
<%
Map<String,Object> map = new HashMap<>();
map.put("school",new School("河北科技大学","石家庄市"));
map.put("age",21);
%>
school.name = ${map.school.sname}<%--这里会自动做一个向下转型--%>
age = ${map.age}
2、EL中的运算符
除了以上的运算符,还有一个重要的运算符 empty
用法:${empty 变量}
如果变量为空,空字符串,空的引用,空集合或者空数组,那么就返回true,否则返回false
<%
String userName = "张三";
Integer age = null;
pageContext.setAttribute("userName",userName);
pageContext.setAttribute("age",age);
%>
userName = ${userName}<br>
age = ${(empty age)?"暂无数据":age}
3、EL内置对象
上面从指定域获取数据用到了四个,下面介绍一些其他常用的
1.pageContext
对于这个对象,用的最多的地方就是
<form action="${pageContext.request.contextPath}/registerServlet" method="GET">
</form>
${pageContext.request.contextPath} 获取当前网站路径
2.param
获取请求中的指定参数值,其底层调用的是request.getParamter()
可用于页面之间传值
姓名:${param.userName}
3.paramValues
获取多个值用paramValues ,其底层调用的是requset.getParamterValues()
爱好:${empty paramValues.hobby[0]?"":paramValues.hobby[0]}<br>
爱好:${empty paramValues.hobby[1]?"":paramValues.hobby[1]}<br>
爱好:${empty paramValues.hobby[2]?"":paramValues.hobby[2]}<br>
4.initParam
web.xml
<context-param>
<param-name>company1</param-name>
<param-value>aaa</param-value>
</context-param>
<context-param>
<param-name>company2</param-name>
<param-value>bbb</param-value>
</context-param>
获取初始化参数
${initParam.company1}
${initParam.company2}
其底层调用的是servletContext.getInitParamter()
4、自定义EL函数
注意:EL表达式不支持字符串的拼接
例子:
实现字符串小写变大写
步骤:
1.创建一个自定义的方法
package com.fjh.test01;
public class ElFunction {
//将字符串小写变大写
public static String lowerToUpper(String source){
return source.toUpperCase();
}
}
2.需要在在一个拓展名为.tld的xml文件中进行注册
tld tag library definition 标签库定义
xml文件是需要约束的,需要配置文件的头部,这个头部可以在tomcat中进行复制
在tomcat安装路径下E:\program\apache-tomcat-8.5.65\webapps\examples\WEB-INF\jsp2
<?xml version="1.0" encoding="ISO-8859-1"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>my</short-name>
<uri>http://mycompany.com</uri>
<!-- Invoke 'Generate' action to add tags or functions -->
<!-- 注册函数-->
<function>
<name>lowerToUpper</name>
<function-class>com.fjh.test01.ElFunction</function-class>
<function-signature>java.lang.String lowerToUpper(java.lang.String)</function-signature>
</function>
</taglib>
3.使用函数
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://mycompany.com" prefix="my"%>
<html>
<head>
<title>index</title>
</head>
<body>
${my:lowerToUpper("ABC")}
</body>
</html>
5、JSTL的EL函数库\
JSTL:jsp Standard tag library 这是Apache定义好的一套标准的标签库规范
需要引入jar包 jstl.jar和standard.jar
三、自定义标签
1.自定义标签的基本用法
步骤
1.定义一个类实现 javax.servlet.jsp.tagext.SimpleTag 这个类成为标签处理器类
package com.fjh.test02;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
public class GetIp extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
//获取pageContext对象
PageContext pc = (PageContext) this.getJspContext();
//获取请求对象
ServletRequest request = pc.getRequest();
//获取客户端ip
String ip = request.getRemoteAddr();
pc.getOut().print(ip);
}
}
2.注册
<?xml version="1.0" encoding="ISO-8859-1"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>myTag</short-name>
<uri>http://my.com</uri>
<!-- Invoke 'Generate' action to add tags or functions -->
<tag>
<name>getIp</name>
<tag-class>com.fjh.test02.GetIp</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
3.使用
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://my.com" prefix="myTag"%>
<html>
<head>
<title>index</title>
</head>
<body>
<myTag:getIp/>
</body>
</html>
2.带标签体的标签
步骤
1定义标签处理器
public class TagTest01 extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
//StringWriter可以获取流中的内容
StringWriter sw = new StringWriter();
//获取标签体内容
JspFragment jspBody = this.getJspBody();
//获取标准输出流
JspWriter out = this.getJspContext().getOut();
//将标签体内容写入到流中
jspBody.invoke(sw);
//获取流中的内容
String content = sw.toString().toUpperCase();
//将内容用标准输出流显示在页面上
out.print(content);
}
}
2注册标签
<tag>
<name>show</name>
<tag-class>com.fjh.test02.TagTest01</tag-class>
<!--
empty:表示当前没有标签体
scriptless:表示有标签体,但是该标签体不会出现java代码块,jsp表达式,但是可以出现EL表达式
jsp:已经弃用,具有标签体,会将标签体内容原样显示在浏览器
tagdependent:表示当前标签具有标签体,将标签内容原样显示在浏览器中,但是不会对EL表达式进行计算
-->
<body-content>scriptless</body-content>
</tag>
3使用标签
<%
pageContext.setAttribute("content","zhangsan");
%>
<myTag:show>${content}</myTag:show>
3.带属性的标签
1.定义标签处理器类
public class TagTest02 extends SimpleTagSupport {
private boolean test;
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
if (test) {
// //获取标签体
// JspFragment jf = this.getJspBody();
// //将标签体写入到标准输出流
// jf.invoke(this.getJspContext().getOut());
this.getJspBody().invoke(null);
//这一句等价于上面,参数为空的时候自动会有一个标准的输出流
}
}
}
2.注册
<!-- 带属性的标签-->
<tag>
<name>if</name>
<tag-class>com.fjh.test02.TagTest02</tag-class>
<body-content>tagdependent</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<!--
runtime expression value
若为true 则属性支持EL和jsp表达式
-->
</attribute>
</tag>
3.使用
<%
pageContext.setAttribute("gender",true);
%>
<myTag:if test="${gender}">男</myTag:if>
<myTag:if test="${not gender}">女</myTag:if>
4.自定义标签遍历所有类型的集合和数组
1.标签处理器
package com.fjh.test02;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.*;
public class ForEach extends SimpleTagSupport {
private Object items;
private String var;
public void setItems(Object items) {
this.items = items;
}
public void setVar(String var) {
this.var = var;
}
//可以处理任何集合或者数组
public Collection getColl(){
if(items instanceof List){
return (List)items;
}else if(items instanceof Set){
return (Set)items;
}else if(items instanceof Map){
return ((Map) items).entrySet();
}else if(items.getClass().isArray()){
List nums = new ArrayList();
for(int i = 0;i< Array.getLength(items);i++){
nums.add(Array.get(items,i));
}
return nums;
}
return null;
}
@Override
public void doTag() throws JspException, IOException {
for(Object obj:getColl()){
this.getJspContext().setAttribute(var,obj);
this.getJspBody().invoke(null);
}
}
}
2.注册
<tag>
<name>forEach</name>
<tag-class>com.fjh.test02.ForEach</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
3.使用
----------遍历List------------
<br>
<%
List users = new ArrayList();
users.add("张三");
users.add("李四");
users.add("王五");
pageContext.setAttribute("users",users);
%>
<myTag:forEach items="${users}" var="user">
${user}<br>
</myTag:forEach>
----------遍历Set------------
<br>
<%
Set set = new HashSet();
set.add("张三");
set.add("李四");
set.add("王五");
pageContext.setAttribute("set",set);
%>
<myTag:forEach items="${set}" var="s">
${s}<br>
</myTag:forEach>
----------遍历Map------------
<br>
<%
Map map = new HashMap();
map.put("name","123");
map.put("age",12);
pageContext.setAttribute("map",map);
%>
<myTag:forEach items="${map}" var="m">
${m}<br>
</myTag:forEach>
----------遍历数组------------
<br>
<%
int[] age = {12,13,14};
pageContext.setAttribute("age",age);
%>
<myTag:forEach items="${age}" var="a">
${a}<br>
</myTag:forEach>
4.结果
----------遍历List------------
张三
李四
王五
----------遍历Set------------
李四
张三
王五
----------遍历Map------------
name=123
age=12
----------遍历数组------------
12
13
14
四、JSTL核心标签库
1.五大标签库
核心标签库:完成基本的逻辑运算,重点
格式化标签库:主要用于日期和数字的格式化
EL函数标签库:定义了若干EL函数
SQL函数标签库:完成SQL操作,不使用了,现在使用java代码完成
XML操作标签库:完成XML操作,不使用了,现在使用java代码完成
最近时间比较紧,而且jsp编程用的不是很多了,所以后面的就省略了
放个链接,可以看看
click这儿
五、javaBean
分类
广义javaBean
数据承载bean
业务处理bean
狭义javaBean
狭义的javaBean是指符合sun公司提出的javaBean规范的java类,javaBean规范规定,满足以下四点的java类称为javaBean
1.该类需要时公共的
2.该类需要实现Serilizable接口
3.该类需要具备无参构造器
4.该类有成员变量,这些成员变量必须是私有的,且需要提供这些属性的setter和getter方法
在实际项目中,实体类一般会被定义为狭义的javaBean,即广义的javaBean的数据承载Bean一般会被定义为满足JavaBean规范的狭义javaBean
六、系统开发模型
1.纯JSP开发
2.JSP+JavaBean的Model1
3.MVC的Model2
MVC,即mode模型,View视图,Controller控制器
View:视图,为用户提供界面,与用户进行交互.
Model:模型,承载数据,并对用户提交的请求进行计算的模块,其分为两类,一类称为数据承载Bean,一类称为业务处理Bean.所谓的数据承载Bean是指实体类,专门用于承载业务数据的,而业务处理Bean则书指Serbice或者Dao对象,专门用于处理用户提交的请求的.
Controller:控制器,用户将用户请求转发给相应的Model处理,指Servlet
4.三层架构
三层架构是指:视图层View,服务层Service,持久层Dao,它们分别完成不同的功能
View层:表现层,视图层,对于Web开发,也称为Web层,用于接收用户提交的代码
Service层:服务层,逻辑层,系统的业务逻辑主要在这里完成
Dao层,持久层,数据访问层,直接操作数据库的代码在这里编写DAO即Data Access Object,数据访问对象
为了更好的降低各层之间的耦合度,在三层架构的设计中,采用面向抽象编程,即上层对下层调用是通过接口实现的,而下层对上层是真正的服务提供者,是下层接口的实现类.
5.MVC+三层架构
注意:MVC和三层架构是不同的不要混淆