JSP初学
1.三层架构
与MVC设计模式的目标一致:都是为了 解耦和、提高代码复用;
区别:二者对项目的理解不同。
2.三层组成
表示层(USL,User Show Layer ; 视图层)
--前台:对应与MVC中的View,用于和用户交互、界面的显示
(呈现给用户的一面)
--后台:对应与MVC中的Controller,控制跳转、调用逻辑层
(相当于准备分配任务)
业务逻辑层(BLL,Business Logic Layer ; Service层)
--接受表示层的调用、请求
--组装数据访问层,逻辑性的操作(增删改查,,比删:先查后删,,是数据访问层的原子操作的组装)
数据访问层(DAL,Data Access Layer ; DAO层)
--注解访问数据库的操作,原子性的操作(增删改查)
(直接和数据库进行打交道)
基础复习知识:
1.html<!-- -->可任意被用户用户通过源代码查看到,不是JSP注释
2.一般更改配置文件要重启服务器,而更改jsp/html代码不用重启
3.JSP内置对象(自带的,不需要初始化就可以使用):
out
pageContext
request
response
session
application
config
page
exception
String[] hobbies;
.....
foreach(String hobby :hobbies)
定义一个字符串:String hobby;
//相当于把数组hobbies的每个值都依次赋给hobby进行遍历
request:请求对象;存储“客户端向服务器发送的请求信息”
·String getParameter(String str)返回字段的value值(input 标签的value属性)
·String[] getParameterValues(String str)
·void setCharacterEncoding(“”)请求设置post类型编码(get并不适用)
·ServletContext getServerContext():获取ServletContext对象
get提交方式:method="get"和地址栏、超链接请求方式都属于get提交方式
post与get区别:
A.get在地址栏上显示请求信息(但地址栏能容纳的信息有限,如果请求数据存在大文件图片等,会导致地址栏无法容纳全部数据而报错); post不显示
B.文件上传操作,必须是post
一般推荐post
--请求统一编码
get请求方式 如果出现乱码
A. new String( 旧编码,新编码);
B. 修改server.xml 一次性更改 URIEncoding=""
post请求方式
request.setCharacterEncoding("UTF-8")
response:响应对象
void addCookie(Cookie cookie);服务器向客户端增加cookie对象
void sendRediect(String location)throws IOException(重定向:页面跳转的一种方式)
void sendContentType(String type):设置服务器响应编码(服务端的contentType类型)
请求转发 重定向
地址栏是否改变 不变 改变
是否保留第一次请求的数据 保留 不保留
请求的次数 1 2
跳转 在服务端 客户端
请求转发,从check.jsp--->success.jsp是服务器内部进行的操作,而重定向是客户端是向服务器发送两次请求
例如;
请求转发: 张三(客户端) -> 【窗口A(服务端)->窗口B】
重定向: 张三(客户端) -> 窗口A(服务端) ->去找B
张三(客户端) -> 窗口B(服务端)
请求转发:request.getRequestDispatcher().forword(request,response)
Cookie :由服务端产生,再发送给客户端保存。
作用:提高服务器的效率,但安全性较差。
java.servlet.http.Cookie
·public Cookie(String name, String Value)
·String getName
·String getValue
·void setMaxAge(int expiry):最大有限期(秒)
服务端:response.addCookie(Cookie cookie)
页面跳转(两种方式都可以)
客户端:request.getCookies()
session
机制:
客户端第一次请求服务端时,服务端产生一个session对象()用于保存客户的信息,并且一个session-->一个sessionID一一对应,服务端会产生一个cookie,name为JSESSIONID,value=服务端sessionID的值,在响应客户端的同时,把cookie发送给客户端,客户都拿cookie就可以和服务端session一一对应(JSESSIONID->sessionID)
补充:客户端第一次请求服务端时,如果服务端发现此请求没有JSESSIONID,
第二次/n次,客户端会用客户端的cookie匹配sessionID,则会创建一个name=JSESSIONID的cookie
a.存储在服务端
b.同一个用户请求共享(同一浏览器看作是一个人)
c.实现机制
方法:
String getID():获取sessionID
boolean isNew():判断用户是否为新用户(第一次访问)
void invalidate():使session失效
void setAttribute()
Object getAttribute()
void setMaxInactiveInterval(秒):设置最大有效 非活动时间
void getMaxInactiveInterval(秒):获取最大有效 非活动时间
session cookie
保存的位置 服务端 客户端
安全性 较为安全 较不安全
保存的内容 Object String
application 全局对象
String getContextPath()虚拟路径
String getRealPath(String name) 绝对路径(虚拟路径的绝对路径)
四种范围对象(从小到大)
pageContext JSP页面容器 (page对象) 当前页面有效(跳转页面失效)
request 请求对象 同一次请求有效(请求转发有效;而重定向是请求了两次,无效,不会获得值)
session 会话对象 同一次会话有效(页面怎么跳转都有效;切换浏览器无效;登录到退出之间有效)
application 全局对象 整个项目有效(服务器关闭无效;其他项目无效)
共有的方法:
Object getAttribute(String name) 根据属性名,获取属性值
void setAttribute(String name, Object obj)设置属性值(新增,修改)
setAttribute("a","b")//若a对象不存在,新建一个a对象。
//若之前已经存在,将a的值改为b
void removeAttribute(String name):根据属性名,删除对象
JDBC:可以为多种关系型数据库 提供统一的访问方式 用Java来操作数据库(一个平台)
Java程序通过jdbc操控数据库
JDBC API 主要功能:
DriverManager :管理jdbc驱动
Connection :连接 (通过DriverManager产生)
Statement :增删改查(通过Connection产生)
CallableStatement :调用数据库中 存储过程/存储函数(通过Connection产生)
ResultSet :返回的结果集(通过上面的Statement产生)
Connection产生操作数据库对象:
Connection-->Statement对象:createStatement()
Connection-->PreparedStatement对象:PreparedStatement()
Connection-->CallableStatement对象:PreparedCall()
Statement操作数据库
增删改:executeUpdate();
查:executeQuery();
PreparedStatement操作数据库
继承Statement
增删改:executeUpdate();
查:executeQuery();
赋值操作:setXXX();
Statement与PreparedStatement比较
1.Statement
sql
executeUpdate(sql)
2.PreparedStatement
sql(占位符?)
创建对象 时,将sql预编译 prepareStatement(sql)
setXXX()替换占位符?
executeUpdate()
CallableStatement:调用 存储过程、存储函数
connection.prepareCall(参数:存储过程或存储函数名)
格式
存储过程(无返回值return 用out参数代替)
{call 存储过程名(参数列表)}
存储函数(有返回值return)
{?= call 存储过程名(参数列表)}
JDBC调用存储过程的步骤
a.产生 调用存储过程的对象(CallableStatement) cstmt= connection.prepareCall("...")
b.通过 registerOutParameter(...)处理输出参数类型
d.cstmt.execute()执行
e.接受 输出值 getXXX()
ResultSet;
next():光标下移,判断是否有下一条数据:true/false
previous:true/false
getXXX(字段名/位置):获取字段名值
jdbc访问数据库具体步骤:
1.导入驱动,加载具体的驱动类
2.与数据库建立连接
3.发送sql,执行
4.处理结果集
数据流关闭顺序 与打开顺序相反(先打开的后关闭)
处理TEXT/BOLB类型
处理大数据:
a.存储路径
通过JDBC把文件以字符串形式存储到数据库中,然后根据IO操作处理
b.
TEXT:大文本数据(小说->数据)
BOLB:二进制
TEXT:
存:
1.先通过pstmt的?代替小说内容
2.再通过pstmt.setCharacterStream(2,reader,(int)file.length())将上一步的?替换成小说流,注意第三个参数的参数类型是int
取:
1.通过Reader reader= re.getCharacterStream("NOVEL")将TEXT类型的数据保存在Reader对象中
2.将reader通过Writer输出即可
BOLB:
步骤基本TEXT一致,只不过pstmt.setBinaryStream(...)
JavaBean(就是一个类)
必须满足;1.public 修饰的类,public 修饰无参构造
2.所有属性都是private,并且有set/get(boolean可以替换is)
作用:1.减轻jsp代码的复杂度 2.提高代码复用
使用层面,JavaBean分两大类:
1.封装业务逻辑的JavaBean
可以将jsp中的JDBC代码封装到JavaBean中
用于操作 一个封装数据的JavaBean
2.封装数据的JavaBean(实体类)
对应数据库中的一张表
文件上传
1.引入 apache:commons-fileupload.jar组件
上依赖于commons-io.jar
2.代码:
前台jsp:
<input type="file" name="..">
表单提交方式必须为post
在表单中必须增加 enctype="multipart/form-data"
后台servlet:
注意:
上传目录:upload:
1.如果修改代码,则在tomcat重新启动的时 会被删除(注释也算)
原因:当修改代码的时候,tomcat或重新编译一份class文件,重新部署(重建apache-tomcat底下各种目录)
(tomcat打包workspace中的项目编译成class文件)
2.不修改代码,则不会删除
原因:没有修改代码,class没有仍然是之前的class,不再重新编译
防止丢失;1.虚拟路径 2.直接更换目录不再apache-tomcat下
限制文件的条件放在 List<FileItem> items = upload.parseRequest(request);前面
下载
不需要任何jar包
1.通过超链接请求servlet
2.servlet通过文件地址 将文件转为输入流 读到servlet中
3.通过输入流 将刚才已经转为输入流的文件 输出给用户
注意:下载文件需要设置2个响应头
response.addHeader("content-Type","application/octet-stream");MIME类型:二进制文件(任意文件)
response.addHeader("content-Disposition","attachment;filename="+fileName);fileName中包含了文件名后缀
EL:Expression Language,可以替代JSP页面 中的Java代码
Servlet(增加数据)-->JSP(显示数据)
传统的在JSP中用加Java代码显示数据的弊端:类型转换、需要处理null、代码参杂
EL实例:
${requestScope.student.address.school.schoolAddress}
${域对象.域对象中的属性.属性.属性.级联属性}
EL操作符:
点·:--使用方便
中括号[]:--功能强大,1.可以包含特殊字符(、. -) 2.可以获取数组的值 3.可以获取变量的值
获取map属性
Map<String,Object> map=new HashMap<>();
map.put("cn","中国")
map.put("us","美国")
request.setAttribute("map",map)
${requestScope.map.cn}
${requestScope.map["us"]}
关系运算符 逻辑运算符
Empty运算符:判断一个值的null、不存在、-->true
${empty requestScope.}
EL表达式的隐式对象(不需要new就能使用的对象,自带的对象)
a.作用域访问对象(EL域对象):pageScope requestScope sessionScope applicationScope
${sessionScope.}
如果不指明域对象,则默认会根据从小到大的顺序依次取值
b.参数访问对象:获取表单数据(包括超链接中传的值、地址栏中传的值)
request.getParameter() 、 request.getParameterValues()
${param.} ${paramValues.}
c.JSP隐式对象:pageContext
在JSP中可以通过pageContext获取其他的JSP隐式对象,
因而如果要在EL中使用JSP隐式对象,就可以通过pageContext间接获取
比如getSession方法 -->${pageContext.seesion}
还可以用此方法级联:
${pageContext.request.serverPort}方法名去掉()然后去掉get,首字母小写
JSTL:
需要引入2个jar:jstl.jar standard.jar
引入<%taglib...%>其中有prefix="c"是前缀
核心标签库:通用标签库、条件标签库、迭代标签库
a.通用标签库
<c:set>赋值
1.在某个作用域中给变量赋值
<c:set var="变量名" value="变量值" scope="4个范围对象的作用域"/>
//request.setAttribute("变量名","变量值")
2.给对象赋值
<c:set target="对象" property="对象的属性" value="赋值"
可以给不存在的变量赋值(但不能给不存在的对象赋值)
<c:out> 显示
true:<c:out value='<a href="..."></a>' default="当value值为空时显示默认值" escapeXml="true">
false:<c:out value='<a href="..."></a>' escapeXml="false">
<c:remove>删除属性
<c:remove var="变量名" scope="4个范围对象的作用域"/>
b.条件标签库
选择:
单重
<c:if test=" " var=" ">
多重:
<c:choose>
<c:when test=" "> </c:when>
<c:when test=" "> </c:when>
<c:when test=" "> </c:when>
<c:when test=" "> </c:when>
<c:otherwise> </c:otherwise>
</c:choose>
一定要注意 test=""后面一定不能有空格,不然很容易变成字符串
迭代标签库
循环
·for(int i=0;i<5;i++)
<c:forEach begin="0" end="5" step="1">
test...
//从零开始,到五,一次递增一.结果:test...test...test...test...test...test...
</c:forEach>
·for(String str:names)
<c:forEach var="str" items="${names}">
${str}
</c:forEach>