Servlet开发的Web存在的缺陷
- 使用Servlet程序进行结果的展示麻烦,需要使用IO流响应结果
- 页面样式改动需要重新编译和部署,重启服务器
JSP — Java server page
- JSP是Servlet的升级版本,运行于服务器端端 Java页面技术,主要用于开发数据的展示功能
- 创建Web项目 —> 在WebRoot创建jsp的文件,不要放在WEB-INF下,因为WEB-INF下的内容,不直接对外公开
- JSP主要用于开发动态Web应用,且必须在服务器中才能运行
Servlet | JSP | |
---|---|---|
开发 | 继承HttpServlet(实现Servlet)接口 覆盖service方法 编写web.xml | 创建 .jsp结尾的文件中 书写HTML+Java代码 |
修改 | 需要重新编译、重新部署、重启服务器 | 刷新页面即可 |
部署 | 正常部署Web项目 | 正常部署Web项目 |
访问 | http://localhost:端口/项目名/url-pattern | http://localhost:端口/项目名/jsp的相对路径 |
JSP执行原理
- JSP的本质就是Servlet,JSP的运行依赖于服务器
- 本质是一个servlet,JSP做数据的展示,从执行的效率上讲,相对比html效率要低
- 翻译:tomcat服务器首先将请求的 JSP翻译成 .java文件
- 翻译规则
- HTML标签翻译成了 out.write(…);
- 表达式脚本中的表达式翻译成out.print(…);
- 声明脚本中的函数翻译成类中普通的方法,变量翻译成了成员变量
- 普通脚本中的内容翻译成了方法内部的代码块
- 普通脚本中声明的变量翻译成了局部变量
- 翻译规则
- 编译:将翻译成的 .java文件,编译成 .class文件
- 执行:最终执行的是 .class文件
- 翻译:tomcat服务器首先将请求的 JSP翻译成 .java文件
JSP页面基本语法
-
脚本元素:各个脚本语法之间都不允许嵌套,且脚本内不允许直接书写HTML标签
- 表达式脚本:展示结果,可以将表达式脚本的结果作为HTML标签属性值
- <%=表达式 => 表达式结束不能有分号
1+1=<%=1+1 %><br> 1/1=<%=1/1 %><br> 1%1=<%=1%1 %><br> <%=1>0 %><br> <%="abc"=="abc" %>
- 声明脚本:用于声明函数和变量
- <%! 函数声明 / 变量声明 %> 声明脚本中不能调用函数,可以在表达式脚本中调用
<%! //声明函数 public int sum(int a,int b){ return a+b; } public java.util.Date getDate(){ return new java.util.Date(); } //声明变量 int m = 10; %> //调用 <%=sum(100,200) %> <%=m+n %> <%=getDate() %>
- 普通脚本:用于书写普通的Java代码,如for循环、分支语句
- <% Java代码 %> 普通脚本内不能嵌套其他脚本元素
<% for(int i = 0;i < 10; i++){%> <%="hello world" %><br> <%} %>
- 表达式脚本:展示结果,可以将表达式脚本的结果作为HTML标签属性值
-
指令元素
- 页面指令:书写和指定当前 JSP页面的基本配置信息
- <%@ page 属性=值 %> 只能写在 JSP页面的第一行开始,可以写多个
<%@ page pageEncoding="utf-8" //编码设置指令,必须写 contentType="text/html;charset=utf-8" //可以省略 默认utf-8 import="java.util.*,java.io.*" //相当于java中导包语句,多个可以用逗号连接 errorPage="xxx.jsp" //配合使用 如果访问出现异常,跳转到错误页面,地址栏不变 isErrorPage="true" language="java" //默认值为java,指定当前的JSP页面支持的变成语言,目前只支持java isELIgnored="false" //是否忽略EL表达式,默认为false,不忽略 session="true" //代表JSP翻译成Java的时候,是否主动创建session对象 %>
- 包含指令:将另一个 JSP页面,包含到当前的 JSP页面
- <%@include file=“被包含页面路径” %>
- 包含的是源文件,也称为静态包含,包含的文件的内容;在开发中需要注意两个页面之间变量名冲突的问题,最后包含页面也被包含页面会合并为一个 .java文件编译
- 标签指令:在当前 JSP页面引入一个标签库
- <%@taglib uri=“标签库路径” prefix=“别名 / 标签库前缀名” %>
- 页面指令:书写和指定当前 JSP页面的基本配置信息
-
动作元素
- 包含动作:动态包含,不包含源文件,是各个页面的执行结果拼接而成,所以不会出现变量名冲突部分
- <jsp:include page=“被包含的路径” ></ jsp:include>
- 转发动作:相当于Servlet中的请求转发
- <jsp:forward page=“路径” ></ jsp:forward>
- 包含动作:动态包含,不包含源文件,是各个页面的执行结果拼接而成,所以不会出现变量名冲突部分
JSP页面九大隐含对象
-
在服务器将 JSP翻译成 .java的时候,自动给我们创建的九个对象
-
request:相当于Servlet中的request作用域
-
response:相当于Servlet中的response对象
-
session:相当于Servlet中的session作用域,要使用session,必须保证页面指令session=true
-
application:相当于Servlet中的ServletContext作用域
-
pageContext
-
pageContext的作用域功能:
- 仅限于当前的 JSP页面
- pageContext.setAttribute(“name” ,value);
-
操作其他作用域:
<% 第三个参数为指定操作哪个作用域 pageContext.setAttribute("name","P"); pageContext.setAttribute("name","R",PageContext.REQUEST_SCOPE); pageContext.setAttribute("name","S",PageContext.SESSION_SCOPE); pageContext.setAttribute("name","A",PageContext.APPLICATION_SCOPE); %> pageContext:<%=pageContext.getAttribute("name") %><br> request:<%=request.getAttribute("name") %><br> session:<%=session.getAttribute("name") %><br> application:<%=application.getAttribute("name") %><br>
-
从作用域中搜索命名属性:
- pageContext.findAttribute(“name”); //按照作用域从小到大的顺序搜索命名属性,找到则返回,不再继续向下搜索;如果所有作用域都没搜索到,则返回null
-
-
out:一个输出流,相当于PrintWriter,可以向页面输出内容
-
config:相当于ServletConfig对象,封装了当前Servlet实现类对web.xml配置文件中的配置信息和获取web.xml默认对象
-
page:相当于this .
-
exception:只在isErrorPage="true"的页面存在,封装了捕捉到的异常信息对象
EL表达式
-
expression language是JSP页面用于展示结果的一种表达式语言,使用EL表达式可以操作作用域和一些表达式运算
-
EL表达式在开发中主要配合JSTL标签库来完成数据的展示
-
EL表达式的诞生是为了使 JSP页面的编码更加简洁,可以替换掉大部分脚本元素
-
语法:${表达式} 在使用EL表达式的JSP页面要保证 isELIgnored=false
-
基础应用
<h3>算数运算</h3> 1+2=${1+2 }<br> <h3>关系比较</h3> 1 > 2=${1>2 } | ${1 gt 2 }<br> 1 >=2=${1>=2} | ${1 ge 2 }<br> 1 < 2=${1<2 } | ${1 lt 2 }<br> 1 <=2=${1<=2} | ${1 le 2 }<br> 1 == 2=${1==2 } | ${1 eq 2 }<br> 1 != 2=${1!=2 } | ${1 ne 2 }<br> ${"a"=="a" }<br> ${"a"=="aa" }<br> <h3>逻辑运算</h3> 与:${1==1 && 1>1 } | ${1==1 and 1>1 }<br> 或:${1==1 || 1>1 } | ${1==1 or 1>1 }<br> 非:${!(1==1 && 1>1) } | ${not(1==1 && 1>1) }<br> <h3>空值的判断</h3> ${m==null } | ${empty requestScope.m }
-
EL表达式操作作用域,主要是从作用域中取值
request:${requestScope.name } | <%=request.getAttribute("name") %> //等价 session:${sessionScope.name } | <%=session.getAttribute("name") %> application:${applicationScope.name } | <%=application.getAttribute("name") %> pageContext:${pageScope.name } | <%=pageContext.getAttribute("name") %>
- 按照范围从小到大搜索命名属性
- 表达式脚本如果从作用域中找不到指定命名属性返回null,EL表达式如果从作用域中找不到命名属性,什么都不返回
<%=pageContext.findAttribute("name") %> //基本等价 ${name }<br> //根据范围从小到大搜索命名属性
- 获取list集合指定元素属性值
<% List<String> strList = new ArrayList<String>(); strList.add("hang"); strList.add("yuan"); strList.add("kun"); request.setAttribute("strList",strList); %> ${requestScope.strList[1] }
- 获取map集合指定元素属性值
<% Map<String,String> strMap = new HashMap<String,String>(); strMap.put("p1","hang"); strMap.put("p2","yuan"); request.setAttribute("strMap", strMap); %> ${requestScope.strMap["p1"] } //根据键获取值
- 获取作用域中自定义对象类型的属性值
- 通过EL表达式获取自定义对象类型的属性值时,是通过调用属性对应的get方法获取的,规则是属性名首字母大写,前面拼接get来调用实体类中get方法;底层是由反射获取,所以注意实体类中的命名规范
<% Person person = new Person(1,"yuan","woman"); request.setAttribute("person",person); List<Person> personList = new ArrayList<Person>(); personList.add(person); personList.add(new Person(1,"hang","man")); request.setAttribute("personList", personList); %> 实体类中的toString:${requestScope.person }<br> person中的值:${requestScope.person.name } | ${requestScope.person.sex }<br> <!-- 取list集合中的自定义对象 作用域中属性名不重复的时候可以在EL表达式中--> ${personList[0] }<br> <!-- 实体类中的toString --> ${personList[0].name } | ${personList[0].sex }<br> <!-- 点的是类中的属性名 -->
- 取map集合元素 —> ${ map[key] }
<% Map<String,String> strMap = new HashMap<String,String>(); strMap.put("一号","hang"); strMap.put("二号","yuan"); request.setAttribute("strMap",strMap); Map<String,Person> personMap = new HashMap<String,Person>(); personMap.put("p1", new Person("hang","LoveMe")); personMap.put("p2", new Person("yuan","LoveMe1")); request.setAttribute("personMap", personMap); %> <h3>取Map集合元素(字符串)</h3> 取所有元素:${strMap }<br> 根据key取值:${strMap['二号'] } <h3>取map集合元素(自定义对象)</h3> ${personMap['p2'].username }
-
EL表达式中其他内置对象
- pageContext:动态获取项目名
- 表达式脚本<%=request.getContextPath() %>
- ${pageContext.request.contextPath }
- param:获取地址栏的请求参数和客户端表单的请求参数
- ${param.name(请求参数的key) }相当于Servlet中的request.getParameter(key)
- <%=request.getParameter(“username”) %>
- paramValues:获取地址栏、表单请求的一组参数
- ${paramValues.hobby[0] }
- <%=request.getParameterValues(“hobby”)[0] %>
- cookie:可以获取到客户端浏览器上保存的cookie
- ${cookie }
- 获取指定的cookie对象:${cookie.username.name }
- 获取指定的cookie对象的value:${cookie.username.value }
- 获取jsessionid:${cookie.JSESSIONID.value }
- pageContext:动态获取项目名
JSTL标签库
-
Java Standard Tag Library,JSP的标准标签库,主要作用是展示数据,与EL表达式配合使用
-
JSTL标签库包含:core核心标签库、fmt数据格式展示库、sql数据库操作、xml子库
-
使用JSTL开发
- 在项目中倒入jstl1.2.jar,myeclipse中的web项目默认集成了jstl的依赖jar包
- 在使用JSTL标签库的JSP页面引入标签库
uri指定标签库地址 prefix给标签库指定一个前缀名,没有强制约束,建议用c <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
核心标签库core的使用
- if:根据条件判断展示数据
<c:if test="书写EL表达式,布尔类型" >内容</c:if>
- choose:类似于Java中switch case
<!-- 当满足指定when的条件,执行对应语句,都不满足执行otherwise --> <c:choose> <c:when test="${score<60 && score>0 }">不及格</c:when> <c:when test="${score>=60 && score<90 }">良好</c:when> <c:otherwise>优秀</c:otherwise> </c:choose>
- 遍历list集合
<% List<String> strList = new ArrayList<String>(); strList.add("hang"); strList.add("yuan"); List<Person> personList = new ArrayList<Person>(); personList.add(new Person(1,"hang","man")); personList.add(new Person(2,"yuan","woman")); request.setAttribute("strList", strList); request.setAttribute("personList", personList); %> <!-- 遍历list集合,泛型是字符串 --> <c:forEach items="${strList }" var="s"> ${s }<br> </c:forEach> <!-- 遍历list集合,泛型是自定义对象 --> <c:forEach items="${requestScope.personList }" var="p"> ${p.id }|${p.name }|${p.sex }<br> </c:forEach>
- 遍历Map集合
<% Map<String,String> strMap = new HashMap<String,String>(); strMap.put("one","hang"); strMap.put("two","圆"); Map<String,People> peopleMap = new HashMap<String,People>(); peopleMap.put("one",new People(1,"hang","man",new Date())); peopleMap.put("two",new People(2,"yuan","women",new Date())); request.setAttribute("strMap", strMap); request.setAttribute("peopleMap", peopleMap); %> <h3>字符串泛型map</h3> <c:forEach items="${strMap }" var="m"> ${m }<br> ${m.key }|${m.value }<hr> </c:forEach> <h3>自定义对象泛型map</h3> <c:forEach items="${peopleMap }" var="map"> ${map.key }|${map.value }<br> ${map.value.id }|${map.value.name }|${map.value.sex }|${map.value.birthday }<hr> </c:forEach>
- 使用forEach标签实现分页的页码展示
<h3>实现分页页码</h3> <!-- begin指定循环初始值,end指定到几结束,var指定循环到变量,step指定循环到步长,默认为1 --> <c:forEach begin="1" end="10" var="i" step="1"> <a href="">${i }</a> </c:forEach>
-
forEach标签的其他属性:
- step:遍历增长的步长;
- varStatus:循环遍历的状态对象
<c:forEach begin="1" end="10" var='i' step="2" varStatus="stu"> ${i } | 当前循环的下标:${stu.index } | 当前遍历的次数:${stu.count } | 是否是第一次遍历:${stu.first } | 是否是最后一次遍历${stu.last }<br> </c:forEach>
-
set:向作用域中存入命名属性,默认存储到pageContext中
<!-- var为命名属性名,value为命名属性值,scope为指定存入哪个作用域 --> <c:set var="name" value="hang"></c:set> <c:set var="name" value="hang" scope="request"></c:set> <c:set var="name" value="hang" scope="session"></c:set> <c:set var="name" value="hang" scope="application"></c:set> pageContext:${pageScope.name }<br> request:${requestScope.name }<br> session:${sessionScope.name }<br> application:${applicationScope.name }<br> <c:set scope="request" var="hello"> //将out流的输出结果存入作用域 <% for(int i=0;i<10;i++){ out.println("Hello World"); } %> </c:set> //存
- remove:移除作用域的命名属性
<!-- var指定移除的命名属性名,scope指定从哪个作用域移除,不指定则删除所有作用域 --> <c:remove var="name"></c:remove> <c:remove var="ceshi" scope="request"></c:remove>
- out:向页面输出结果,可以设置是否原样输出还是加标签效果输出
<c:out value="12345"></c:out><hr> <c:out value="<h1>12345</h1>"></c:out> <!-- escapeXml是否原样输出内容,默认为true,原样输出 --> <c:out value="<h1>12345</h1>" escapeXml="false"></c:out>
- import:可以将另一个页面的结果导入到当前页面,类似于动态包含
<c:import url="http://www.baidu.com"></c:import>
- url:可以生成一个代表路径(项目名)的字符串,还可以检测浏览器cookie是否被禁用,被禁用的话会自动完成URL的重写,相当于response.encodeURL()方法的作用
<a href="<c:url value="/elList.jsp"></c:url>">链接</a> //自动获取项目名 <c:set var="path"> <c:url value="/elList.jsp"></c:url> </c:set> <a href="${path }">链接</a> //配合set使用
- redirect:相当于Servlet中的转发重定向
<c:redirect url="xxx.jsp"></c:redirect>
-
格式化展示日期标签,需要导入格式化日期标签库
<!-- 格式化日期标签库 --> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <% request.setAttribute("date", new Date()); %> ${date }<br> <!-- value属性必须接受一个日期值 --> <fmt:formatDate value="${date }" pattern="yyyy-MM-dd HH:mm:ss" />
MVC
- 是一种编程思想,人为的将Web项目分成了三层,实际开发中顺序通常为MCV
- M:Modle,数据模型层;负责数据的处理和操作
- 数据处理和操作:实体类、DAO、Service
- 实现技术:JDBC、Mybatis、Hibernate
- C:Controller,控制器层;接收请求并处理请求,向客户端响应结果;控制请求从哪来、到哪去。负责流程的跳转
- 处理请求的Servlet
- 实现技术:Servlet、Struts2、SpringMVC
- V:View,视图层;负责与用户进行交互,负责数据的展示,向服务器提交收集到的数据
- html、JSP
- M:Modle,数据模型层;负责数据的处理和操作
- 分层开发优点:各司其职、解耦合、利于团队的协作开发,且分层后每层的复用性得到提示