name="useBean中属性id的值"
property="* | JavaBean的属性名"
value="JavaBean属性值 | <%=表达式 %>"/>
name: 应为该页面中的id值property:
当值为*时,表示存储用户在JSP页面中输入的所有值,并自动匹配JavaBean属性当值为某一具体属性时,表示JavaBean中的一个具体属性名
value: 为JavaBean中某一具体的属性赋值,可以是一个字符串或者是一个表达式
获取JavaBean中指定属性的值
id:引用javaBean在所定义的作用域内的名称,在此作用域内使用该id就代表所引用的JavaBean,区分大小写class:所引用的javaBean的完整包路径scope:指定该javaBean的作用域以及id变量名的有效作用域
4.3JavaBean的作用范围
page:当前页面有效(用户间、页面不共享)
不同用户访问同一个页面,互不影响
request: 用户的请求期有效( request间不共享)
多个request请求同一页面,请求期间互不影响当Web服务器对该请求做出响应后,该JavaBean无效
session :用户会话期间有效(同一用户,页面间共享)
用户在多个页面间建立连接,共享同一JavaBean
application: 作用范围为整个Web应用(不同用户,不同页面共享)
对于同一id名称,此时在Web应用的每一个页面都共享同一个JavaBean,不同用户访问也是同一个JavaBean
4.4 JSP内置对象
不用声明就可在JSP页面中直接使用的对象
4.4.1 request
HTTP协请求报文4部分
请求行(Request Line)
请求方法字段
URL字段
HTTP协议版本字段
请求首部(Header)
客户端传递请求的附加信息和客户端把自己的附加信息给服务器的内容
Host:指出请求的目的地
User-Agent:表示服务器端和客户端脚本都能访问它,他是浏览器类型检测逻辑的重要基础,由客户端的浏览器来定义,并且在每个请求中自动发送
Connection:设置浏览器操作
空行(Blank Line)
即使不存在请求主体,此空行也是必需的
请求数据(Body)
request对象方法
request对象获取客户端的请求信息,以获取通过HTTP协议传送给服务器端的数据(头信息Header,请求方式Post和Get,以及客户端的其他信息)
利用getParameter()、setAttribute(),getAttribute()等方法实现在两个页面间传递数据
String getHeader()获取HTTP协议的头文件信息BufferedReader getReader()以字符码的形式返回请求体String getCharcterEncoding()返回request请求体的字符编码int getContentlength()返回HTTP请求的长度String getContentType()获取客户端请求的MIME类型String getContextPatn()获得上下文的路径,即当前Web应用的根目录String getMethod()获取请求方法 GET POSTString getProtocal()返回请求所使用的协议及其版本Object getAttribute(String name)获取name的属性值,若不存在返回nullEnnumeration getAttributeNames()返回一个枚举类型的 request对象所有属性名称的集合void setAttribute(String name,Object object)设置名为name的参数,其值为objectvoid removeAttribute(String name)删除名称为name的request参数String getParameter(String name)获得指定参数name的参数值Enumeration getParameterValues()返回一个枚举类型的所有参数名称的参数集合String[] getParameterValues(String name)返回包含参数name的所有值的数组ServletInputStream getInputStream()得到请求体中一行的二进制流String getQueryString()获得查询字符串,该字符串在客户端以GET方式向服务器传送获取客户端及服务器的运行环境
String getRemoteHost()返回客户端的主机名String getScheme()返回请求所用的协议名称(HTTP、HTTPS、FTP等)String getRemoteAddr()返回客户端的IP地址int getServerPort()返回服务器的端口号String getServletPath()获得请求JSP页面的名称boolean getSession()返回和当前客户端请求相关联的HTTPSession对象boolean isSecure()判断客户机是否以安全的访问方式访问服务器String getServerName()获取服务器名称,域名或IP地址4.4.2 response
HTTP响应报文
包括状态行(Status Line)、响应头(Header)、空行(Blank Line)、可选实体内容(Body)
请求状态行
状态行 协议版本、状态码、相关的文本短语
1XX请求被接收到,继续处理2XX被成功接收3XX重发,为了完成请求必须采取下一步动作4XX客户端出错5XX服务器端出错response对象常用方法
获取
String getCharacterEncoding()取得字符编码类型int getBufferSize()取得缓冲区的大小String getContentType()取得MIME类型Locale getLocale()取得本地信息输出
ServletOutputStream getOutputStream()返回一个二进制输出字符流PrintWriter getWriter()返回一个输出字符流新增
void addCookie(Cookie cookie)给客户端添加一个Cookie对象,保存客户端信息void addDateHeader(String name,long value)添加一个日期类型的HTTP首部信息,覆盖同名的HTTP首部void addIntHeader(String name,int value)添加一个整型的HTTP首部,覆盖旧的首部操作
void flushBuffer()清空缓存区int getBufferSize()取得缓存区的大小void resetBuffer()重置缓存区void reset()重置response对象void setBufferSize(int size)设置缓存区大小为Sizevoid setCharacterEncoding(String encoding)设置字符编码为encodingvoid setContentType(String type)设置MIME类型void setContentLength(int length)设置响应数据的大小为lengthvoid setDateHeader(String s1,long l)设置日期类型的HTTPvoid setHeader(String s1,String s2)设置HTTP首部信息void setLocale(Locale locale)设置本地化为localevoid setStatus(int status)设置状态码为statusvoid sendError(int sc)向客户端发送HTTP状态码的出错信息void sendRedirect()重定向客户的请求到指定页面编译
String encodeRedirectURL(String url)对使用的URL进行编译StringencodeURL(String url)封装url并返回到客户端,实现URL的重写setHeader
response.setHeader("Refresh","1") //设置自动刷新时间间隔
response.setHeader("Refresh","10;URL=") //设置页面的自动跳转
sendRedirect
response.sendRedirect("")//实现页面直接跳转
禁用页面缓存
response.setHeader("Cache-Control","no-cache")
response.setHeader("Pragma","no-cache")
response.setDateHeader("Expires",0);
4.4.3 page
代表的是当前正在运行的JSP页面
被编译后的Servlet,相当于JAVA中的object类
class getClass()获取page对象的类int hashCode()获取page对象的hash码4.4.4 pageContext
代表当前页面的所有属性和对象,可以通过该对象提供的方法获取其他内置对象
获取其他内置对象
ServletRequest getRequest()ServletResponse getResponse()Object getPage()ServletContext getServletContext()JSPWriter getOut()HttpSession getSession()ServletConfig getServletConfig()Exception getException()
方法
void setAttribute(String name,Object obj)设置默认页面范围或对象范围内的属性值void removeAttribute(String name)删除属性namevoid forward(String url)将当前页面重影响到另一个页面或Servlet对象Object findAttribute(String name)查找在所有范围内属性名为name 的属性4.4.5 out
向JSP页面输出各种类型数据,并管理Web服务器上的输出缓存区。输出包括(文本内容,HTML标签,JS脚本)
void print()向JSP页面输出数据,但不结束当前行,下一个输出仍将在本行输出void println()向JSP页面输出数据,结束当前行void newline()换行void close()关闭输出流void clear()清空缓冲区数据,但不把数据写到客户端void clearBuffer()清空缓冲区数据,并将数据写到客户端void flush()清空缓冲区数据boolean isAutoFlush()是否自动清空缓冲,autoFlush通过page指令设置int getBufferSize()返回缓冲区大小int getRemaining()返回缓冲区剩余空间大小4.4.6 session
跟踪用户状态:指在一段时间内用户与Web应用的交互过程中,保存每个用户的用户信息和会话状态
由web容器自动创建,当初次登录Web应用时,分配唯一的用户表示session id,
用MAP保存数据,每个用户都有若干键值对
Web中跟踪用户状态的四种方法
使用session
在HTML表单中,加入隐藏字段,包含与跟踪用户状态的数据
重写URL
使用cookie传送
客户端的Cookie通过HTTP头信息发送给服务器,用于唯一标识浏览器用户
Cookie是保存在客户端某个目录下的文本数据,由服务器生成该数据,返回给客户端。
键值对组成
方法
long getCreationTime()返回session创建时间String sessionId()返回用户的session idlong getLastAccessedTime()返回session最后一次被操作的时间,单位为毫秒Object getAttribute(String name)返回属性名为name的属性值Enumeration getAttributeNames()返回一个枚举类型,即session的所有属性int getMaxInactiveInterval()返回两次操作的最大时间间隔,超时取消ServletContext getServletContext()返回session所属的ServletContext对象void invalidate()取消会话boolean isNew()返回服务器创建的一个会话,即客户端是否加入void setAttribute(String name,Object obj)设置指定名称为name属性值为obj,并存储在session中void removeAttribute(String name)删除void setMaxInactiveInterval(int time)设置两次请求最大时间间隔为time4.4.7 application
application对象保存的是Web应用中的共享数据,被所有用户共享使用
**生命周期:**在Web服务器启动之后产生,直至Web服务器关闭之前。
Object getAttribute(String name)获取name属性值Enumeration getAttributeNames()获取所有属性的名称,返回类型为枚举类型String getInitParameter(String name)获取name属性的初始值String getServerInfo()获取当前JSP引擎名及版本信息等String getRealPath(String path)返回当前Web应用的实际路径ServeletContext getContext(String path)返回Web应用的application对象String getMimeType(String file)返回指定文件的MIME类型URL getResource(String path)返回指定资源的URLServlet getServlet(String name)返回指定名称的ServletEnumeration getServlets()返回所有Servlet的枚举Enumeration getServletNames()返回所有Servlet名的枚举int getMajorVersion()返回服务器支持的Servlet API主版本号int getMinorVersion()返回服务器支持的Servlet API此版本号void setAttribute(String name,value k)设置name的属性值为k4.4.8 config
用于读取Web应用的初始化参数
web.xml
配置WEB应用程序的欢迎页、Servlet、Filter等,保存于WEB-INF文件下
web.xml配置文件中的元素名称及其顺序有严格规定。
包含web.xml中所有子元素
设置欢迎页面,为Web应用设置首页
按顺序从第一个向后查找,若第一个存在,则后面不起作用
命名与定制URL
为JSP和Servlet文件命名,并定制URL
描述该Servlet
设置显示该Servlet的名称,为可选子元素
设置Servlet的名称
设置该Servlet具体的包路径
指定Servlet加载的次序,即启动装入优先权。数值越小,优先级越高
设置servlet的名称,必须与servlet-name下的子元素值相同
设置Servlet的URL
定制初始化参数
设置Servlet、JSP、Context的初始化参数,使用config对象就可获取
参数名
参数值
指定错误处理页面
状态码
指定异常类型
发生错误时跳转到的错误处理页面
设置过滤器
设置监听器
设置会话过期时间
方法
String getInitParameter(String name)返回名称为name的初始化参数Enumeration getInitParameterNames()返回所有初始参数名称的枚举ServetContext getServletContext()返回当前Servlet的上下文String getServletName()返回当前Servlet的名称4.4.9 exception
处理JSP页面执行时发生的异常
使用时需要指定错误处理页面,通过page指令设置错误处理页面
注意
错误处理页面的page指令中isErrorPage属性值为trueerrorPage指定错误处理页面如果在产生异常的页面中使用try-catch-finally进行异常捕获和处理,则将不能触发异常处理页面
String getMessage()返回异常信息void printStackTrace()以标准错误的形式输出错误及跟踪信息String toString()以字符串形式返回异常信息5. JDBC
5.1 概述
JDBC:用于 执行Sql语句 的Java API,可以为多种关系数据库提供统一访问,是一组用Java语言编写的类和接口
独立于特定的数据库管理系统,提供了通用的Sql数据库的操作接口,定义了访问数据库的标准Java类库包
通过JDBC就可以连接任何提供了JDBC驱动程序的数据库系统
Java应用程序通过JDBC API 和 JDBC Manager API 进行通信
JDBC Manager管理JDBC驱动程序(由数据库厂商提供, Java实现,套接字为底层)
5.2 JDBC API访问数据库
5.2.1 基本步骤
(1) 加载JDBC驱动
(2) 建立数据库连接
(3) 创建操作数据库SQL的Statement、PrepareStatement、CallableStatement对象
(4) 执行语句并分析结果
(5) 关闭连接
0). 环境
首先应将加载数据库的JDBC驱动程序(jar包)复制到Web应用程序的WEB-INF\lib目录下
1). 加载驱动
通过反射机制创建数据库驱动程序实例
MySQL驱动类名为 com.mysql.jdbc.Driver
Class.forName("com.mysql.jdbc.Driver")
2). 建立与数据库的连接
利用DriverManager类的方法getConnection()获得与特定数据库的链接实例
String url = "jdbc:mysql://localhost:3306/userdb?user=root&password=passwd&userUnicode=true&characterEncoding=UTF-8"
Connection con = DriverManager.getConnection(url)
字符串拼接容易出错
Connection con = DriverManager.getConnection("jdbc://mysql://localhost:3306/userdb",root,passwd);
3)对数据库操作
JDBC提供三种执行SQL的对象
Statement对象执行静态SQL语句
Statement = con.createStatement();
//使用executeQuery()方法执行Select语句,返回ResultSet类型
ResultSet rs = statement.executeQuery("select *from userdb");
//executeUpdate方法执行INSERT,UPDATE,DELETE等SQL语句,返回int 类型
int result = 0;
result = ststement.executeUpdate("DELETE FROM userdb where ");
PreparedStatement 执行动态SQL语句
#查询
//声明动态SQL,参数使用?占位符表示
String sqlSelect = "SELECT * FROM userdb WHERE userName=?";
//创建PreparedStatement对象
PreparedStatement psQuery = con.prepareStatement(sqlSelect);
//设置第一个参数
psQuery.setString(1,'Allen')
//使用executeQuery()方法执行SELECT语句,返回职位ResultSet类型
ResultSet rs = psQuery.executeQuery();
#更新
String sqlDelete = "DELETE FROM userdb WHERE username=?";
//创建PreparedStatement对象
PreparedStatement psUpdate = con.prepareStatement(sqlDelete);
psUpdate.setString(1,"Allen");
//使用executeUpdate()方法执行INSERT,DELETE,UPDATE等SQL语句
int result = 0;
result = psUpdate.executeUpdate();
CallableStatement执行存储过程
CallableStatement中的新增方法用于处理OUT参数或INOUT参数的输出部分
为OUT类型参数赋值需要使用CallableStatement接口的registerOutParameter()方法
/*创建CallableStatement
?为占位符,表示IN,OUT或INOUT类型的参数
*/
CallableStatement cs = con.prepareCall("{call sq_Search(?)}");
//使用setXxx()方法为IN参数赋值
cs.setString(1,"Allen");
//执行存储过程,该存储过程为执行一个查询,故使用executeQuery()
ResultSet rs = cs.executeQuery();
4)对执行结果进行分析处理
分析查询结果集ResultSet
执行SELECT语句后必然产生ResultSet结果集实例,用循环 next 遍历结果集中的没一行记录,使用 getXxx() 方法获取遍历记录行指定列的数据
ResultSet rs = ststement.executeQuery("SELECT * FROM userdb");
//使用next()方法判断结果集是否有下一行,从而遍历结果集的所有记录航
while(re.next()){
String username = rs.getString("username");
String gender = rs.getString(2);
System.out.println("用户名:"+username+"性别:"+gender);
}
分析执行结果
执行INSERT,UPDATE,DELETE,一般由executeUpdate()方法执行并返回int类型,表示受影响的记录行数
int result = 0;
String sql = "DELETE FROM userdb WHERE username='Allen'";
result = statement.executeUpdate(sql);
if(result > 0)
System.out.println("删除成功!");
else
Syetem.out.println("执行删除失败!");
5)关闭JDBC对象
(1) 关闭结果集ResultSet对象
(2) 关闭Statement,PreparedStatement或CallableStatement对象
(3) 关闭连接对象
在应用程序操作完数据库之后,需要关闭JDBC相关对象,释放系统资源
在JDBC中建议使用PreparedStatement或者CallableStatement,防止SQL注入问题,减轻网络负载,但增加了数据库负载
5.3 JDBC API
5.3.1 驱动程序接口 Driver
将应用程序的API请求转换为特定的数据库请求
由驱动程序开发商提供JDBC驱动程序,并提供 java.sql.Driver 类
由 java.lang.Class 类的方法 forName() 加载该Driver类,创建实例并向java.sql.DriverManager 类注册该实例
5.3.2 驱动管理器类 DriverManager
管理数据库与对应驱动程序之间的连接
方法
static Connection getConnection(String url)建立与指定路径为url的数据库连接static Connection getConnection(String url,Properties prop)建立数据库连接,prop保存了数据库用户的用户名与密码等static Connection getConnection(String url,String user,String password)建立与数据库连接,用户名,密码JDBC URL标准语法
jdbc:子协议://主机名:端口号/数据库名(可选)
第一个字段固定值jdbc,表示协议第二个字段为子协议,区分JDBC驱动程序,不同数据库厂商子协议不同(如mysql,sqlserver)第三个字段为指定数据库的主机名,由ip地址表示第四个字段表示端口号
5.3.3 数据库连接接口
Connection 对象表示Java程序与特定数据库之间的连接
方法
void close()关闭数据库连接boolean isClosed()判断当前Connection对象是否关闭void rollback()回滚事务void commit()向数据库提交添加、修改和删除等语句boolean getAutoCommit()判断Connection对象是否为自动提交模式void setAutoCommit(boolean commit)设置是否为自动提交,默认为trueString getCatalog()获取Connection对象的当前目录名boolean isReadOnly()判断当前Connection对象是否只读void setReadOnly(boolean readOnly)将此连接设置为只读模式Statement createStatement()创建Statement实例,执行SQL语句Statement createStatement(int rsType,int rsConcurrency)产生指定类型的结果集Statement createStatement(int rsType,int rsConcurrency,int rsHoldability)产生指定类型的结果集PreparedStatement prepareStatement(String sql)创建一个PrepareStatement实例,执行含有参数的SQL语句,动态SQLCallableStatement prepareCall(String sql)创建一个CallableStatement实例,该实例可执行存储过程5.3.4 执行SQL语句接口 Statement
三种Statement对象
Statement执行不含参数的静态SQL语句PreparedStatement执行带参数的动态SQL语句CallableStatement调用数据库的存储过程方法
void isClosed()判断是否已关闭了此Statement对象void close()立即释放此Statement对象占用的数据库和JDBC资源void addBatch(String sql)将给定的SQL命令添加到此Statement对象的当前命令列表void clearBatch()清空次Statement命令列表int[] executeBatch()将一批命令交给数据库执行,如果所有命令执行成功,返回整型数据boolean execute(String sql)执行给定SQL语句,若执行成功返回true,否则返回falseint executeUpdate(String sql)执行给定SQL语句,该语句可以是insert、uodate、update、delete语句,或者不返回任何内容的SQL语句int getUpdateCount()以更新技术的形式获取当前结果,若为ResultSet对象返回-1ResultSet executeQuery(String sql)执行给定的SQL查询语句,返回ResultSet对象5.3.5 执行动态SQL语句接口 PreparedStatement
执行带参数的动态SQL语句,PrepareStatement实例执行SQL语句将进行预编译,并保存到实例中
方法
void addBatch()将一组参数添加到此PreparedStatement对象的批处理命令中void clearParamenters()立即清除当前参数值void setXxx(int I,Xxx v)设置动态SQL语句中的第i个参数值为v,参数的数据类型为Xxxboolean execute()在此PreparedStatement对象中执行SQL语句ResultSet executeQuery()在此PreparedStatement对象中执行SQL查询,并将查询结果以ResultSet形式返回int executeUpdate()执行SQL语句,该语句必须是一个INSERT、UPDATE、DELETE语句,也可以是DDL语句5.3.6 查询结果集接口 ResultSet
ResultSet 结果集是一张二维表,其中有查询返回的列标题以及对应的数据
方法
xxx getXxx(int columnIndex)获取第columnIndex列数据类型为xxx的字段数据xxx getXxx(String columnName)获取列名为columnName,列数据类型为xxx的字段数据boolean next()使指针向下移动一行,如存在下一行返回true,否则返回falseboolean absolute(int row)指针定位在指定行row,其实行号为1boolean first()将指针定位在第一行,若结果集为null返回falseboolean last()将指针定位在最后一行,若结果集为null返回falseboolean close()释放ResultSet实例占用的数据库和JDBC资源5.4 数据库连接池
数据库连接池:在一个虚拟的池中预先创建一定数量的Connection对象等待客户端的连接,当有客户端连接时则分配一个空闲的Connection对象给客户端连接数据库;
当客户端请求结束,将连接归还给数据库连接池,等待下一个客户端访问
数据库连接池负责分配、管理和释放数据库连接,允许应用程序重复使用一个现有的数据库连接。
5.4.1 数据库连接池工作过程
预先定义一定数量的连接,并存放在数据库连接池中当客户端请求一个数据库连接时,系统将从数据库连接池中分配一个空闲的连接;当该请求结束时,该连接归还到数据库连接池中当连接池中的空闲连接数量低于下限时,连接池将会根据配置信息追加一定数量的连接对象;当空闲连接数量多于上限时,连接池会释放一定数量的连接。
5.4.2 连接池优势
创建一个新的数据库连接所耗费的时间主要取决于网络的速度以及应用程序和数据库服务器(网络)的距离提高了数据库连接的重复利用率解决了数据库对连接数量的限制
5.4.3 使用连接池技术访问数据库
在WEB应用的META-INF下新建context.xml文件,配置数据源
type="javax.sql.DataSource"
auth="Container"
driverClassName="com.mysql.jdbc.Driver"
url = "jdbc:mysql://localhost:3306/test"
username="root"
passward="123"
maxActive="5"
maxIdle="2"
maxWait="6000"/>
Resource元素的属性
name设置数据源JNDI名type设置数据源的类型auth设置数据源的管理者,有Container(容器创建者来创建和管理数据源)和Application(由Web应用程序来创建和管理数据源)两种driverClassName设置连接数据库的JDBC驱动程序url设置连接数据库的路径username设置连接数据库的用户名password设置连接数据库的密码maxActive设置连接池中处于活动状态的数据库连接的最大数目,0表示无限制maxIdle设置连接池中处于空闲状态的数据库连接最大数目maxWait设置当连接池中处于空闲状态的连接请求数据库连接的请求的最长等待时间,超时抛出异常-1表示无限制
使用JBDI访问数据库连接池
JDBC提供了javax.sql.DataSource接口负责与数据库建立连接,在应用中,可直接从数据源(context.xml)中获得数据库连接。
DataSource对象由WEB服务器提供
//context是javax.name包中的一个接口,用于查找数据库连接池的配置文件
Context ctx = new InitialContext();
ctx = (Context)ctx.lookup("java:comp/env");
DataSource ds = (DataSourcce) ctx.lookup("dbpool");
Connection con = db.getConnection();
6.MVC与DAO模式
6.1 MVC模式
6.1.1 概述
MVC模式按功能对各种对象进行分割(这些对象用来维护和表现数据的),目的是将各对象的耦合程度减小到最小
Model模型:访问数据,处理数据。用于封装与应用程序的业务逻辑相关的数据以及数据处理方法。
当模型发生改变时,会通知视图,并且为视图提供查询模型相关状态的能力;
为控制器提供访问封装在模型内部的应用程序的能力
View视图:接受请求,可视化响应。从模型获得数据并制定这些数据如何表现。
当模型变化时,视图负责维持数据表现的一致性,视图同时负责将用户需求通知控制器
Controller控制器:业务流程控制,决定数据流方向——用哪个模型处理数据 用于控制应用程序的流程。
处理事件并做出响应。事件包括用户的行为和数据模型上的改变
6.1.2 MVC工作过程
客户通过视图发出请求,该请求转发给控制器控制器接受用户请求,决定使用何种业务逻辑处理该请求,并调用相应的模型处理模型处理用户请求并存取相关数据,客户查询检索的任何数据都被返回给控制器控制器接收从模型返回的数据,并选择适当的视图显示响应结果
6.1.3 Web模式发展历程
传统Web框架
特点:简单直观,易于搭建原型
但维护困难,代码可读性差,程序和页面耦合度高,致使程序不易扩展,分工不明确,开发效率低。
JSP Model1
JSP页面负责调用模型组件以响应客户请求,并将处理结果返回给用户。
JSP负责视图和控制器双重功能,JavaBean负责业务处理逻辑
JSP Model2
使用JSP生成视图层内容;
使用Servlet实现业务逻辑控制,处理客户机请求,充当控制器的角色;
使用JavaBean充当模型,用于数据的存储于提取
演进式开发
Alibaba PHP–>个人网站用户量大–>Java去IOE -->Mysql–>AliSql,AliRedisAll in one --> 微服务
特点:
有利于代码复用有利于开发人员分工有利于降低程序模块间的耦合度
6.2 DAO模式
对业务层提供数据抽象层接口
6.2.1 目标
数据存储与逻辑处理的分离
DAO模式将数据访问划分为接口层和实现层,从而分离了数据使用和数据访问的实现细节
数据抽象
DAO模式通过对底层数据封装,为业务层提供一个面向对象的接口,使得业务逻辑开发人员可以面向业务的实体进行编码
6.2.2 MVC与Dao
model ——dao,service
数据层,数据Dao Value Object
保存数据状态
pojo:User
vo:UserVodto:
服务层,行为Service
业务逻辑
view——jsp
显示页面
controller——servlet
接受请求,委托模型层处理,完毕后返回给视图,由视图展示
取得表单数据调用业务逻辑转向指定的页面
用户发请求Servlet接受请求数据,并调用对应的数据业务逻辑方法业务处理完毕,返回更新后的数据给Servletservlet转向JSP,由JSP来渲染页面响应给前端更新后的页面
6.2.3 实现DAO模式的步骤
数据库连接类
数据库连接类既可以使用基本的JDBC技术实现,也可以使用DBCP等数据库连接池技术实现
VO类
VO类是值对象,包含所有属性与表中字段完全对应的类,在该类中提供setter和getter方法设置并获取该类中的属性
仅仅含有私有成员变量和响应的setter和getter方法的类,可以理解为一种简化的JavaBean
DAO接口
DAO接口为开发人员提供了访问数据库表的一些通用方法,是开发人员操作数据库的接口,
并将数据访问和底层和数据操作分离,降低了应用程序对底层数据库的依赖
DAO接口命名格式为“I+VO类+Dao”
DAO实现类
DAO实现类实现类DAO接口,并实现类DAO接口中所有的抽象方法,
在DAO实现类中设计SQL语句,DAO实现类往往与具体的底层数据库较为紧密
DAO工厂类
用工厂方法代替new操作的一种模式。相当于创建实例对象的new,需要根据Class类生成实例对象
6.3 请求转发与重定向
实现Web应用资源(包括HTML/JSP页面、Servlet对象等)相互关联与整合
请求转发重定向包含
6.3.1 请求转发
请求转发方式允许将客户端的请求转发给 同一个Web应用的其他资源
在Servlet对象中选择客户请求做一些预处理操作,然后将客户请求转发给其他资源
共享同一用户请求
RequestDispatcher dispatcher = request.getRequestDispatcher("target.jsp");
dispatcher.forward(request,response);
6.3.2 重定向
目标资源可以不在同一Web应用中
response.sendRedirect("pages/target.jsp");
与请求转发区别
(1)Web资源可以重定向任何一个URL
(2)重定向是返回一个应答给客户端,然后再重新发送一个请求给目标URL,所以浏览器地址栏中会更新为目标资源的URL
RequestDispatcher不会更新浏览器资源栏
(3)在使用重定向时,Web资源之间不会共享使用用户请求对象
6.4 页面间数据的共享方式
6.4.1 重写URL
在URL后附加参数,称为查询字符串
**?**后附加查询键值对
获取查询字符串对应值
String id= request.getParameter("id");
缺点:
(1)重写URL的页面必须动态生成
(2)用户数据暴露,容易造成安全隐患
(3)URL长度有限制,若传递大量数据,造成性能下降
(4)必须对所有指向本Web站点的URL进行编码
(5)访问不方便,不能预先记录访问页面的URL
6.4.2 共享会话
使用session内置对象访问共享用户数据
session对象的setAttribute(String name,Object object)方法可以设置在会话期间共享的数据属性的名称和值
session过期时间设置
minutes
6.4.3 使用Cookie
Cookie用户存储Web服务器发送客户机的信息(通常以文本形式保存在客户端)
当客户端第一次访问服务器时,服务器为用户创建一个Cookie对象,在响应客户端的同时Cookie对象发送到客户端
服务器程序需要读取Cookie时,可以再由Resuqst对象获取Cookie中的数据
Cookie以 “name/value” 映射形式保存数据
通过Cookie构造方法创建Cookie对象
Cookie cookie=new Cookie(String name,Object object)
设置Cookie的最大保留时间
cookie.setMaxAge(int value);//单位为秒
将Cookie对象添加到响应对象中
response.addCookie(Cookie onject);
得到从客户端发来的Cookie对象
Cookie[] cookies=request.getCookies();//返回一个Cookie数组
获取Cookie中的数据方法
cookie.getName();//键名
cookie.getValue();//值名
7. EL表达式
<%=expression %>的优化
7.1 EL简介
中文称为表达式语言
特点:
在EL表达式中可以访问JSP内置对象EL表达式可以访问一般变量,还可以访问JavaBean中的属性以及嵌套属性和集合对象在EL表达式中可以执行关系、逻辑和算数等运算在EL表达式中可以访问JSP作用域(request、session、page、application)EL表达式中可以直接调用一个普通的Java类中的公共静态方法
7.2 EL语法
${expression}
7.2.1 EL运算符
?:——条件语句+*/或div——除法%或mod——取余==或eq!=或ne——不等于<或lt>或gt<=或le>=或ge&&或and∣\mid∣ ——或or!或notempty表达式中操作符要与操作数用空格分隔
7.2.2 使用EL表达式访问JavaBean对象
${JavaBean对象名称.属性名称}
7.2.3 使用EL访问隐式对象
applicationScope应用范围的对象集合sessionScoppe所有会话范围的对象集合requestScope所有的请求范围对象集合pageScope所有页面范围的对象集合cookie所有cookie组成的集合headerHTTP请求头部,字符串headerValuesHTTP请求头部,字符串集合initParam全部应用程序参数名责成的集合pageContext当前页面的对象,提供了页面属性的访问param所有请求参数字符串组成的参数集合paramValues所有作为字符串集合的请求参数8. Web开发中常见问题
8.1 中文问题
8.1.1 起因
很多媒介质(例如数据库,文件等)的存储方式都是基于字节流,Java应用程序与这些媒介交互时会发生字符(char)与字节(byte)之间的转换
(1)从JSP页面表单提交数据到Java应用程序(Servlet)时,需要进行从字节到字符的转换
(2)从Java应用程序到JSP页面显示时需要进行字符到字节的转换
(3)从数据库到Java程序读取时,需要进行从字节到字符的转换
(4)从Java程序到数据库存储时,需要进行从字符到字节的的转换
(5)当一些文件被Java程序读取时,需要进行从字节到字符的转换
(6)当Java应用程序向一些文件存储数据时需要进行从字符到字节的转换
转换过程中使用的编码方式与字节原有的编码不一致时,中文信息就会出现乱码
8.1.2 常见字符集
ASCII
包括英文字母,阿拉伯数字和标点符号
GB2312-80
简体汉字标准字符编码方案,区位码
GBK
向下完全兼容GB2312
GB18030
向下兼容GBK
Unicode
国际统一标准称为Unicode
Unicode为每一个字符提供了唯一特定数值
三套编码方案:UTF-8,UTF-16,UTF-32
ISO8859-1
Latin-1,西欧语言
BIG5
大五码,繁体中文
8.1.3 中文问题解决办法
JSP页面显示乱码问题
在JSP页面的page指令的contentType属性和pageEncoding属性以及HTML的meta标签的charset属性指定使用中文编码即可
指定字符集时,不区分大小写
JSP页面中文输出出现乱码,设置响应报文的MIME类型
response.setContentType("text/html;charset=UTF-8");
表单提交中文时出现乱码问题
第一种方法
获取表单数据的页面或Servlet中首先使用request对象的setCharacterEncoding()方法强制设定获取表单数据的编码方式
此时表单的提交方式,method属性必须设定为"POST"方式
request.setCharacterEncoding("UTF-8");
String name=request.getParameter("name");
第二种方法
使用String类的构造方法对字符和撺弄进行重构
String name=request.getParameter("name");
name=new String(name.getBytes("ISO-8859-1"),"utf-8");
String.getBytes(String decode)
根据decode编码返回该编码下字符的Bytes数组表示中文占两位,高八位,低八位
new string(byte[],decode)
根据decode将byte数组转换为字符串
数据库连接出现乱码问题
在数据库连接字符串中加入编码字符集
String url="jdbc:mysql//localhost:3306/database?user=root&password=pwd&useUnicode=true&characterEncoding=UTF-8";
数据库显示中文信息的乱码问题
Java程序访问MySQL数据库中的varchar、text等类型字段时会出现中文乱码问题
编写转换编码的公共类
public class StringConvert{
/* 将ISO-8859-1编码的字符转换为UTF编码方式 */
public static String iso2utf(String s){
String gb;
try{
if(s.equal("")||s==null){
return "";
}
else{
s=s.trim();//删除字符串头尾空白符
gb = new String(s.getBytes("ISO-8859-1"),"UTF-8");
return gb;
}
}catch(Exception e){
System.err.print("编码格式转换错误:"+e.getMessage());
return "";
}
}
//将UTF-8编码字符转换为ISO-8859-1编码方式
public static String utf2iso(String s){
String gb;
try{
if(s.equal("")||s==null){
return "";
}
else{
s=s.trim();//删除字符串头尾空白符
gb = new String(s.getBytes("UFT-8"),"ISO-8859-1");
return gb;
}
}catch(Exception e){
System.err.print("编码格式转换错误:"+e.getMessage());
return "";
}
}
}
8.2 分页显示
8.2.1 设计思路
总记录数:表示从数据库中检索出满足条件的记录总数
每页显示记录数:表示程序中设定的每页显示记录的最大个数
总页数:总记录数/每页显示记录数
当前页码:当前JSP页面中显示记录的页码
两种思路
一次性的从数据库查询所有符合条件的记录,然后利用程序实现分页基于数据库的分页技术(利用SQL语句)实现分页
8.2.2 不同数据库中实现分页显示
select * from db limit M ,N
从M开始的N条记录
上一页:M=(当前页码-1)*每页显示最大记录数+1
下一页:M=(当前页码+1)*每页显示最大记录数+1
8.3 格式化数值与日期
NumberFormat格式化数字,DateFormat格式化日期
二者本身都是抽象类,不能实例化对象
在java.text包中有一个抽象类Format,NuberFormat和DateFormat都是Format的直接子类
8.3.1 数值格式化
方法
StringFormat(long number)将数值、日期格式化为字符串Locale[] getAvailableLocales()返回系统支持的Locale对象数组NumberFormat getCurrencyInstance()返回默认locale的货币格式,也可指定LocaleNumberFormat getNumberInstance()返回默认locale的数值格式,也可指定LocaleNumberFormat getPercentInstance()返回默认locale的百分比格式,也可指定LocaleNumber parase(String source)将字符串解析为数值指定Locale
NumberFormat nf = NumberFormat.getInstance(Locale.CHINA);
locale用于封装特定的国家或地区、语言环境
8.3.2 日期格式化
String format(long number)将日期、时间格式化为字符串Number parse(String source)将字符串解析为日期Calendar getCalendar()获得与此日期/时间相关联的日历DateFormat getDateInstance()返回默认Locale的日期格式,也可指定LocaleDateFormat getDateTimeInstance()返回默认Locale的日期时间格式,也可指定LocaleDateFormat getTimeInstance()返回默认Locale的时间格式,也可指定LocalegetInstance(type,locale)两个参数
四种类型
DateFormat.SHORT中19-6-6DateFormat.MEDIUM中2019-6-6DateFormat.LONG中2019年6月6日DateFormat.FULL中2019年6月6日 星期六