1 动态网页
1.1 服务端、客户端
01.服务器
服务器,代码编写的一个可以根据用户请求实时的调用执行对应的逻辑代码的一个容器
在普通用户看来就是一个安装程序。我们只需要将服务器在操作系统上进行安装
并将我们事先编写好的逻辑处理代码根据规则放到服务器的指定位置
启动服务器,那么服务器就自动的会根据接收到请求调用并执行对象的逻辑代码进行处理
02.CS:Client Server
1.如果软件升级,那么全部软件都需要升级
2.维护麻烦:需要维护每一台客户端软件
3.每一台客户端都需要安装客户端软件
03.BS:Broswer Server
客户端可以通过浏览器直接访问服务端
1.2 服务端脚本语言
01.Tomcat文件说明
bin:可执行文件(startup.bat shutdown.bat)
conf:配置文件(server.xml)
lib:tomcat依赖的jar文件
log:日志文件(记录出错等信息)
temp:临时文件
webapps:可执行的项目(将我们开发的项目 放入该目录)
work:存放由jsp翻译成的java,以及编辑成的class文件(jsp ->java ->class)
02.常见错误
200:一切正常
300/301:页面重定向 (跳转)
404:资源不存在
403:权限不足 (如果访问a目录,但是a目录设置 不可见)
500:服务器内部错误(代码有误)
03.初始化页面
在项目/WEB-INF/web.xml中设置默认的初始页面(387行)
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.xhtml</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
04.JSP执行流程 jsp- java(Servlet文件) -class
D:\study\apache-tomcat-8.5.30\work\Catalina\localhost\JspProject\org\apache\jsp
Jsp和Servlet可以相互转换
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase....
1.3 虚拟路径与虚拟主机
01.虚拟路径(将web项目配置到webapps以外的目录)
a.方式一 (conf/server.xml,需要重启start.up)
<Engine>
<host>
<Host appBase="webapps"autoDeploy="true"name="localhost" unpackWARs="true">
<Context docBase="D:\study\JspProject" path="/JspProject" />
docBase:实际路径
path:虚拟路径(相对路径:相对于webapps)
</host>
</Engine>
b.方式二
D:\study\apache-tomcat-8.5.30\conf\Catalina\localhost中新建“项目名.xml”中新增一行:
<Context docBase="D:\study\JspProject" path="/JspProject" />
02.虚拟主机 (网站默认为80,http://www.uc123.com:80),通过www.test.com访问本机
a.conf/server.xml
<Engine name="Catalina" defaultHost="www.test.com"> //默认引擎
<Host appBase="D:\study\JspProject" name="www.test.com">
<Context docBase="D:\study\JspProject" path="/"/>
</Host>
</Engine>
b.通过www.test.com访问本机127.0.0.1
在C:\Windows\System32\drivers\etc\host增加一个映射,127.0.0.1 www.test.com
www.test.com->host找映射关系->server.xml找Engine的defaultHost->通过"/"映射D:\study\JspProject
1.4 Tomcat服务器
01.Apache与Tomcat比较联系
a.介绍
apache支持静态页,tomcat支持动态的,比如servlet等。
一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由tomcat来处理的。
apache可以支持php\cgi\perl,但是要使用java的话,你需要tomcat在apache后台支撑,将java请求由apache转发给tomcat处理。
b.共同点
两者都是apache组织开发的
两者都有HTTP服务的功能
两者都是免费的
c.不同点
Apache是专门用了提供HTTP服务的,以及相关配置的(例如虚拟主机、URL转发等等)
Tomcat是Apache组织在符合J2EE的JSP、Servlet标准下开发的一个JSP服务器
02.Tomcat的缺省端口是多少,怎么修改
默认8080
修改端口号方式
找到Tomcat目录下的conf文件夹
进入conf文件夹里面找到server.xml文件
打开server.xml文件
在server.xml文件里面找到下列信息
把Connector标签的8080端口改成你想要的端口
03.Tomcat的目录结构
/bin:存放用于启动和暂停Tomcat的脚本
/conf:存放Tomcat的配置文件
/lib:存放Tomcat服务器需要的各种jar包
/logs:存放Tomcat的日志文件
/temp:Tomcat运行时用于存放临时文件
/webapps:web应用的发布目录
/work:Tomcat把有jsp生成Servlet防御此目录下
04.怎么在Linux部署项目
先使用eclipse或IDEA把项目打成.war包,然后上传到Linux服务器,
然后把项目放在Tomcat的bin目录下的webapps,在重启Tomcat就行了。
05.在Tomcat中部署Web应用的方式主要有如下几种:
利用Tomcat的自动部署:把web应用拷贝到webapps目录。Tomcat在启动时会加载目录下的应用,并将编译后的结果放入work目录下。
使用Manager App控制台部署:在tomcat主页点击“Manager App” 进入应用管理控制台,可以指定一个web应用的路径或war文件。
修改conf/server.xml文件部署:修改conf/server.xml文件,增加Context节点可以部署应用。
增加自定义的Web部署文件:在conf/Catalina/localhost/ 路径下增加 xyz.xml文件,内容是Context节点,可以部署应用。
1.5 Nginx服务器
01.介绍
Nginx是一款高性能的Web服务器软件,主要用于提供网上信息浏览服务,为高并发网站的应用场景而设计,
可以在Linux、macOS和Windows等操作系统中运行,它的优点包括性能高、稳定性好、结构模块化、配置简单以及资源消耗非常低等。
02.常用功能
a.正向代理
正向代理中,proxy和client同属一个LAN,对server透明;
正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端;
b.反向代理
反向代理中,proxy和server同属一个LAN,对client透明;
反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端;
c.负载均衡
目前负载均衡有4种典型的配置方式,分别为轮询、权重、ip_hash和利用第三方模块的方式。
轮询方式 负载均衡默认设置方式,每个请求按照时间顺序逐一分配到不同的后端服务器进行处理,服务器岩机,会自动别除
权重方式 利用weight指定轮询的权重比率,与访问率成正比,用于后端服务器性能不均的情况
ip_hash方式 每个请求按访问1P的ash结果分配,这样可以使每个访客固定访问一个后端服务器,可以解决Session共享的间题
d.Web缓存方式
永久性缓存:将内容源服务器响应的内容缓存到本地,若不手动删除,该缓存文件会一直生效。
临时性缓存:采用md5算法将请求连接进行哈希后,根据具体配置生成缓存文件目录,保存响应的数据。
Web缓存服务器:位于内容源Web服务器和客户端之间,当客户端用户访问一个URL时,
Web缓存服务器就会请求相应的内容源Web服务器,并将响应的信息缓存至内存或磁盘;
然后,当下一个请求到来时,如果访问的是相同URL,Web缓存服务器会直接将已缓存的内容输出给客户端,
而不用再次向内容源Web服务器发送请求。
2 JSP服务端脚本语言
2.1 JSP页面元素
00.组成
JSP的页面元素 HTML 、java代码(脚本Scriptlet)、指令、 注释
01.java代码(脚本Scriptlet)
<% 局部变量、java语句%>
<%! 全局变量、定义方法%>
<%= 输出表达式 %>
02.指令
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.Date"%>
①language:jsp页面使用的脚本语言
②import:导入类
③pageEncoding:jsp文件自身编码 jsp ->java
④contentType:浏览器解析jsp的编码
03.注释
html注释 <!-- -->
java注释 /* */
jsp注释 <%-- --%>
2.2 JSP九大内置对象
01.九个内置对象
1)request 用户端请求,此请求会包含来自GET/POST请求的参数
2)response 网页传回用户端的回应
3)pageContext 网页的属性是在这里管理
4)session 与请求有关的会话期
5)application servlet 正在执行的内容
6)out 用来传送回应的输出
7)config servlet的构架部件
8)page JSP网页本身
9)exception 针对错误网页,未捕捉的例外
---------------------------------------------------------------------------------------------------------
其中,request、response、session、application、config这五个对象和Servlet的API是一样的。这5个对象我就不解释了。
page 【只在一个页面中保存属性,跳转页面无效】
requet 【只在一次请求中保存属性,服务器跳转有效,浏览器跳转无效】
session 【在一个会话范围中保存属性,无论何种跳转均有效,关闭浏览器后无效】
application 【在整个服务器中保存,所有用户都可以使用】
pageContext 【内置对象中最重要的一个对象,它代表着JSP页面编译后的内容(也就是JSP页面的运行环境)】
02.PageContext,ServletRequest,HttpSession,ServletContext
1)PageContext域:作用范围是整个JSP页面,是四大作用域中最小的一个;生命周期是当对JSP的请求时开始,当响应结束时销毁。
2)ServletRequest域:作用范围是整个请求链(请求转发也存在);生命周期是在service方法调用前由服务器创建,传入service方法。整个请求结束,request生命结束。
3)HttpSession域:作用范围是一次会话。生命周期是在第一次调用request.getSession()方法时,服务器会检查是否已经有对应的session,如果没有就在内存中创建一个session并返回。当一段时间内session没有被使用(默认为30分钟),则服务器会销毁该session。如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁。如果调用session提供的invalidate() ,可以立即销毁session。
注意:服务器正常关闭,再启动,Session对象会进行钝化和活化操作。同时如果服务器钝化的时间在session 默认销毁时间之内,则活化后session还是存在的。否则Session不存在。 如果JavaBean 数据在session钝化时,没有实现Serializable 则当Session活化时,会消失。
4)ServletContext域:作用范围是整个Web应用。当Web应用被加载进容器时创建代表整个web应用的ServletContext对象,当服务器关闭或Web应用被移除时,ServletContext对象跟着销毁。
---------------------------------------------------------------------------------------------------------
作用域从小到大为:PageContext(jsp页面),ServletRequest(一次请求),HttpSession(一次会话),ServletContext(整个web应用)。
03.jsp和servlet的区别、共同点、各自应用的范围
JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。
Servlet和JSP最主要的不同点在于:Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。
JSP侧重于视图,Servlet主要用于控制逻辑。
2.2.1 out:输出对象
01.汇总
out.print(char) out.println(char)
out.print(double) out.println(double)
out.print(float) out.println(float)
out.print(long) out.println(long)
out.print(String) out.println(String)
out.newLine() out.flush()
2.2.2 request:请求对象
00.汇总
String getParameter(String name):根据请求的字段名key,返回字段值value
String[] getParameterValues(String name):根据请求的字段名key ,返回多个字段值value
void setCharacterEncoding("utf-8"):设置post方式的请求编码
getRequestDispatcher("b.jsp").forward(request,response): 请求转发的方式跳转页面
ServletContext getServerContext():获取ServletContext对象
01.重定向与转发
如果request域中没有数据,使用重定向跳转response。sendRedirect()
如果request域中有数据,先request.setAttribute()将信息放到request,再请求转发getRequestDispatcher
02.请求方式
Get方式:method="get"和地址栏、重定向、超链接(<a href="xx">)请求方式,默认Get请求
Post方式:get方式在地址栏显示请求信息(但是地址栏能够容纳的信息有限,4-5KB;如果请求数据存在大文件,图片等会出现地址栏无法容纳全部的数据而出错),而post不会显示请求信息,其次,文件上传操作,必须是post
03.Get编码方式
a.统一每一个变量的编码(不推荐):new String(旧编码,新编码);
name = new String(name.getBytes("iso-8859-1"),"utf-8");
b.修改server.xml(推荐):一次性的更改tomcat默认get提交方式的编码 (utf-8)
<Connector connectionTimeout="20000" port="9999" URIEncoding="UTF-8"/>
c.对信息重新编码:request将获取的信息重新编码,即用ISO-8859-1进行编码,并将编码存放到一个字节数组中,然后再将这个数组转化为字符串
String str=request.getParameter("message");
byte b[]=str.getBytes("ISO-8859-1");
str=new String(b);
04.Post编码方式
request.setCharacterEncoding("utf-8")
2.2.3 response:响应对象
00.汇总
void addCookie( Cookie cookie ):服务端向客户端增加cookie对象
void sendRedirect(String location ) :页面跳转的一种方式(重定向)
void setContetType(String type):设置服务端响应的编码(设置服务端的contentType类型)
addHeader(String head,String value):动态添加响应头
setHeader(String head ,String value):动态添加响应头
01.对比
请求转发 重定向
地址栏是否改变 不变 改变
是否保留第一次请求时的数据 保留 不保留 --4种范围对象
请求的次数 1 2
跳转发生的位置 服务端 客户端发出的第二次跳转
02.Cookie:提高访问服务端的效率,但安全性较差
①不是内对对象,要使用必须new
②但是,服务端会自动生成一个(服务端自动new一个cookie) name=JSESIONID的cookie并返回给客户端
特别地,客户端在第一次请求服务端时,如果服务端发现此请求没有JSESSIONID,会创建name=JSESIONID的cookie并返回给客户端
03.javax.servlet.http.Cookie
public Cookie(String name,String value):产生一个cookie
String getName():获取name
String getValue():获取value
void setMaxAge(int expiry):最大有效期(秒)
04.注意事项
1.服务端准备Cookie:response.addCookie(Cookie cookie)
2.页面跳转(转发,重定向)
3.客户端获取cookie: request.getCookies();
4.服务端增加cookie: response对象;客户端获取对象:request对象
5.不能直接获取某一个单独对象,只能一次性将全部的cookie拿到
6.通过F12可以发现,除了自己设置的Cookie对象外,还有一个name为JSESSIONID的cookie,建议cookie只保存英文数字,否则需要进行编码、解码
2.2.4 session:会话对象
00.汇总
session:HttpSession对象
客户端第一次请求服务端时,服务端会产生一个session对象(用于保存该客户的信息),并且每个session对象都会有一个唯一的sessionID(用于区分其他session),服务端由会产生一个cookie,并且该cookie的name=JSESSIONID ,value=服务端sessionId的值,然后服务端会在响应客户端的同时将该cookie发送给客户端,至此客户端就有了cookie(JSESSIONID),因此客户端的cookie就可以和服务端的session一一对应(JSESSIONID - sessionID)
客户端第二/N次请求服务端时,服务端会先用客户端cookie种的JSESSIONID去服务端的session中匹配sessionid,如果匹配成功(cookie的jsessionid和sesion的sessionid)说明此用户不是第一次访问,无需登录。
01.session机制
1.session存储在服务端
2.session是在同一个用户(客户)请求时,共享
3.实现机制:第一次客户请求时,产生一个sessionid并复制给cookie的jsessionid,然后发给客户端,最终通过session的sessionid对应cookie的jsessionid
02.session方法
String getId():获取sessionId
boolean isNew():判断是否是新用户(第一次访问)
void invalidate():使session失效(退出登录、注销)
03.session属性
void setAttribute(String key, Object obj)
Object getAttribute(String key)
void removeAttribute(String key)
void setMaxInactiveInterval(秒):设置最大有效非活动时间
int getMaxInactiveInterval():获取最大有效非活动时间
2.2.5 application:全局对象
00.汇总
a.分类1
String getContextPath():虚拟路径
String getRealPath(String name):绝对路径(虚拟路径对应的绝对路径)
b.分类2
pageContext:当前页面有效,页面跳转后无效
request:同一次请求有效;其他请求无效(请求转发后有效;重定向后无效)
session:同一次会话有效(无论怎么跳转,都有效;关闭/切换浏览器后无效;登陆->退出之间全部有效)
application:全局变量,整个项目运行期间都有效(切换浏览器,仍然有效);关闭服务、其他项目无效
01.四个对象共有的方法
Object getAttribute(String name):根据属性名,或者属性值
setAttribute(String name,Object obj):设置属性值(新增,修改) 键值对 前键 后值
setAttribute("a","b"):如果a对象之前不存在,则新建一个a对象,如果a之前已经存在,则将a的值改为b
void removeAttribute(String name):根据属性名,删除对象
02.注意事项
1.以上的4个范围对象,通过setAttribute()复制,通过getAttribute()取值
2.以上范围对象,尽量使用最小的范围。因为对象的范围越大,造成的性能损耗越大
2.3 Servlet
01.JSP的生命周期方法是什么?
与servlet的init方法相同, 仅被调用一次。
它在每次请求时都被调用, 与servlet的service()方法相同。
与Servlet的destroy()方法相同, 它仅被调用一次。
02.Servlet的生命周期?
Servlet的生命周期:实例化、初始化、处理请求、销毁四个阶段。
这个声明周期由javax.servlet.Servlet接口的init(),service()和destroy方法表达。
Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。
web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现,根据请求的不同调用不同的do***()方法。结束服务,web容器调用servlet的destroy()方法。
03.Servlet 中forward()与redirect()的区别(转发和重定向)
a.从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.所以redirect等于客户端向服务器端发出两次request,同时也接受两次response。
b.从数据共享来说
forward:转发页面和转发到的页面可以共享request里面的数据
redirect:不能共享数据
redirect不仅可以重定向到当前应用程序的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源
forward方法只能在同一个Web应用程序内的资源之间转发请求.forward 是服务器内部的一种操作
redirect 是服务器通知客户端,让客户端重新发起请求。所以说 redirect 是一种间接的请求, 但是不能说"一个请求是属于forward还是redirect"
c.从跳转方式来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
d.从效率来说
forward:高
redirect:低
3 JDBC
00.什么是JDBC?
JDBC的全称是Java DataBase Connection,也就是Java数据库连接,我们可以用它来操作关系型数据库。
JDBC接口及相关类在java.sql包和javax.sql包里。
我们可以用它来连接数据库,执行SQL查询,存储过程,并处理返回的结果。
01.JDBC中的Statement 和PreparedStatement的区别?
PreparedStatement 继承于 Statement,PreparedStatement 实例包含已编译的SQL语句,所以其执行,速度要快于Statement对象
02.有哪些不同的结果集?
a.一共有三种ResultSet对象。
ResultSet.TYPE_FORWARD_ONLY:这是默认的类型,它的游标只能往下移。
ResultSet.TYPE_SCROLL_INSENSITIVE:游标可以上下移动,一旦它创建后,数据库里的数据再发生修改,对它来说是透明的。
ResultSet.TYPE_SCROLL_SENSITIVE:游标可以上下移动,如果生成后数据库还发生了修改操作,它是能够感知到的。
b.ResultSet中有两种并发类型。
ResultSet.CONCUR_READ_ONLY:ResultSet是只读的,这是默认类型。
ResultSet.CONCUR_UPDATABLE:我们可以使用的ResultSet的更新方法来更新里面的数据。
03.JDBC的DriverManager是用来做什么的?
JDBC的DriverManager是一个工厂类,我们通过它来创建数据库连接。当JDBC的Driver类被加载进来时,
它会自己注册到DriverManager类里面,然后我们会把数据库配置信息传成DriverManager.getConnection()方法,
DriverManager会使用注册到它里面的驱动来获取数据库连接,并返回给调用的程序。
04.RowSet和ResultSet的区别?
RowSet继承自ResultSet,因此它有ResultSet的全部功能,同时它自己添加了些额外的特性。
RowSet一个最大的好处是它可以是离线的,这样使得它更轻量级,同时便于在网络间进行传输。
05.常见的JDBC异常有哪些?
java.sql.SQLException:JDBC异常的基类。
java.sql.BatchUpdateException:当批处理操作执行失败的时候可能会抛出这个异常。这取决于具体的JDBC驱动的实现,它也可能直接抛出基类异常java.sql.SQLException中。
java.sql.SQLWarning:SQL操作出现的警告信息。
java.sql.DataTruncation:字段值由于某些非正常原因被截断了
JDBC的DataSource是什么,有什么好处?
DataSource即数据源,它是定义在javax.sql中的一个接口,跟DriverManager相比,它的功能要更强大。我们可以用它来创建数据库连接,当然驱动的实现类会实际去完成这个工作。除了能创建连接外,它还提供了如下的特性:
3.1 JDBC驱动
01.定义
JDBC:Java DataBase Connectivity,可以为多种关系型数据库DBMS提供统一的访问方式,用Java来操作数据库
02.Oracle
驱动jar ojdbc-x.jar
具体驱动类 oracle.jdbc.OracleDriver
连接字符串 jdbc:oracle:thin:@localhost:1521:ORCL
03.MySQL
驱动jar mysql-connector-java-x.jar
具体驱动类 com.mysql.jdbc.Driver
连接字符串 jdbc:mysql://localhost:3306/数据库实例名
04.SqlServer
驱动jar sqljdbc-x.jar
具体驱动类 com.microsoft.sqlserver.jdbc.SQLServerDriver
连接字符串 jdbc:microsoft:sqlserver:localhost:1433;databasename=数据库实例名
3.2 JDBC功能与方法
01.Oracle开启服务说明
如果仅通过sqlplus访问数据库,只需要开启:OracleServiceORCL,但通过其他程序访问数据(sqldevelop、navicate、JDBC),需要开启:OracleServiceORCL、OracleOraDb11g_home2TNSListener(监听器)
02.JDBC三大功能
1.与数据库建立连接
2.发送SQL语句
3.返回处理结果
03.JDBC三大功能,具体通过以下类/接口实现
1.DriverManager:管理jdbc驱动
2.Connection:连接,通过DriverManager产生Connection
3.Statement:增删改查,通过Connection产生
PreparedStatement:增删改查,通过Connection产生
CallableStatement:调用数据库中的存储过程/存储函数,通过Connection产生
4.Result:返回的结果集,上面的Statement等产生
04.Connection产生操作数据库的对象
Connection产生Statement对象:createStatement()
Connection产生PreparedStatement对象:prepareStatement() 区分‘d’
Connection产生CallableStatement对象:prepareCall();
05.Statement操作数据库
增删改:executeUpdate()
查询:executeQuery();
06.PreparedStatement操作数据库
public interface PreparedStatement extends Statement 继承statement
增删改:executeUpdate()
查询:executeQuery()
07.ResultSet:保存结果集
next():光标下移,判断是否有下一条数据
previous():true/false
getXxx(字段名|位置):获取具体的字段值,从1开始
3.3 JDBC访问数据库
01.JDBC访问数据库的具体步骤
a.导入驱动,加载具体的驱动类
Class.forName("oracle.jdbc.OracleDriver");
b.与数据库建立连接
Connection connection = DriverManager.getConnection(URL, USERNAME, PWD);
c.发送sql,执行
Statement stmt = connection.createStatement();
String sql = "select stuno,stuname from student";
int count = stmt.executeUpdate(sql);
ResultSet rs = stmt.executeQuery(sql);
d.处理结果集(查询)
if (count > 0) {
System.out.println("操作成功!");
}
3.4 JDBC的相关案例
3.4.1 不同数据库的连接方式
01.表结构
STUNO NUMBER 范围1~38
STUNAME VARCHAR2(22)
STUAGE NUMBER
GNAME VARCHAR2(20)
02.数据
insert into student values(1,'zs',23,'s1');
insert into student values(2,'zxs',24,'s1');
insert into student values(3,'aaxs',34,'s1');
3.4.2 pstmt与stmt的区别
01.Statement
String sql = "insert into student values(1,'zs',23,'s1')";
Statement stmt = connection.createStatement(); //无预编译
int count = stmt.executeUpdate(sql); //有sql
02.PreparedStatement
String sql = "insert into student values(?,?,?,?)"; //sql使用????占位符
PreparedStatement pstmt = connection.prepareStatement(sql); //预编译sql
pstmt.setInt(1, 36); //setXxx()替换占位符?
pstmt.setString(2, "zhangsan");
pstmt.setInt(3, 56);
pstmt.setString(4, "s3");
int count =pstmt.executeUpdate() ; //无sql
03.推荐使用PreparedStatement
1.编码更加简便,避免了字符串的拼接
2.提高性能,因为有预编译操作,预编译只需要执行一次
3.安全,可以有效防止sql注入:stmt字符串拼接引发问题
3.4.3 存储函数与存储过程
01.创建存储过程
a.定义
create or replace procedure addTwoNum(num1 in number,num2 in number,result out number) -- 1 + 2 ->3
as
begin
result := num1+num2 ;
end ;
/
b.JDBC调用存储过程的步骤
1.产生调用存储过程的对象CallableStatement cstmt = connection.prepareCall("...") ;
2.通过setXxx()处理输出参数值 cstmt.setInt(1, 30);
3.通过registerOutParameter处理输出参数类型
4.cstmt.execute()执行
5.接受输出值(返回值)
02.调用存储函数
a.定义
create or replace function addTwoNumfunction(num1 in number,num2 in number)-- 1 + 2
return number
as
result number ;
begin
result := num1+num2 ;
return result ;
end ;
/
b.JDBC调用存储函数的步骤
1.调用存储函数与调存储过程的相比,仅有一处不同
2.在调用存储函数时,需要注意参数:"{? = call addTwoNumfunction (?,?) }"
3.4.4 JDBC连接模板
01.stmt
Connection connection = null;
Statement stmt = null;
int rs = 0;
try{
//1.导入驱动,加载具体的驱动类
Class.forName("oracle.jdbc.OracleDriver");
//2.获取conn
connection = DriverManager.getConnection(URL, USERNAME, PWD);
//3.获取stmt
stmt = connection.createStatement();
//4.发送sql,执行
rs = pstmt.executeQuery("select stuno,stuname from student");
//5.处理结果集
while(rs.next()){
rs.getXxx(..);
}
}}catch(Exception e){
e.printStackTrace();
}finally{
if(rs != null) rs.close()
if(stmt != null) stmt.close();
if(connection != null) connection.close();
}
02.pstmt
Connection connection = null;
preparedStatement pstmt = null;
int rs = 0;
try{
//1.导入驱动,加载具体的驱动类
Class.forName("oracle.jdbc.OracleDriver");
//2.获取conn
connection = DriverManager.getConnection(URL, USERNAME, PWD);
//3.获取pstmt
pstmt = connection.createStatement("insert into student values(?,?,?,?)");
//4.发送sql,执行
pstmt.setInt(1, 36);
pstmt.setString(2, "zhangsan");
pstmt.setInt(3, 56);
pstmt.setString(4, "s3");
rs =pstmt.executeUpdate();
//5.处理结果集
while(rs.next()){
rs.getXxx(..);
}
}}catch(Exception e){
e.printStackTrace();
}finally{
if(rs != null) rs.close()
if(pstmt != null) pstmt.close();
if(connection != null) connection.close();
}
3.4.5 JDBC处理CLOB、BLOB
4 MVC架构
4.1 MVC架构解读
4.2 Servlet25与Servlet30
4.3 MVC经典案例
5 三层架构
5.1 三层架构解读
5.2 增删改查
5.3 增删改查-存储函数-jQuery渲染
01.操作1
SQL> create or replace procedure addTwoNum ( num1 in number, num2 in number, result out number ) -- 1 + 2 ->3
2 as
3 begin
4 result := num1+num2 ;
5 end ;
6 /
02.操作2
SQL> create or replace function addTwoNumfunction(num1 in number,num2 in number)-- 1 + 2
2 return number
3 as
4 result number ;
5 begin
6 result := num1+num2 ;
7 return result ;
8 end ;
9 /
03.操作3
SQL> create table mynovel(id number primary key, novel clob);
SQL> drop table student;
SQL> create table student(sno number primary key, sname varchar2(20), sage number, saddress varchar2(30));
04.操作4
<script type="text/javascript" src="js/jquery-1.8.3.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("tr:odd").css("background-color","lightgray");
});
</script>
5.4 增删改查-接口开发-DBUtil工具
01.DB工具
package org.student.util;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.*;
public class DBUtil {
private final static String DRIVER = "oracle.jdbc.OracleDriver";
private final static String URL = "jdbc:oracle:thin:@localhost:1521:orcl";
private final static String USERNAME = "scott";
private final static String PASSWORD = "tiger";
private static Connection con = null;
private static PreparedStatement pstmt = null;
private static ResultSet rs = null;
public static Connection getCon() {
return con;
}
public static PreparedStatement getPstmt() {
return pstmt;
}
//通用PreparedStatement
public static PreparedStatement getPreparedStatement(String sql, Object[] params) throws ClassNotFoundException, SQLException {
Class.forName(DRIVER);
con = DriverManager.getConnection(URL,USERNAME,PASSWORD);
pstmt = con.prepareStatement(sql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
}
return pstmt;
}
//通用查:返回值是一个集合
public static ResultSet executeQuery(String sql, Object[] params) throws SQLException, ClassNotFoundException {
pstmt = getPreparedStatement(sql, params);
rs = pstmt.executeQuery();
return rs;
}
//通用的增删改
public static boolean executeUpdate(String sql, Object[] params) throws SQLException, ClassNotFoundException {
boolean flag = false;
pstmt = getPreparedStatement(sql, params);
int result = pstmt.executeUpdate();
if (result > 0) {
flag = true;
}
closeAll(null, pstmt, con);
return flag;
}
//通用的close
public static void closeAll(ResultSet rs, Statement stmt, Connection con) throws SQLException {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (con != null) con.close();
}
}
5.5 增删改查-分页查询
01.MySQL分页
/**要实现分页,必须知道某一页的数据从哪里开始,到哪里结束**/
页面大小:每页显示的数据量
假设每页显示10条数据
/**mysql从0开始计数**/
第n页 开始 结束
0 0 9
1 10 19
2 20 29
n n*10 (n+1)*10-1
mysql实现分页的sql:/**limit 开始,条数**/
第0页
select * from student limit 0,10;
第1页
select * from student limit 10,10;
第2页
select * from student limit 20,10;
第n页
select * from student limit n*10,10; /**sql的分页查询语句**/
/* select * from student limit 页数*1页面大小,页面大小; */
02.Oracle分页
/*Oracle/sqlserver从1开始计数**/
第n页 开始 结束
1 1 10
2 11 20
3 21 30
n (n-1)*10+1 n*10
//此种做法前提:id值必须连续,数据无裂缝
select * from student where sno>=(n-1)*10+1 and sno<=n*10;
//如果根据sno排序,则rownum会混乱(解决方案:分开使用->先排序,再查询rownum)
select rownum,t.* from student t where sno>=(n-1)*10+1 and sno<=n*10 order by sno;
//rownum只能查询小于的数据,不能查询大于的数据
select rownum,t.* from student t where rownum>=(n-1)*10+1and rownum<=n*10 order bysno;
//(解决方案:分开使用->先排序,再查询rownum)
select s.* from student s order by sno asc; /**排序**/
select rownum,t.* from /**rownum**/
(select s.* from student s order by sno asc) t
where rownum >=(n-1)*10+1 and rownum <=n*10 ;
select * from( /**Oracle的分页查询语句**/
select rownum r,t.* from
(select s.* from student s order by sno asc) t
)where r>=(n-1)*10+1 and <=n*10 ;
select * from( /**Oracle的分页查询语句**/优化/
select rownum r,t.* from
(select s.* from student s order by sno asc) t
where rownum<=n*10
)where r>=(n-1)*10+1;
select * from( /**Oracle的分页查询语句**/优化/
select rownum r,t.* from
(select s.* from student s order by sno asc) t
where rownum<=页数*页面大小
)where r>=(页数-1)*页面大小+1;
03.SQLserver分页
/**SQLserver分页**/ :3种分页sql
row_number() over(sno order by sno asc) //进行预编译处理
/**SQLserver2003:不支持row_number(),支持top**/ 缺陷:id值不连续,则不能保证每页数据量相等
select top 页面大小 * from student
where id not in
(select top (页数-1)*页面大小 id from student order by sno asc);
/**SQLserver2005之后支持的分页查询语句**/
/**row_number() **/
select * from(
select row_number() over(sno order by sno asc)
as r,* from student
where r<=n*10
)where r>=(n-1)*10+1;
/**SQLserver2012之后支持的分页查询语句**/
/**offset ... fetch next ... only**/
select * from student
oreder by sno
offset (页数-1)*页面大小+1 rows fetch next 页面大小 rows only;
04.分页实现
1.数据总数 查数据库 select count(*) from xxx
2.页面大小 页面容量,每页显示的数据条数
3.总页数 程序自动计算
800:10= 80页 总页数=数据总数/页面大小
802:10= 800/10 +1 总页数=数据总数/页面大小+1
--通式:总页数= 数据总数 % 页面大小==0 ? 数据总数 /页面大小: 数据总数 /页面大小 + 1;
--注意:自动计算的时机:当数据总数和页面大小都被赋值以后,自动计算总页数
4.当前页码
5.当前页的对象集合(实体类集合)
List<student>
select * from student where id>=起始 and id<=终止;
6 上传、下载
01.上传文件
a.引入2个jar
commons-fileupload.jar组件,commons-fileupload.jar依赖commons-io.jar
b.<input type="file" name="spicture"/>
必须Post请求,必须增加entype="multipart/form-data"
c.限制上传
类型、大小、注意对文件的限制条件,写在parseRequest之前
02.下载文件
a.不需要依赖任何jar
b.下载文件需要设置2个响应头
response.addHeader("content-Type","application/octet-stream" );
response.addHeader("content-Disposition","attachement;filename="+fileName );
7 EL表达式
7.1 EL表达式
7.2 JSTL表达式
8 过滤器与监听器
01.概念
a.拦截器
在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法
比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
b.过滤器
在Javaweb中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,
然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),
或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符
02.过滤器和拦截器的区别
1.拦截器是基于java的反射机制的,而过滤器是基于函数回调
2.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器
3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能
5.在action的生命周期中,拦截器可以多次被调用,而过滤器只在容器初始化时调用一次
8.1 过滤器
8.2 监听器
8.3 Cookie和Session
01.Cookie和Session
Session 是「基于Cookie 实现」的另一种记录服务端和客户端会话状态的机制。
Session 是存储在服务端,而 SessionId 会被存储在客户端的 Cookie 中。
---------------------------------------------------------------------------------------------------------
Session 的「认证过程」:
客户端第一次发送请求到服务端,服务端根据信息创建对应的 Session,并在响应头返回 SessionID
客户端接收到服务端返回的 SessionID 后,会将此信息存储在 Cookie 上,同时会记录这个 SessionID 属于哪个域名
当客户端再次访问服务端时,请求会自动判断该域名下是否存在 Cookie 信息,如果有则发送给服务端,服务端会从 Cookie 中拿到 SessionID,再根据 SessionID 找到对应的 Session,如果有对应的 Session 则通过,继续执行请求,否则就中断
02.Cookie和Session的区别
作用范围不同,Cookie 保存在客户端,Session 保存在服务器端。
有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
隐私策略不同,Cookie 存储在客户端,容易被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
存储大小不同, 单个 Cookie 保存的数据不能超过 4K;对于 Session 来说存储没有上限,但出于对服务器的性能考虑,Session 内不要存放过多的数据,并且需要设置 Session 删除机制。
03.session中数据失效的情况
客户端关闭了浏览器,凭证消失,不能取得服务器内存的数据
服务器重启或关闭,服务器内存的内存清空,凭证无效
服务器设置了超时时间,当会话超过了超时时间,服务器内存被清理,凭证无效
通过程序代码清除了session中的数据
04.session何时被删除 ?
1.程序调用 HttpSession.invalidate()
2.距离上一次收到客户端发送的 session id 时间间隔超过了 session 的最大有效时间
3.服务器进程被停止
注意关闭浏览器只会使存储在客户端浏览器内存中的 session cookie 失效,不会使服务器端 的 session 对象失效 .
8.4 session绑定解绑、钝化活化
01.示例
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!--通过配置,实现钝化、活化
maxIdleSwap="5":最大空闲时间,如果超过该时间session就会自动被钝化
FileStore:配置存储路径:内存到硬盘,通过该类具体实现钝化操作
directory:相对路径(绝对路径),相对于“D:\software\Java\apache-tomcat-8.5.56\work\Catalina\localhost\090UpAndDown”
-->
<Manager classname="org.apache.catalina.session.PersistentManager" maxIdleSwap="5">
<Store classname="org.apache.catalina.session.FileStore" directory="lq"/>
</Manager>
</Context>
9 Ajax
9.1 JavaScript实现Ajax
9.2 jQuery实现Ajax
9.2.1 ajax - ajax()
https://www.w3school.com.cn/jquery/ajax_ajax.asp
9.2.2 ajax - load()
https://www.w3school.com.cn/jquery/ajax_load.asp
9.2.3 ajax - getJSON() :json格式
https://www.w3school.com.cn/jquery/ajax_getjson.asp
9.2.4 ajax - getJSON() :json对象
10 数据源连接池
10.1 Tomcat编码问题
10.2 jar引入问题
10.3 数据源连接池
10.3.1 JNDI:java命名与目录接口
01.JNDI
java命名与目录接口
将某一个资源(对象),以配置文件(tomcat/conf/context.xml)的形式写入
02.在jsp中存在四种范围对象
pageContext < request < session < application(一个项目运行期间都有效)
如何使得多个项目之间可以共享一个变量?回答:JNDI
03.实现步骤:
a.D:\software\Java\apache-tomcat-8.5.56\confcontext.xml
<Environment name="jndiName" value="jndiValue" type="java.lang.String" />
b.jsp页面使用JNDI
<%
Context context = new InitialContext();
String testJndi = (String) context.lookup("java:comp/env/jndiName");
out.print(testJndi);
%>
10.3.2 Tomcat-dbcp连接池
01.配置数据源(D:\software\Java\apache-tomcat-8.5.56\confcontext.xml)
<Resource
name="student"
auth="Container"
type="javax.sql.DataSource"
maxActive="400"
maxIdle="20"
maxWait="5000"
username="scott"
password="tiger"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1521:ORCL"
/>
02.项目指定数据源(web.xml)
<resource-ref>
<res-ref-name>student</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
03.使用数据源DataSource获取Connection:更改连接对象Connection的获取方式
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/student");
con = ds.getConnection();
} catch (NamingException e) {
e.printStackTrace();
}
10.3.3 Apache-dbcp连接池
10.3.4 c3p0连接池
10.3.5 DataSourceUtil工具类
01.DataSourceUtil工具类
package org.myslayers.util;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.Properties;
public class DataSourceUtil {
//Apache-dbcp方式一:BasicDataSource方式(硬编码)
public static DataSource getDataSourceWIthDBCP(){
BasicDataSource dbcp = new BasicDataSource();
dbcp.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dbcp.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
dbcp.setUsername("scott");
dbcp.setPassword("tiger");
dbcp.setInitialSize(20);
dbcp.setMaxActive(10);
return dbcp;
}
//Apache-dbcp方式二:BasicDataSourceFactory方式: 配置方式(.properties文件,编写方式key=value)
public static DataSource getDataSourceWIthDBCPByProperties() throws Exception{
//1.Properties对象
Properties props = new Properties();
//2.Properties对象方法:load(输入流)
InputStream input = new DataSourceUtil().getClass().getClassLoader().getResourceAsStream("dbcpconfig.properties");
props.load(input);
//3.BasicDataSourceFactory方式(核心代码)
DataSource dbcp = BasicDataSourceFactory.createDataSource(props);
return dbcp;
}
//C3P0方式一:硬编码,无参
public static DataSource getDataSourceWithC3P0() throws PropertyVetoException {
ComboPooledDataSource c3p0 = new ComboPooledDataSource();
c3p0.setDriverClass("oracle.jdbc.driver.OracleDriver");
c3p0.setJdbcUrl("jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
c3p0.setUser("scott");
c3p0.setPassword("tiger");
return c3p0 ;
}
//C3P0方式二:配置文件,有参
public static DataSource getDataSourceWithC3P0ByXml(){
ComboPooledDataSource c3p0 = new ComboPooledDataSource("myslayers");
return c3p0 ;
}
}
11 ApacheDBUtils
11.1 增删改查:自动提交+可变参数
11.2 使用ThreadLocal手动提交事务
11.3 元数据
01.元数据(MetaData):描述数据的数据
1.数据库元数据:DataBaseMetaData
2.参数元数据:ParameterMetaData
3.结果集元数据:ResultSetMetaData
02.很多数据库对元数据的支持问题
1.Oralce目前必须使用ojdbc7.jar作为驱动包
2.MySql必须在url中附加参数配置:jdbc:mysql://localhost:3306/数据库名?generateSimpleParameterMetadata=true
12 自定义标签
12.1 传统标签
12.2 简单标签
13 验证码
14 Tomcat集群
00.分布式session策略
1.sticky:固定将每一个用户的请求分给特定的服务器,后期的请求不会分给其他服务器
2.session广播(自动同步session):如果服务器太多,可能造成广播风暴
3.集中管理方式(推荐):将各个服务器的session集群存储到一个数据库中
01.Apache负载均衡
a.下载apache服务器工具
https://www.apachehaus.com/cgi-bin/download.plx
b.配置Apache
a.conf/http.conf
Define SRVROOT "D:\software\Java\Apache24\"
b.将Apache配置成windows服务:管理员身份打开cmd,通过命令注册Apache服务
"D:\software\Java\Apache24\bin\httpd.exe" -k install -n apache24
c.如果在注册apache服务时,提示“丢失VCRUNTIME140.DLL”,则需要下载并安装vc_redist.x64.exe
下载地址https://www.microsoft.com/en-US/download/details.aspx?id=48145
d.注册成功后,启动服务查看是否成功访问,localhost:80
删除服务 sc delete 服务名
VM端口占用,如果失败需要关闭VM进程后再安装
02.Tomcat-a与Tomcat-b的集群搭建
a.修改端口:conf/server.xml
server端口号 http协议端口 ajp协议端口号
tomcat-a: 1005 1080 1009
tomcat-b: 2005 2080 2009
b.配置引擎Engine:conf/server.xml
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat-b">
c.打开集群开关:conf/server.xml
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
03.Tomcat集群的配置文件
a.下载mod_jd.so 存放mod_jd.so文件的位置 \Apache24\conf\mod_jk.so
http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/windows中httpd.zip
b.存放workers.properties文件的位置 \Apache24\conf\workers.properties
worker.list=controller,tomcata,tomcatb
#tomcata
worker.tomcata.port=1009
worker.tomcata.host=localhost
worker.tomcata.type=ajp13
#负载均衡的权重
worker.tomcata.lbfactor=1
#tomcatb
worker.tomcatb.port=2009
worker.tomcatb.host=localhost
worker.tomcatb.type=ajp13
#负载均衡的权重
worker.tomcatb.lbfactor=2
#controller
worker.controller.type=lb
worker.controller.balanced_workers=tomcata,tomcatb
worker.controller.sticky_session=false
c.存放mod_jk.conf文件的位置 \Apache24\conf\mod_jk.conf,用于加载mod_jk.so和workers.properties
#加载mod_jk.so
LoadModule jk_module modules/mod_jk.so
#加载workers.properties
JkWorkersFile conf/workers.properties
#拦截请求
JkMount /* controller
d.存放httpd.conf文件的位置 \Apache24\conf\httpd.conf,Apache在启动时会自动加载httpd.conf文件
追加Include conf/mod_jk.conf
04.准备测试的工程项目
a.index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Tomcat B</title>
</head>
<body>
服务器地址:
<%
out.print(request.getRemoteAddr()+":"+request.getLocalPort() ) ;
%>
<br/>
sessionID:
<%
out.print(session.getId());
%>
</body>
</html>
b.web.xml:加入<distributable/>标签,开启session的自动同步
<distributable/>
05.测试Tomcat集群
集群情况下,CATALINA_HOME会自动启动CATALINA_HOME指定Tomcat
单机环境下就会造成多个Tomcat只能启动一个,而集群中需要开启多个不同的Tomcat
因此在单机环境下需要删除CATALINA_HOME
多机环境下可以选择不删除
例如:http://localhost:80/ClusterProject/index.jsp
06.命名细节
a.Apache的workers.properties文件
worker.list=controller,tomcata,tomcatb
b.Tomcat的server.xml文件:只需要保证所有Tomcat的jvmRoute不能重名即可,可以和Apache中的命名不一致
jvmRoute="tomcat-a"
jvmRoute="tomcat-b"
c.Tomcat的服务器文件名:普通文件名,任意
tomcat-a
tomcat-b
d.文件流程
Apache的workers.properties中配置的ip+端口,找到具体的Tomcat服务,与Tomcat中的jvmRoute没有关系
15 算法实践
15.1 魔术
15.2 字符串
15.3 糖果问题
15.4 汉诺塔问题
15.5 反射实现一个servlet处理多个请求