JSP学习
Jsp环境搭建及入门jsp的全名: JavaServer Pagesjsp的意思: 动态网页动态、静态区分不用和是否有“动感”混为一谈是否随着时间、地点、用户操作的改变而改变注:动态网页需要用到服务端脚本语言(JSP)架构CS架构:全名: Client Server(客户端服务)图示:优点:1.美观2.响应更加迅速不足:1.如果软件升级,那么全部软件都需要升级2.维护麻烦,需要维护每一台客户端软件
Jsp环境搭建及入门
jsp的全名: JavaServer Pages
jsp的意思: 动态网页
动态、静态区分
- 不用和是否有“动感”混为一谈
- 是否随着时间、地点、用户操作的改变而改变
注:动态网页需要用到服务端脚本语言(JSP)
架构
CS架构:
全名: Client Server(客户端服务)
图示:
优点:
1.美观
2.响应更加迅速
不足:
1.如果软件升级,那么全部软件都需要升级
2.维护麻烦,需要维护每一台客户端软件
3.每一台客户端都需要安装客户端软件
BS架构:
全名: Browser Server(浏览器服务)
优点: 客户端通过 浏览器直接访问服务端,弥补CS的缺点
注:BS和CS各有优势
注:JSP是基于BS的网页开发,且使用TOMCAT服务器
Tomcat
Tomcat目录
bin: 可执行文件(startup.bat shutdown.bat)
conf: 配置文件(server.xml)
lib: tomcat依赖的jar文件
log: 日志文件(记录出错等信息)
temp: 临时文件
webapps: 可执行的项目(将我们开发的项目放入该目录)
work: 存在由jsp翻译成的java,以及编辑成的class文件
注:.jsp->.java->.class,class文件才是最终执行的文件
配置tomcat
1.配置jdk(必须配置JAVA_HOME)
2.配置catalina_home 内容是tomcat的根目录
3.通过bin目录中的startup.bat可以验证是否配置成功
注:不要直接关闭tomcat,建议使用shutdown.bat关闭
常见错误
可能与其他服务的端口号冲突
tomcat端口号默认8080(此端口较为常见,容易冲突),建议修改端口
修改端口
在conf目录下的配置文件server.xml
修改端口之后可以通过在浏览器中输入网址 localhost:8888来验证是否修改成功
注:如果是IE浏览器需要加上www.的前缀
访问顺序
如果直接输入localhost:8888会按照中的文件顺序来依次寻找,直到找到存在的文件,然后访问
常见状态码
404:资源不存在
200:一切正常
403:权限不足(比如访问a目录,但是a目录设置为不可见)
3xx:页面重定向
500:服务器内部错误(代码有误)
Tomcat启动时乱码
将conf文件下的logging.properties文件中的java.util.logging.ConsoleHandler.encoding = UTF-8
改为java.util.logging.ConsoleHandler.encoding = GBK
该代码位于47行
JSP项目
Jsp项目需要的东西
1.项目/WEB-INF/lib
2.项目/WEB-INF/classes
3.项目/WEB-INF/web.xml 注:主要需要的是里面的配置信息
注:项目中的lib和 tomcat中 lib的区别是,项目中的lib中的 Jar包仅仅适用于当前项目,tomcat中的lib使用与所有的 tomcat项目
jsp的意思: 在html文件中嵌套java代码
例如:
JSP如何访问
访问路径 localhost:8888/项目名/文件名
如果wel.xml文件中目录下存在文件名
例如:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index1.jsp</welcome-file>
</welcome-file-list>
就可以通过localhost:8888/项目名来直接访问文件
如果index.jsp存在则访问它,否则访问index1.jsp
虚拟路径和虚拟主机
tomcat默认的项目路径是webapps,如果项目不放在webappps在可以通过虚拟路径来识别
注:在tomcat\server.xml文件中配置
相对路径和绝对路径
相对路径: /项目名 (建议使用)
绝对路径: D:\Apache\apache-tomcat-8.5.49\webapps\项目名
虚拟路径
docBase:实际路径
path:虚拟路径 (绝对路径,相对路径(相对于webapps))
配置虚拟路径之后,访问虚拟路径 /项目 相当于访问实际路径D:\study\项目
注:配置虚拟路径后需要重启 tomcat
还可以使用第二种方式来访问不在webapps中的项目
1.在D:\Apache\apache-tomcat-8.5.49\conf\Catalina\localhost中创建文件 项目名.xml
2.在xml文件中写入虚拟路径
注:该方式不需要重启 tomcat
注:如果使用 ROOT.xml作为文件名,那么访问的时候可以直接通过localhost:8888/文件名来访问项目(一般不这么用)
虚拟主机
可以改变访问项目的名字
例如可以将localhost/8888/文件名 ----》 www.jd.com
1.在conf.xml文件的目录下创建一个虚拟主机
<Host name="www.jd.com" appBase="D:\study\JspProject">
<Context docBase="D:\study\JspProject" path="/" />
</host>
appBase: 项目的发布路径
name: 项目的访问名
2.修改conf.xml文件中的默认主机
注:之前默认的是localhost
3.新增主机映射
文件位置: C:\Windows\System32\drivers\etc\hosts.SYS
4.将端口改成默认端口80
5.通过www.jd.com来访问我们自己写的jsp页面
JSP执行流程
第一次访问
服务端将jsp翻译成java,再将java编译成class文件
java和class的生成位置:
D:\Apache\apache-tomcat-8.5.49\work\Catalina\localhost\项目名\org\apache\jsp
注:这是第一次访问慢的原因
第二次访问
直接访问class文件
注:如果服务端代码修改了,将会在访问时重新翻译,编译
生成的JAVA文件实质
翻译命名规则: index.jsp->index_jsp.java
本质: Servlet文件
注:jsp和Servlet可以互相转换
使用Eclipse开发web项目
注:eclipse重置布局小技巧
1.用eclipse关联(集成)tomcat
Windows->Preferences->Server->Runtime Environment->add->Apache tomcat 8.5
2.创建 Dynamic Web Project
3.将创建的项目部署到tomcat
Jsp项目结构
其中WebContent是一个虚拟路径,我们可以通过localhost/8888/项目名/文件名直接访问WebContent**来目录下的文件
注:WEB-INF是一个权限很高的目录,我们无法通过localhost/8888/项目名/WEB-INF/文件名(浏览器)来直接访问,只能通过请求转发来访问
注:跳转有请求转发和重定向两种方式,只有请求转发可以访问
原因:因为有一些文件比较敏感,是基于安全原因导致WEB-INF只能通过请求转发访问
配置Tomcat运行时环境
如果创建的Jsp文件第一行报错,说明没有配置Tomcat的运行时环境,导致无法将jsp文件翻译成servlet(java)文件
1.将tomcat/lib中的servlet.jar加入项目的构建路径
2.右键项目->Build Path -> Add library ->Server Runtime
注:方法二的本质是将tomcat的lib中的api全部加入到项目中
统一字符编码
编码分类
设置jsp文件的编码
通过配置jsp文件中的PageEncoding属性,jsp->java的编码
设置浏览器读取jsp的编码
通过配置jsp文件中的Content属性
注:一般需要将上述统一设置为UTF-8(国际化编码),大小写不区分
文本编码
1.统一设置(设置Eclipse中的所有的文件,从当前时间开始)
Windows->Preferences->web->Jsp File
2.设置某一个项目的编码
右键项目->Properties->Resource
3.设置单独文件的编码
右键文件->Properties->Resource
部署Eclipse中tomcat的端口
选择第一个,是在将项目部署到eclipse的tomcat上是,复制一份tomcat使用,存储在server文件夹中
选择第二个,是指eclipse中的tomcat与本地的tomcat一致的,即将eclipse中的tomcat设置为托管模式
JSP路径问题
根目录
1.src(构建路径)
2.WebContent**(Idea中为web**)
例子
a. WebContent中有个index.jsp,index.jsp中有xxx,那么系统会在webContent和src中寻找abc
b. 对于xxx,系统会在src和Content中找QQ,然后再在QQ目录中找abc
/的含义
/出现在不同的文件有着不同的含义
web.xml:/(打头)代表着项目路径, http://localhost:8888/项目名/
例如:/WelcomeServlet的含义是http://localhost:8888/JspProject/WelcomeServlet*
.jsp:/(打头)代表服务器根路径 http://localhost:8888/
例如:/a/index.jsp的含义是http://localhost:8888/a/index.jsp
JSP中的页面元素
脚本Scriptlet
1. 局部变量、常见java语句
<%
String name = "zhangsan";
out.print("hello...." + name);
//换行
out.print("<br/>");
%>
2. 定义全局变量,定义方法
<%!
public String bookName; //全局变量`
public void init(){
bookName="java书";
}
%>
- 输出表达式
<%="hello..." + bookName %>
注:修改jsp代码不需要重启tomcat服务器,修改web.xml、配置文件、java代码需要重新启动 tomcat服务器
注:jsp中脚本中可以直接解析HTML代码,直接在里面写就行
指令
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import = "java.util.Date"%>
Page指令
位置: 写在网页的开头
属性:
language: jsp页面使用的脚本语言
import: 导入类
pageEncoding: jsp文件的自身编码 jsp->java
contentType: 浏览器解析jsp的编码
注释
html注释
<!-- -->
注:用户可以通过浏览器查看源码,所观察到
java注释
//
/* … */
JSP注释
<%-- %–>
get和post区别
get提交方式
method=“get” 和地址栏、超链接()等请求方式都默认为get方式
形式为: 链接/文件?参数名1=参数值1&参数名2=参数值2&参数名3=参数值3
post提交方式
method=“post”
形式为: 链接/文件
注:如果没有特别标明,建议使用post方式
区别
- get会在地址栏显示请求信息(但是地址栏能容纳的信息有限,大概是4kb-5kb),post不会显示
- 文件上传操作必须使用post提交方式
- 推荐使用post方式,因为get方式将信息暴露出来了,不安全
重定向和请求转发
重定向
使用:
response.sendRedirect(String location);
说明: 客户端向服务端发送两次请求,服务端返回两次响应给客户端
请求转发
使用:
request.getRequestDispatch(String location).forward(reques,response)
说明: 客户端向服务端发送一次请求,服务端进行一次浏览器内部的跳转,服务端返回一次响应给客户端
区别
请求转发 重定向
地址栏是否改变 不变 改变
是否保留第一次请求时数据 保留 不保留
请求的次数 1次 2次
如何理解
请求转发: 张三(客户端)去找李四(服务端) 办事,李四(服务端) 说:“我办不了,但是我可以去帮你找 王五(服务端) 来办”;
重定向: 张三(客户端) 去找李四(服务端) 办事,李四(服务端) 说:“我办不了,你自己去找王五(服务端) 办吧”;
JSP九大内置对象
指自带的,不需要new 也可以使用的对象
注:Jsp九大内置对象中又有四种范围对象,根据编号范围从小到大
1.out
输出对象: 向客户端输出内容
用法(常用对象)
在jsp页面中可以直接调用:
out.print(String str)
在servlet页面中:
PrintWriter out = response.getWriter();
注:在servlet调用out,会作用在请求该serlvet的jsp页面中
2.request(2.范围对象)
请求对象: 存储“客户端”向服务端发送的请求信息
用法(常用对象)
在jsp页面:
作为内置对象可以直接调用
在servlet页面:
作为doGet()和doPost()方法的形参,可以直接调用
抓取类型
1.jsp页面的form表单
<form action="">
姓名:<input type="text" name="name"><br/>
<input type="submit" value="提交">
</form>>
action的值是 数据传送的地方
2.jsp页面的超链接
<a href=""?name="xxx">提交</a>
href的值是 数据传送的地方
作用域
只在同一次请求有效
解释:
第一次请求: 通过输出姓名和密码来跳转到check.jsp页面,check.jsp可以拿到姓名和密码的信息
第二次请求: 在check.jsp页面直接通过浏览器再次访问check.jsp页面是相当于第二次请求了check.jsp页面,拿不到姓名和密码的信息
注:如果是按F5刷新的话,是相当于重新输入账号,密码从 login.jsp页面跳转到 check.jsp页面,这样是不会丢失数据的
常见方法
String getParameter(String name)
根据请求的字段名key,返回字段值value,key通常是标签内的name属性的值,value通常是根据请求的字段名key,返回字段值value,key通常是标签内的value属性的值
String[] getParameterValues(String name )
根据请求的字段名key,返回多个字段值value,常见多选按钮checkbox
void setCharacterEncoding("编码格式UTF-8")
设置请求编码,tomcat7以前默认iso-8859-1,tomcat8之后默认utf-8
getRequestDispatch("b.jsp").forward(reques,response)
请求转发的方式跳转页面,当前页面跳转到b页面
getServerContext()
获取项目的ServletContext对象
例子
使用request对象实现注册和展示功能
注册页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>注册页面</title>
</head>
<body>
<form action="show.jsp">
姓名:<input type="text" name="uname" /><br/>
密码:<input type="password" name="upwd"/><br/>
年龄:<input type="text" name="uage" /><br/>
爱好:<input type="checkbox" name="uhobbies" value="足球" /> 足球、
<input type="checkbox" name="uhobbies" value="篮球" /> 篮球、
<input type="checkbox" name="uhobbies" value="羽毛球" /> 羽毛球<br/>
<input type="submit" value="注册" />
</form>
</body>
</html>
显示页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>显示页面</title>
</head>
<body>
<%
//设置POST形式的编码,仅仅对post有效
request.setCharacterEncoding("utf-8");
String name = request.getParameter("uname");
String password = request.getParameter("upwd");
int age = Integer.parseInt(request.getParameter("uage"));
String[] hobbies=request.getParameterValues("uhobbies");
%>
注册成功<br/>
姓名:<%=name+"<br/>" %>
密码:<%=password + "<br/>" %>
年龄:<%=age + "<br/>" %>
爱好:
<%
if(hobbies!=null){
for(String hobby:hobbies){
out.print(hobby+" ");
}
}
%>>
</body>
</html>
注:使用get方法会将信息存储在地址栏,我们可以直接通过地址栏来提交信息
3.response
响应对象: 响应客户端的请求
用法(常用对象)
在jsp页面:
作为内置对象可以直接调用
在servlet页面:
作为doGet()和doPost()方法的形参,可以直接调用
常用方法
void addCookie(Cookie cookie)
服务端向客户端增加cookie对象
void sendRedirect(String loaction) throws IOException
页面跳转的一种方式,重定向
void setContentType(String type)
设置服务端content类型
cookies
介绍: 是客户端对象,不是内置对象。由服务端产生,发送给客户端保存
产生: javax.servlet.http.Cookie
作用: 相当于本地缓存的作用,可以提高效率
缺点: 因为会将数据缓存在本地(客户端),所以这导致数据安全性较差
用法
public Cookie(String name,String value)
常见方法
String getName();
获取name
String getValue();
获取value
void setMaxAge(int expiry)
设置最大有效期,单位为秒
服务端发送给客户端流程
1.创建Cookie
Cookie cookie = new Cookie(String name,String value)
2.利用response
response.addCookie(Cookie cookie)
3.页面跳转(转发,重定向都可以)
4.客户端获取cookie
Cookie[] cookies = request.getCookies()
注:不能获取某个Cookie,而是一次性获取所有的Cookie
注:建议Cookie中的name只保存数字或者英文,不然的话需要编码和解码处理
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<!-- 因为客户端是共享Cookie的,所以这里也可以访问到Cookie-->
<%!
//需要使用全局变量
String uname;
%>
<%
Cookie[] cookies = request.getCookies();
for (Cookie cookie:
cookies) {
if(cookie.getName().equals("name")){
uname = cookie.getValue();
}
}
%>
<form action="check.jsp" method="post">
姓名:<input type="text" name="uname" value="<%=uname==null?"":uname%>" /><br/>
密码:<input type="password" name="upwd"/><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
check.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>核查页面</title>
</head>
<body>
<%
String name = request.getParameter("uname");
String pwd = request.getParameter("upwd");
Cookie cookie = new Cookie("name",name);
//设置最大存在时间,单位为秒
cookie.setMaxAge(7200);
response.addCookie(cookie);
//利用重定向,将cookie发送到客户端
response.sendRedirect("success.jsp");
%>
</body>
</html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功页面</title>
</head>
<body>
登录成功<br/>
欢迎你
<%
String name = request.getParameter("uname");
out.print(name);
%>
</body>
</html>
4.Session(3.范围对象)
说明
**会话对象:**会话,即一次开始到一次结束的过程
例子:
1.浏览网站 打开-关闭 是一次对话
2.购物 浏览-付款-退出 是一次对话
用法(常用对象)
在jsp页面:
作为内置对象可以直接调用
在servlet页面:
HttpSession session = request.getSession();
运行机制(原理)
1.客户端在第一次请求服务端的时候,会生成一个Session对象(用于保存该客户的信息)
2.每个Session对象都会有一个唯一的SessionID(用于区分其他Session)
3.服务端会产生一个Cookie,并且该Cookie的name是JSESSIONID,key是SessionID
4.服务端会在响应客户端的时候,将Cookie发送给客户端
5.客户端中的Cookie就可以合服务端中的Session一一对应(实际上是通过JSEIONID和SessionID)
作用: 服务端通过JSESSIONID来区别客户
注:客户端会通过JSESSIONID去和服务端中的 Session通过 SessionID进行匹配
如果匹配成功,说明此用户不是第一次访问,将服务端存储的信息显示给客户端
如果匹配失败,就是第一次访问,就行处理
理解
**客户端:**顾客
**服务端:**商场存包处
JSESSIONID: 钥匙
SessionID: 柜子
Session中的信息: 柜子中的物品
情景:
顾客去商场存包处
处理:
商场存包处会通过顾客手中是否有钥匙(并且钥匙要和柜子匹配)来判断是否是新顾客,
如果顾客手中没有钥匙说明是新顾客,就分配一把钥匙给新顾客
如果手中有钥匙说明是老顾客,就不用分配钥匙
一个钥匙和一个柜子一一对应,顾客可以通过钥匙来获取柜子中的物品
Session特点
1.session存储在服务端
2.session是在同一个用户请求时共享,即每一个顾客都有一个只属于自己的柜子
3.session同一次会话共享
解释: session在同一次会员中,所有的页面都可以访问到session,但是切换浏览器就需要重新进行会话过程
注:Session存储在服务端,Cookie存储在客户端
方法
String getId()
获取sessionId
boolean isNew()
判断是否是 新用户(第一次访问)
void invalidate()
使session失效(场景为:退出登录,注销),实际是清空session对象里的东西,并不是清除session这个对象本身
void removeAttribute(String str)
清空某个session对象(一般使用invalidate())
void setAttribute(String str,Object obj)
利用session来保存信息,使用key-value对的形式
void getAttribute(String str)
获取session中保存的信息
Object setMaxInactiveInterval(int s)
设置最大有效 非活动时间 单位为秒
int getMaxInactiveInterval()
获取最大有效 非活动时间 单位为秒
非活动时间: 浏览器没有经过任何操作的时间
### 例子
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<form action="check.jsp" method="post">
姓名:<input type="text" name="uname" /><br/>
密码:<input type="password" name="upwd"/><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
check.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>核查页面</title>
</head>
<body>
<%
String name = request.getParameter("uname");
String pwd = request.getParameter("upwd");
if("zs".equals(name)&&"abc".equals(pwd)){
//说明成功登录
response.sendRedirect("success.jsp");
session.setAttribute("name",name);
}else {
response.sendRedirect("login.jsp");
}
%>
</body>
</html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功页面</title>
</head>
<body>
登录成功<br/>
欢迎你
<%
String name = (String) session.getAttribute("name");
if(name!=null) {
out.print(name);
}else {
request.getRequestDispatcher("login.jsp").forward(request,response);
}
%>
</body>
</html>
Cookie和Session的区别
Session Cookie
保存位置 服务器 客户端
安全性(相对) 安全 不安全
保存的内容 Object String
5.Application(4.范围对象)
说明
**全局对象:**获取当前项目的所有信息
用法(常用对象)
在jsp页面:
作为内置对象可以直接调用
在servlet页面:
HttpSession session = req.getSession();
ServletContext application = request.getServletContext();
方法
String getContextPath()
获取虚拟路径
String getRealPath(String name)
获取绝对路径(虚拟路径对应的)
6.Config
说明
配置对象
用的较少
7.page
说明
当前页面对象:相当于Java的This
用的较少
8.pageContext(1.范围对象)
说明
JSP页面容器对象
用的较少
9.exception
说明
异常对象
用的较少
四种范围对象
共有的方法
Object getAttribute(String name)
根据属性名获取属性值
void setAttribute(String name,Object obj)
设置属性值
void removeAttribute(String name)
根据属性名删除对象
作用范围
注:根据编号从小到大
1.pageContext
范围: 当前页面有效
2.request
范围:同一次请求有效
解释: 请求转发有效,重定向无效
3.session
范围:同一次会话有效
解释: 关闭(切换)浏览后无效
4.application
范围:整个项目(全局)有效
解释: 整个项目运行期间,切换浏览器也有效。关闭浏览器,关闭项目后无效
注:以上四个范围对象都是通过 以上的三个方法进行取值和赋值,而且尽量使用范围最小的对象,这样可以减小开销,降低性能的损耗
JDBC
全名: java DataBase Connectivity
作用
图形示例
为多种关系型数据库DBMS 提供统一的访问,用java的方式来操作数据库
JDBC API主要功能
DriverManager: 管理JDBC驱动
Connection: 连接数据库
Statement(PreparedStatement) : 发送增删改查语句
CallableStatement: 调用数据库中的 存储过程/存储函数
Result: 返回的结果集
数据库驱动对应的jar包
数据库 驱动jar包
Oracle -------- ojdbc-x.jar
MySQL-------- mysql-connection-java-x.jar
SqlServer----- sqljdbc-x.jar
注:x是版本号,使用的jar版本要和数据库版本一致
JDBC访问数据库的步骤
1.导入驱动包,加载具体的驱动类
2.与数据库建立连接
3.获取操作数据库的对象
4.处理结果集(针对查询操作)
例子
public class JdbcTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动程序
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/book?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8", "root", "root");
//3.获取操作数据库的对象,三种
Statement statement = connection.createStatement();
String sql = "select * from category";
ResultSet resultSet = statement.executeQuery(sql);
//4.处理结果集
while (resultSet.next()){
int id = resultSet.getInt("id");
String cname = resultSet.getString("cname");
System.out.println("id:" + id + " cname" +cname);
}
statement.close();
connection.close();
}
}
statement
用法:
通过连接获取Statement对象
Statement statement = connection.createStatement();
Statement接口:
- 用于执行静态SQL语句并返回它所生成结果的对象。
三种Statement类:
- Statement:
- 由createStatement创建,用于发送简单的SQL语句(最好是不带参数的)
- PreparedStatement:
- 继承Statement接口,由preparedStatement创建,用于发送含有一个或多个输入参数的sql语句。PreparedStatement对象比Statement对象的效率更高,实行是参数化查询,这样可以防止SQL注入。
- CallableStatement:
- 继承自PreparedStatement。由方法prePareClas创建,用于调用存储过程。
常用的Statement方法:
execute():
运行语句,返回是否有结果集。executeQuery():
运行select语句,返回ResultSet结果集executeUpdate():
运行insert/update/delete操作,返回更新的行数
ResultSet接口:
- Statement执行SQL语句时返回ResultSet结果集
- ResultSet提供的检索不同类型字段的方法,常用的有:
getString()
:获得在数据库里是varchar、char等数据类型的对象getFloat():
获得在数据库里是Float类型的对象getDate():
获得在数据库里是Date类型的数据getBoolean():
获得在数据库里是Boolean类型的数据
注:处理结果集ResultSet,使用的方式很像迭代器,但是并不是迭代方式
关闭的顺序:要分开关闭
- ResultSet
- Statement
- Connection
PreparedStatement(推荐)
用法
通过connection获取preStatement对象
Preparedstatement pstm = connection.PreparedStatement();
例子
public static int delete(int id) throws SQLException {
Connection connection = linkDataBase();
String sql = "delete from category where id = ?";
PreparedStatement pstm = connection.prepareStatement(sql);
pstm.setInt(1,id);
int update = pstm.executeUpdate();
pstm.close();
connection.close();
return update;
}
优势
1.编码更加简便(避免的了字符串的拼接)
String sql = " insert into student(stuname,stuage) values('"+name+',"age") ";
stmt.executeUpdate(sql);
使用statement的sql语句,遇到char类型需要加’ ';
String sql = " insert into student(stuname,stuage) values(?,?) ";
//预编译SQL
pstm = connection.prepareStatement(sql);
pstm.setString(1,name);
pstm.setInt(2,age);
使用preparedStatement,就可以直接用?充当占位符
2.提高性能
在重复使用sql语句的过程中。因为预处理的过程,preparedStatement只需要编译一次(预编译),而Statement需要编译多次,这样提高了性能
3.安全(可以有效的防止sql注入)
sql注入: 将客户输出的内容与开发人员的SQL语句混为一起
例如:
在实行登录操作的时候的sql语句
select count(*) from login where name = '"+name+"'and pwd='"+pwd+"'
我们可以通过name= 任意值’ or 1=1 --来完成sql注入
select count(*) from login where name = '任意值' or 1=1 --'and pwd='任意值';
注:该语句相当于
select count(*) from login;
分析:
对于上诉的sql语句,name=‘任意值’ 为false,1=1为true, 所以总结果为true,而且 – 为注释符号,后面的全部被注释了,这样就可以跳过sql的检查,直接登录成功
原因: preparedStatement会自动帮我们补齐’ ',这样可以避免SQL注入
CallableStatement
用法
CallableStatement cstm = con.prepareCall("存储过程或存储函数");
例子
//调用存储过程
public static int invokeProcedure() throws SQLException {
Connection con = linkDataBase();
CallableStatement cstm = con.prepareCall("{call addTwoNum(?,?,?)}");
cstm.setInt(1,20);
cstm.setInt(2,30);
//设置返回值类型
cstm.registerOutParameter(3, Types.INTEGER);
cstm.execute();
int result = cstm.getInt(3);
cstm.close();
con.close();
return result;
}
//调用存储函数
public static int invokeFunction() throws SQLException {
Connection con = linkDataBase();
CallableStatement cstm = con.prepareCall("{?=call addTwoNum(?,?)}");
cstm.setInt(2,20);
cstm.setInt(3,30);
//设置返回值类型
cstm.registerOutParameter(1, Types.INTEGER);
cstm.execute();
int result = cstm.getInt(1);
cstm.close();
con.close();
return result;
}
JSP访问数据
说明
Jsp就是在Html中嵌套Java代码,因此Java代码可以写在jsp中(<% … %>)
导包操作
注:针对idea
Java项目:
1.将jar复制到项目中,然后add as Lirbary
2.点击Project Structure->Project Settings->Modules->Dependencies->add jar
Web项目:
1.直接将jar包复制到WEB-INF/lib中,然后add as libary
缺点
在jsp页面写java代码会导致代码十分混乱,所以我们在src目录下写java代码
命名规范
xxxDao(数据访问层): 用于访问数据库
例子
check.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>核查页面</title>
</head>
<body>
<%
String name = request.getParameter("uname");
String pwd = request.getParameter("upwd");
LoginDao dao = new LoginDao();
int result = dao.login(name, pwd);
if(result>0){
request.getRequestDispatcher("success.jsp").forward(request,response);
}else if (result==0){
out.print("账号或者密码错误");
}else {
out.print("系统错误!!!");
}
%>
</body>
</html>
LoginDao.java
package JspAndDataBase;
import java.sql.*;
public class LoginDao {
public static Connection getConnection(){
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jsp?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8", "root", "root");
return connection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void close(Connection conn, PreparedStatement pstm, ResultSet rs) throws Exception{
if(conn!=null) conn.close();
if(pstm!=null) pstm.close();
if (rs!=null) rs.close();
}
public int login(String name,String pwd) {
int result = -1;
PreparedStatement pstm=null;
Connection con = null;
ResultSet rs= null;
int index = 0;
try {
String sql = "select count(*) from login where name= ? and password=?";
con = getConnection();
pstm = con.prepareStatement(sql);
pstm.setString(1,name);
pstm.setString(2,pwd);
rs = pstm.executeQuery();
while (rs.next()){
index++;
}
result = index;
return index;
} catch (SQLException e) {
e.printStackTrace();
return result;
}finally {
try {
close(con,pstm,null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
注:如果Jsp出现错误:The import Xxxx Cannot be resolved
解决方案:
a: 可能是tomcat和jdk的版本问题,右键build Path,删除其中报错的Libary和lib,重新导入
b: 清空各种缓存,Clean Tomcat,Clean Project,或者进入Tomcat删除work的子目录
c: 删除tomcat,然后重启后重新安装,配置
d: 如果之前类没有包,那么就将该类加入包中
JavaBean
定义
实质上是一个java类
要求满足以下两点:
1.public修饰的类,具有public 无参构造
2.所有属性都是private,并且实现get,set方法(如果是boolean类型,可以用is方法代替get方法)
注:系统自动提供的无参构造是public修饰的,所以上述的LoginDao.java也是一个JavaBean
作用
1.减轻jsp的复杂度
2.提高代码复用(例如:以后登录只需要调用LoginDao.java)
分类
封装数据的javaBean
数据
package JavaBean;
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
注:一般对应于数据库中的一张表
优点
缺点:如果不使用JavaBean,用之前的传值方式,一旦需要传的值太多的话,那么需要传递很多数据,很麻烦
优势:使用JavaBean将数据封装成一个类对象,那么无论需要传递多少值,都只需要传递一个类对象
封装业务逻辑的JavaBean
逻辑
之前写的LoginDao.java
注:用于操作一个封装数据的一个JavaBean
MVC设计模式
MVC概念图示
MVC流程图示
Model(模型)
作用:
实现功能(例如,增加,删除)
实现:
利用JavaBean实现
View(视图)
作用:
用于展示、以及与用户交互
实现:
html、js、css、jquery等前端技术实现
Controller(控制器)
作用:
1.接收请求,将请求跳转到模型进行处理
2.模型处理完毕,将处理结果返回给请求处
实现:
可以用jsp实现 (不推荐)
建议使用Servlet实现
注:Jsp->Java(Servlet)->Class
Servlet
要求
Java类必须符合一定的规范
a. 必须继承 javax.servlet.http.HttpServet
b. 重写其中的doGet()或doPost()方法
doGet: 接收 并 处理 所有的get提交方式的请求
doPost: 接收 并 处理 所有的post提交方式的请求
注:一般而言,无论是访问doGet还是doPost都是用一个方法去解决
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Welcome..........");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
使用
要想使用Servlet需要配置
Servlet2.5版本
要求: 配置web.xml
流程示意图:
解释:
1.jsp页面请求Servlet处理
2.请求被标签拦截
3.根据标签中的寻找标签中标签(二者同名)
4.中的标签访问对应的Servlet类(全类名)
注:标签中填入的应该是请求访问的页面在项目的相对路径,
注: /WelcomeServlet
例如:
下面的例子中,servlet.jsp所在的目录是WebContent/Servlet/servlet.jsp,所以标签内的路径为
/Servlet/WelcomeServlet
注:/WelcomeServlet的含义是http://localhost:8888/JspProject/WelcomeServlet
例子
servlet.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="WelcomeServlet">WelcomeSerlvet</a>
</body>
</html>
WelcomeServlet.java
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Welcome..........");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>WelcomeServlvet</servlet-name>
<servlet-class>Servlet.WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WelcomeServlvet</servlet-name>
<!-- 相对路径为请求的jsp页面的路径-->
<url-pattern>/Servlet/WelcomeServlet</url-pattern>
</servlet-mapping>
</web-app>
Servlet3.0版本
要求: 不需要配置web.xml,只需要在Servlet类的之上写注解@webServlet(“的值”)
解释: 请求地址与注解@webServlet中的值进行匹配,如果匹配成功,则说明请求的就是注解的Servlet类
WelcomeServlet2.java
//注解的内容为请求页面的相对路径
@WebServlet(value="/JspServlet/WelcomeServlet2")
public class WelcomServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(".................Welcome....");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
servlet.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="WelcomeServlet2">WelcomeSerlvet</a>
</body>
</html>
注:对于注解@WebServlet("/WelcomeServlet2")
与@WebServlet(urlPatterns ="/WelcomeServlet2")
是等价的
注:对于注解@WebServlet("/WelcomeServlet2")
与@WebServlet(value ="/WelcomeServlet2")
也是等价的
生命周期
Servlet的生命周期为5个
加载: Servlet容器自动处理
初始化: 该方法会在Servlet被加载的时候自动执行 只在Servlet被第一次访问的时候执行一次(可修改),且执行一次
服务: 主要是doget()和doPost两个方法 调用几次,执行几次
销毁: Servlet被系统回收时会自动执行 只在tomcat关闭时执行,且只执行一次
卸载: Servlet容器自动处理
初始化详解
第一次访问Servlet时会执行,且只执行一次(默认,但可以修改成Tomcat启动时自动执行)
修改方式:
对于Servlet2.5:
<servlet>
<servlet-name>WelcomeServlvet</servlet-name>
<servlet-class>Servlet.WelcomeServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
加入1这段代码,可以让init()在tomcat启动时执行
对于Servlet3.0:
//注解的内容为请求页面的相对路径
@WebServlet(urlPatterns = "/JspServlet/WelcomeServlet2",loadOnStartup = 1)
public class WelcomServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(".................Welcome....");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
注:1的意思为,当存在多个Servlet需要Tomcat启动时自动执行,执行的顺序
Servlet API
组成: Http协议的软件包+除Http协议以外的其他软件包(即Servlet API适用于所有的通信协议)
注: 这次主要是学习javax.servlet.http,即 Http协议的软件包中类和接口,是基础的 HTTP协议
其中,单个是继承,三个的是实现
ServletConfig
成分: 接口
方法
ServletContext getServletContext();
获取Servlet上下文对象,返回值用于创建application对象
String getInitParameter(String name);
在当前Servlet范围内,获取名为name的参数值(初始化参数)
注:ServletContext类中同样有一个方法为String getInitParameter(String name);
例子:
WelcomeSerlvet.java
public class WelcomeServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("init.......");
//获取当前servlet的初始化参数值
String servletValue = super.getInitParameter("servletParamter");
System.out.println("servletValue: " +servletValue);
//获取整个容器的初始化参数值
ServletContext servletContext = super.getServletContext();
String globalValue = servletContext.getInitParameter("globalParamter");
System.out.println("globalValue: " +globalValue);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Welcome..........");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>WelcomeServlvet</servlet-name>
<servlet-class>Servlet.WelcomeServlet</servlet-class>
<!-- 要求放在<load-on-startup>上面-->
<init-param>
<!-- 当前Servlet的初始化参数-->
<param-name>servletParamter</param-name>
<param-value>servletvalue...</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<context-param>
<!-- 整个容器的初始化参数 -->
<param-name>globalParamter</param-name>
<param-value>globalVale</param-value>
</context-param>
<servlet-mapping>
<servlet-name>WelcomeServlvet</servlet-name>
<!-- 相对路径为请求的jsp页面的路径-->
<url-pattern>/JspServlet/WelcomeServlet</url-pattern>
</servlet-mapping>
</web-app>
注:Servlet3.0版本同样是在注解中写,如下所示,并且Servlet3.0不能通过注解配置整个容器的初始化参数,只能通过web.xml
@WebServlet(initParams = {@WebInitParam(name="ServletParamter",value = "ServletValue")})
Servlet
重点是sevice方法,他是服务过程调用的函数
所以对象req,和对象resp的方法为JSP中 request和response的方法,其中就包括了请求转发和重定向
解释
void service(ServletRequest servletRequest, ServletResponse servletResponse)
上述的方法来着接口Servlet
public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
抽象类GenericServlet继承该方法
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(lStrings.getString("http.non_http"));
}
service(request, response);
}
}
抽象类HttpServlet继承了GenericServlet,并且重写了该方法,主要是将req,和res转换成只被http协议访问的参数
然后http重载了service方法,然后将请求分类(get,post…),然后调用对应的方法进行处理,例如get请求就调用doGet()方法
空实现的优势
实际上这是设计模式中的接口适配器模式
如果不使用空实现,那么实现类在实现接口的时候需要实现所有的抽象方法,就算是只使用其中一个方法,也得全部实现
例如: 我只需要使用add()方法,但是我却要把上述三个方法都实现
如果使用空实现,因为我们空实现类已经实现(空实现)了接口的所有抽象方法,所以当我们需要哪个方法时,只需要继承空实现类,然后重写该方法即可
例如: 我需要add()方法,我只需要写一个add类来继承空实现类,然后重写其中的add()方法
MVC实例
图示
modul层
数据存储的JavaBean
package mvcTest.entry;
//JaveBean
public class Login {
private String name;
private String password;
public Login(){
}
public Login(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
业务逻辑的JavaBean
package mvcTest.dao;
import mvcTest.entry.Login;
import java.sql.*;
public class LoginDao {
public static Connection getConnection(){
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jsp?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8", "root", "root");
return connection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void close(Connection conn, PreparedStatement pstm, ResultSet rs) throws Exception{
if(conn!=null) conn.close();
if(pstm!=null) pstm.close();
if (rs!=null) rs.close();
}
public static int login(Login login) throws Exception {
int flag=0;
Connection con = getConnection();
String sql = "select count(*) from login where name=? and password = ?";
PreparedStatement pstm = con.prepareStatement(sql);
pstm.setString(1,login.getName());
pstm.setString(2,login.getPassword());
ResultSet rs = pstm.executeQuery();
while (rs.next()){
flag++;
}
close(con,pstm,rs);
return flag;
}
}
view层
Login.jsp 路径:web/mvcTest/Login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<form action="LoginController" method="post">
姓名:<input type="text" name="uname" /><br/>
密码:<input type="password" name="upwd"/><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
**success.jsp ** **路径:**web/mvcTest/xx/success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
登录成功!!!!!!!!!!!!!!!!!
</body>
</html>
controller层
package mvcTest.controller;
import mvcTest.entry.Login;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import static mvcTest.dao.LoginDao.login;
@WebServlet("/mvcTest/LoginController")
public class LoginController extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("uname");
String password = request.getParameter("upwd");
Login login = new Login(name,password);
System.out.println(login.getName());
try {
int result = login(login);
if(result>0){
//路径为请求页面的相对路径
response.sendRedirect("xx/success.jsp");
}else {
response.sendRedirect("login.jsp");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
三层架构(ThreeTiar)
与MVC设计模式设计的初衷一致,都是为了 解耦合,提高代码复用度
但是,二者对于项目的理解不同
表示层
全名: USL (User Show Layer)
常用名: 视图层
前台代码
作用: 对应于MVC中的View,用于和用户交互,界面的显示
实现技术: jsp js html css jquery等前端技术实现
位置: WebContent
后台代码
作用: 对应于MVC中的Controller,用于控制跳转,调用业务逻辑
实现技术: Servlet (SpringMVC Struts2)
位置: xxx.servlet包中
业务逻辑层
全名: BLL(Business Logic Layer)
常用名: dao层
作用:
– 用于组装数据访问层,带逻辑性的操作
– 用于接收表示层的请求,调用
位置:xxx.service包中(主流)或者xxx.manager或xxx.bll
数据访问层
全名: DAL(Data Access Layer)
常用名 : service层
作用: 直接访问数据库的操作,原子性的操作(增删改查)
位置: xxx.dao包中
图示
流程:
上层将请求发送给下层,下层处理完返回给上层
比MVC模式比较
三层架构中不包括实体类,但是需要实体类来进行数据的传递
三层架构的关系
上层将请求发送给下层,下层处理完返回给上层
上层依赖于下层,即上层持有下层的成员变量
例如:A类中有B类的对象,那么A类依赖于B类
class A {
private int id;
private B b;
}
class B{
private int id;
}
优化
建议面向接口编程:即先接口,再实现类
接口和实现类命名规范:
接口(interface): XXXX 例如:StudentService StudentDao
实现类(implements): XXXXImple StudentServiceImpl StudentDaoImpl
页面分页
MySQL实现分页
假设每页显示10条数据
第n页 开始 结束
0 ------- 0------------- 9
1 ------- 10----------- 19
n ------- n*10 -------- (n *10)+9
注:mysql计数是从0开始
sql语句: select * from table limt 0,10 获取第一页的数据
数据需求
1.总数据的数量
2.页面大小(每页数据的条数)
3.总页数(可以根据总数据数量和页面大小计数得到)
4.当前页面
5.当前页面的数据集合
流程图示
更多推荐
所有评论(0)