Java Web
基础概念
web开发:
- web–网页
- 静态web
- html, css…
- 提供给所有人看不会发生变化的.
-
动态web
- 京东…几乎所有的网站
- 提供的数据始终在变化,每个人看到的都不相同
- 技术栈:Servlet/jsp, asp, php
在java中,动态web资源开发的技术统称javaweb
web应用程序:
- 可以提供浏览器访问的程序,例如…
- 我们每一个访问的页面或资源,都存在于世界上某一个角落的计算机上
- 这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat:服务器
- 一个web应用由多部分组成 (静态web,动态web)
- html,css,js
- jsp,servlet
- Java程序
- jar包,配置文件 (Properties)…
静态web:
*.htm/ *.html这些都是网络后缀,需要一个统一的服务器管理;
缺点:除了不能动,不能更新,没有特效,无法跟数据库交互,无法跟用户交互几乎没有缺点.
动态web:
缺点:当动态资源出现问题时,我们需要重新编写我们的后台程序,重新发布;(停机维护)
web服务器(实现手段)
ASP:
- 微软: 国内最早流行的
- 在html中嵌入VB脚本
- 在ASP开发中,基本上一个页面上有html,java,css等代码,全部嵌套在一起
- 主要应用c#语言,维护成本高,iis服务器
PHP:
- 开发速度快,功能强大,跨平台,代码简单(优点)
- 无法承载大访问量的情况–中小型开发(缺点)
JSP(Servlet):
- sun公司主推的B/S架构
- 基于java语言开发(几乎所有大公司都用java)
- 可以解决高并发,高可用,高性能(三高问题)
搭建Web环境
c/s架构与b/s架构
- c/s架构需要有客户端才能进行操作,需要进行更新等
- b/s架构只需要打开浏览器就可以直接操作
- b/s架构原理:基于请求与响应–客户发送请求信息,服务器运行程序返回检索到的信息
随着5G时代的到来,b/s架构会更受欢迎
URL
/news/200/?page=6
其中:
- http 是协议
- 是主机地址
- /news/200/ 是目标资源地址
- ?page=6 是传递的参数
URL (Uniform Resource Locator) “统一资源定位符"
万维网中统一默认端口号是80,默认协议是http,这些都是不用你直接输入的
WEB服务器
服务器是一种被动的操作,用来处理用户请求返回一些响应信息.
Web服务器可以向发出请求的浏览器提供文档的程序,以提供上网的功能(运行Web程序的)
常见的web服务器
- IIS: 微软自带服务器
- Nainx
- Apache: Tomcat
Tomcat服务器
Tomcat是由Apacha软件基金会出品,Apacha是一个专门支持开源软件的基金会.
Tomcat官网; http://tomcat.apache.or
启动:
- bin\
- 访问Tomcat主页: http://localhost:端口号
- 关闭: bin\
访问:
- 将解压好的项目放进webapps文件夹里面,必须以文件夹的形式
- 先启动Tomcat然后再在浏览器里输入localhost:8080/文件夹名
特点:
- Apache Jakarta的开源项目
- 轻量级应用服务器
- 开源,稳定,资源占用小
坑:
- 如果Tomcat运行不了,那就去配置jdk,(只能有一个jdk)
- 提示80端口被占用,那就去卸载 服务-sql sever
- 放进webapps里的文件想要打开就必须放进文件夹里
目录:
- bin : 执行与开关闭
- conf : 配置文件
- lib : 所有的jar包
- logs ; 日志文件
- temp : 临时文件
- webapps : 今后所有程序的放置位置
- work : Tomcat把由jsp生成的Servlet放于此(无意义)
小结:
-
Tomcat浏览器访问方式: localhost:8080(本地ip地址:端口号)
-
conf/文件
-
可以更改端口号
-
可以更改主机名称
-
补充:高难度面试题:
请你谈谈网站是如何进行访问的!
-
输入一个域名;回车
-
检查本机的 C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;
-
有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
127.0.1 www.linghuchong.com//在hosts文件里
- 1
-
没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;
-
Http
含义
HTTP(超文本传输协议):一个简单的请求-响应协议,通常运行在Tcp之上
端口:80
- 1
HTTPS: 端口443
两个时代:
- http1.0: 客户端与web服务器连接后,只能获得一个web资源并断开连接
- http1.1: 一次可以获得多个web资源
Http请求
- 客户端 – 发请求 – 服务器
Http响应
- 服务器 – 响应 – 客户端
部署自己的web项目(idea)
视频在–第十五周–1213–视频文件夹
- 在idea里面先创建一个java项目
- 项目右键添加框架支持–web应用程序4.0
- 添加配置-汤姆猫
- 项目结构-全局库-添加进去
- // 上边栏设置按钮–工件–点击+号–web应用程序:存档–对于’…’
- // 点击最上方栏–构建–构建工件–项目名:war–构建
- // 构建完左边项目里就会出现out文件夹(里面找到war文件)
- // 将war文件放入Tomcat里的webapps文件夹,然后点击Tomcat运行,就会解压,解压成一个文件夹的形式
- 在浏览器里输入localhost:8080/项目文件夹名访问自己创建的项目
- 一个网站应该有的结构:
--webapps :Tomcat服务器的web目录
-ROOT
-linghuchong :网站的目录名
- WEB-INF-classes : java程序
-lib:web应用所依赖的jar包
-web.xml :网站配置文件
- index.html 默认的首页
- static
-css
-style.css
-js
-img-...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
在idea里面配置Tomcat
- 在idea中右上角有个添加配置-- 点击+号
- 找到Tomcat服务器-本地
- 注意这里也可以进行端口号的修改
- 修改jdk,找到自己的jdk安装目录
- 在上栏找到部署 --工件–可选war包跟war exploded(扩展包)
war包跟war exploded包的区别:
-
前者是需要解压然后才能运行的, 后者不需要.一般练习用测试包就可以,这样减少资源的浪费,上传到服务器端项目的时候才会用war包
-
然后睡觉哦应用程序的上下文–这里注意小写英文字母就可以了
JSP(Java跟html的结合)
初识 jsp
JSP:(Java Server Pages)
在 JSP 文件中,HTML 代码与 Java 代码共同存在,其中,HTML 代码用来实现网页中静态内容的显 示,Java 代码用来实现网页中动态内容的显示。
特点:
- 跨平台:适用于各大主流系统平台运行
- 业务代码相分离(运行原理)
- 组件重用
- 预编译
运行原理:
一些jsp代码指令
基本结构: <% 内容 %>
<%@ **page **contentType=“text/html;charset=UTF-8” language=“java” %>
page指令:
-
用于表明这是一个jsp;
-
他用来设置JSP文件中的全局属性;
-
language=“java"声明脚本语言的种类,暂时只能用"java”.
注意:
-
在 page 指令中区分大小写,不限制指令的位置、个数,JSP 指令对整个页面有效
-
contentType主要是告诉浏览器自己是什么类型的文件,同时要求浏览器以什么编码进行解析
out 输出:
// 向页面输出
<% (); %> / <% (); %>
- 1
- 2
注意做到这一步会产生一个报错,具体解决的途径是导入jar包,具体步骤如下:
- 导包: 找到Tomcat安装目录–lib–找到
- 在 idea 目录中 WEB-INF 中新建一个 lib 文件夹复制刚才的 jar 文件
- 右键点击 jar 包–添加为库
- 右侧栏–项目结构–右键点击–置于…
注意:
-
直接用上面的语句会产生一个问题-- 可读性不好(java代码与heml代码混在一起,且不利于修改)
解决方法: 声明变量,利用标签进行解决
如下:
<% String name = "张三";//声明变量 // 向页面输出 ("我叫"+name); %> <%="我叫"+name%>//<!--跟上面的是一样的,注意name后面不要写;-->
- 1
- 2
- 3
- 4
- 5
- 6
-
使用< %@page%>导包 如:< %@page import=“”%>
-
输出转义字符。 如:<%=“谈”\北京精神\ “”%>(转义字符代表的是你先使用/输出这个符号,而不是它在这里面本身的作用–这里指字符串用“”括起来。)
注释:
- HTML注释:
- JSP注释: <%–JSP注释–%>
- JSP脚本中注释<%//单行注释%> <%/* 多行注释*/%>
<%@ page import="" %>
<%@ page import="" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2021/12/13
Time: 10:38
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>Hello Web !!!</h1>
<%-- 向页面输出 谈KJDE1037学习精神--%>
<%
// 脚本 里面可以写Java代码
// int a = 10;
// if(a > 5){
// ("Hello"); // 向控制台输出
// }
String name = "张三";
// 向页面输出
("谈KJDE1037学习精神");
("我叫"+name);
// 输出当前日期
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String dateString = (date);
("当前时间是"+dateString);
%>
<%-- 向页面输出 \转义 代表你想使用的是符号本身 --%>
<%="现在时间\"是\""+dateString%>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
JSP执行原理
此处省略一万字… …
局部变量与全局变量
<%
// 声明局部变量
int i = 0;
i++;
// 局部变量 : 声明在脚本的内部 每次使用都初始化
// 全局变量 声明在外部 只会在加载的时候初始化一次(每次使用都变化一次)
// out在局部可用,全局用不了,因为局部有参数,全局没有参数
%>
<!-- 声明全局变量 -->
<%! int k = 0; %>
<!-- 声明全局变量 -->
public void show(){
("我是全局方法,我被执行了")
}
<%="局部变量"+i%>
<%="全局变量"+(k++)%>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
常见错误
- 404: 地址写错了/页面没有在WEB-INF下/外部启动了Tomcat,未部署项目
- 500: jsp页面代码有错误
- … …
JSP实现数据传递和保存
一.request请求
// 获取表单数据
getParameter();
// 获取多个相同的name
getParameterValues()
// 解决中文字符乱码问题
// 设置字符编码 解决post请求,而get不会有这个问题
setCharacterEncoding()
setCharacterEncoding("utf-8")
// 存储数据 request作用域 数据只存在与一次请求只间
setAttribute(key,value)
// 获取数据 可能有空指针异常 返回值是object需要强转
Object getAttribubte(key)
// 请求转发
// forward(request,response) 是固定写法
request.getRequestDispatcher("转发地址").forward(request,response)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
二.response响应
// 重定向
response.sendRedirect()
- 1
- 2
三.请求转发和重定向区别
转发 | 重定向 |
---|---|
地址栏不会发生变化 | 地址发生变化 |
请求一次 | 请求两次 |
携带请求 | 不携带请求 |
作用域web程序(不能转发到程序以外的界面) | 任意的地址(URL)都可以重定向 |
转发:
重定向:
get与post的区别
比较项 | Get | Post |
---|---|---|
参数是否出现在url(地址栏)中 | 是 | 否 |
安全性 | 低 | 高 |
URL可传播 | 是 | 否 |
长度限制 | 有 | 无 |
四.示例
登录界面
<form action="" method="get">
<p>
用户名: <input type="text" name="name">
</p>
<p>
密码: <input type="password" name="pwd">
</p>
<p>
<input type="submit" value="登录">
</p>
</form>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
处理请求页面
// 2.接收参数
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
// 3.验证密码是否正确
String uname = "渣渣辉";
String upwd = "123456";
if (name.equals(uname) && pwd.equals(upwd)){
// 存储数据 键值对 key value
request.setAttribute("name",name);//存储一次数据
//对应下方欢迎界面的get
// 4.进行请求转发
request.getRequestDispatcher("").forward(request,response);
}else{
// 5.正常情况下密码错误 回到
//("").forward(request,response);
// 使用重定向
response.sendRedirect("");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
欢迎界面
<%--如果没有数据会出现空指针异常所以要判空 得到的数据是object类型 所以要进行数据类型转换--%>
<h1>
欢迎你 <%= request.getAttribute("name") == null ? "" : //获取这一次值时进行判空
(String) request.getAttribute("name")%> //强转
</h1>
- 1
- 2
- 3
- 4
- 5
session
作用域: 一次会话中实现数据共享
request
作用域: 只在一次请求实现数据传递
session.getAttribute()
session.setAttribute()
// 设置有效期 和获取有效期 s:秒
session.setMaxInactiveInterval()
// 获取有效期
session.getMaxInactiveInterval()
// 清除session数据
session.invalidate();
// 删除session属性
session.removeAttribute()
// 在中设置session有效期 m:分
<session-config>
<session-timeout>1</session-timeout>
</session-config>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
application
作用域: 整个web程序之间实现数据共享
application.getAttribute()
application.setAttribute()
- 1
- 2
<%
int count = 0 ;//初始化
if(application.getAttribute("count")==null){
count++;//第一次进入这个页面,给你设置为1
application.setAttribute("count",count);
}else{//只要不是第一次进入这个页面,获取你的值,++,然后再设置
count = (int) application.getAttribute("count");
count++;
application.setAttribute("count",count);
}
%>
<h1>欢迎您能在百忙之中莅临本站,<%=count%>号客人</h1>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
cookie
作用域: 以文件的形式保存数据到浏览器(客户端)中
并且只能存字符串,
// 添加cookie
response.addCookie(Cookie cookie)
// 创建cookie对象
Cookie cookie = new Cookie("key",value)
// 设置cookie有效期
cookie.setMaxAge() //s:秒
// 获取cookie
Cookie[] request.getCookie()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
JDBC
Java DataBase Connectivity(Java 语言连接数据库)
-
本质
JDBC是SUN公司制定的一套接口(interface)
–原因就是因为每一个数据库都有自己的实现原理,为了方便连接数据库,方便使用跟书写代码
接口都有调用者与实现者
面向接口调用,面相接口写实现类这都属于面向接口编程
-
为什么要面向接口编程?
降低程序的耦合性,提高程序的可读性跟拓展性
多态机制就是典型的面相抽象编程
例如:
建议:
Animal a = new Cat();
Animal a = new Dog();
//喂养的方法
public void feed(Animal a){
}
不建议:
Dong d = new Dog();
Cat c = new Cat();
单例模式(2种)
懒汉模式:
线程不安全 同步锁
延迟加载 调用时才会产生实例
饿汉模式:
线程安全 不具备延迟加载特性
当虚拟机加载时直接创建好对象
不管什么时候过来都直接返回创建好的对象
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
数据源以及分层开发
数据源
由于JDBC在访问数据库数据的时候会有效率低,安全性差,稳定性差的问题,所以java给出了连接池与数据源解决的方案.
-
连接池的工作原理
-
JNDI :
配置 tomcat数据源
- 1
<!-- 配置Tomcat的conf/context.xml -->
<!--想要获取tomcat集成的dbcp连接池 使用接口可以接收 -->
<!--
name:自行设置 唯一
auth:Container 固定 容器来托管数据源
type:javax.sql.DataSource 当服务器启动的时候 会自动帮你创建一个DataSource数据源的实现类
maxActive:最大活跃 (最大连接)
maxIdle:最大闲置(备胎)
maxWait:最大等待时间
username:数据库用户名
password:数据库密码
driverClassName:驱动名称
url:数据库地址
& :与符号&
useUnicode=true&characterEncoding=utf-8 防止项目编码和数据库编码不一致的情况 统一采用UTF-8
-->
<Resource name="jdbc/news" auth="Container" type=""
maxActive="100" maxIdle="30" maxWait="10000" username="root"
password="root" driverClassName=""
url="jdbc:mysql://127.0.0.1:3306/kgcnews?
useUnicode=true&characterEncoding=utf-8" />
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
引用 连接池代码 (获取连接对象)
- 1
public static void getConnection() throws Exception{
// 1.加载驱动
Class.forName(driver);
// 2.获取连接对象
//conn = (url,username,password);
// 通过连接池技术获取连接对象 每次关闭连接对象时并不会关闭掉 而是让连接对象返回到连接池
// 以下是重点
Context context = new InitialContext();
DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/news");
conn = dataSource.getConnection();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
分层开发
层与层之间是依赖关系 dao -> service -> jsp
-
第一层:
dao: 数据访问层
- 1
-
第二层:
service: 业务逻辑层
- 1
-
第三层:
jsp: 访问层(展示与控制页面)
- 1
以后会分出来: controller: 控制层
以下是代码演示
- 登录
分析: 输入完用户名 密码 点击登录
验证 接收form表单中的信息
// 字符编码
request.setCharacterEncoding("utf-8");
// 接收参数
String uname = request.getParameter("uname");
String upassword = request.getParameter("upassword");
// 去找userDao 帮我们去数据库查询
UserDao userDao = new UserDaoImpl();
// 查询用户名密码是否正确
User user = userDao.login(uname,upassword);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2.创建数据访问层 UserDao 的UserDaoImpl 实例 访问数据库查询是否有数据
public User login(String uname, String upassword) {
User user = null;
// 1.写sql语句
String sql = " select * from news_user where userName = ? and password = ? ";
// 2.执行
try {
select(sql,uname,upassword);
// 3.遍历结果集
while (rs.next()){
int id = rs.getInt("id");
String userName = rs.getString("userName");
String password = rs.getString("password");
String email = rs.getString("email");
int userType = rs.getInt("userType");
user = new User(id,userName,password,email,userType);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
closeAll();
} catch (Exception exception) {
exception.printStackTrace();
}
}
return user;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
3.实现跳转
//3. 实现跳转
if (user == null){
// 提示用户名密码输入错误
request.setAttribute("msg","用户名或者密码错误!");
request.getRequestDispatcher(request.getContextPath()+"/").forward(request,response);
}else{
// 重定向
session.setAttribute("user",user);
response.sendRedirect(request.getContextPath()+ "/pages/");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 注销
$(".fr").click(function (){
location.href = "../controller/"
})
- 1
- 2
- 3
2.点击注销按钮
// 实现注销功能
session.removeAttribute("user");
response.sendRedirect("../");
- 1
- 2
- 3
- 查询列表
1.当进入到admin界面
// 当进入此页面的时候应该去后台将新闻列表查询出来
List<NewsDetail> newsList = (List<NewsDetail>) session.getAttribute("newsList");
// 如果没有获取到 说明还没去查询
if (newsList == null || newsList.size() == 0){
response.sendRedirect(request.getContextPath()+"/controller/");
return;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
2.控制跳转
// 查询新闻列表
NewsDetailService newsDetailService = new NewsDetailServiceImpl();
List<NewsDetail> newsList = newsDetailService.findNewsList();
session.setAttribute("newsList",newsList); // 设置数据到作用域中
// 跳转
request.getRequestDispatcher(request.getContextPath()+"/pages/").forward(request,response);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
查询新闻列表
public List<NewsDetail> findNewsList() {
List<NewsDetail> newsList = new ArrayList<>();
String sql = " select * from news_detail ";
try {
select(sql);
while (rs.next()){
int id = rs.getInt("id");
int categoryId = rs.getInt("categoryId");
String title = rs.getString("title");
String summary = rs.getString("summary");
String content = rs.getString("content");
String picPath = rs.getString("picPath");
String author = rs.getString("author");
Date createDate = rs.getDate("createDate");
Date modifyDate = rs.getDate("modifyDate");
NewsDetail newsDetail = new NewsDetail(id,categoryId,title,summary,content,picPath,author,createDate,modifyDate);
newsList.add(newsDetail);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
closeAll();
} catch (Exception e) {
e.printStackTrace();
}
}
return newsList;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
4.数据展示
<%
for (NewsDetail newsDetail : newsList) {
%>
<tr class="admin-list-td-h2">
<td>
<a href='?id=2'><%=newsDetail.getTitle()%></a>
</td>
<td><%=newsDetail.getAuthor()%></td>
<td><%=newsDetail.getModifyDate() != null ? format.format(newsDetail.getModifyDate()):""%></td>
<td>
<a href='?id=2'>修改</a>
<a href="javascript:if(confirm('确认是否删除此新闻?')) location='?id=2'">删除</a>
</td>
</tr>
<%
}
%>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
补充: 解决404路径问题
1. 清除idea缓存与重启
2. 设置绝对路径
3. 更改浏览器地址栏路径
根据id删除新闻流程
一.点击删除新闻界面
关键代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFhKVjcx-1640771308145)(/imgs/2021/12/)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-91kOHz2t-1640771308146)(/imgs/2021/12/)]
二.删除控制页jsp
<%
// 接收id
String id = request.getParameter("id");
System.out.println(id);
// 根据id 去删除新闻
NewsDetailService newsDetailService = new NewsDetailServiceImpl();
int result = newsDetailService.deleteNewsById(id);
if (result > 0){
out.write("<script type='application/javascript' >");
out.write("alert('删除成功!'); ");
out.write(" = ''; ");
out.write("</script>");
}else if(result == 0){
out.write("<script type='application/javascript' >");
out.write("alert('没有要删除的新闻了!'); ");
out.write(" = ''; ");
out.write("</script>");
}else{
out.write("<script type='application/javascript' >");
out.write("alert('删除失败,系统异常,请重试!'); ");
out.write(" = ''; ");
out.write("</script>");
}
%>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
三.业务逻辑层关键代码
@Override
public int deleteNewsById(String id) {
int newsRow = 0;
Connection conn = null;
try {
conn = BaseDao.getConnection();
// 1. 开启事务
conn.setAutoCommit(false); // 关闭自动提交
// 2.删除相关评论
int commentRow = newsCommentDao.deleteCommentByNewsId(id);
if (commentRow >= 0){
// 3.删除新闻
newsRow = newsDao.deleteNewsById(id);
}
// 如果没有异常提交
conn.commit();
} catch (Exception e) {
e.printStackTrace();
// 4.如果出现异常 回滚
try {
if (conn != null) {
conn.rollback();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}finally {
// 5.开启自动提交
try {
if (conn != null) {
conn.setAutoCommit(true);
// 一次性关闭
BaseDao.closeAll();
}
} catch (Exception throwables) {
throwables.printStackTrace();
}
}
return newsRow;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
四.数据库工具类的一些修改 原本的连接池改为了单例获取对象
// 2.获取连接对象 ():连接对象是关闭状态也要创建对象
if (conn == null || conn.isClosed()){
conn = DriverManager.getConnection(url,username,password);
}
return conn;
- 1
- 2
- 3
- 4
- 5
五.数据访问层关键代码
评论
@Override
public int deleteCommentByNewsId(String id) {
String sql = " delete from news_comment where newsId = ? ";
try {
return update(sql, id);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
新闻
@Override
public int deleteNewsById(String id) {
String sql = " delete from news_detail where id = ? ";
try {
return update(sql, id);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
每日一测
//1、写出的获取参数方法、获取cookie的方法、获取HttpSession的方法、转发的方法
获取参数方法:
String getParameter(String name)
String[] getParameterValues(String name)
获取cookie的方法:
Cookie[] getCookies()
获取HttpSession的方法:
HttpSession getSession()
HttpSession getSession(boolean create)
转发的方法:
RequestDispatcher getRequestDispatcher(java.lang.String path)
request.getRequestDispatcher(url).forward(request,response)
//2、写出的重定向的方法,添加cookie对象的方法
重定向的方法:
void sendRedirect(String url)
添加cookie对象的方法:
void addCookie(Cookie cookie)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
第三方控件
1.文件上传
- 在form表单里添加一个文件域
- 修改form表单的enctype属性: application/x-www-form-urlencoded(键值对name-value)->multipart/form-data(文件项)
- 修改form表单请求方式改为post
- 原因: 理论上post没有上传大小限制
<form action= "" method="post" enctype="multipart/form-data">
<p>内容...</p>
</form>
- 1
- 2
- 3
-
需要导入和
-
使用commons-fileupload组件进行文件接收
//核心1.创建文件项工厂
FileItemFactory fif = new DiskFileItemFactory();
//核心2.工人进驻工厂
ServletFilrUpload upload = new ServletFileUpload(fif);
// 额外功能1:限制上传文件大小(单位字节byte) 30kb = 30*1024;
upload.setSizeMax(30*1024);
// 核心3:判断是否符合上传要求:enctype="multipart/form-data"和method="post"
if(ServletFileUpload.isMultipartContent(request)){
// 核心4:解析请求并转换为文件项集合
List<FileItem> fileItemList = upload.parseRequest(request);
// 核心5:遍历所有的文件项
for(FileItem fileItem : fileItemList){
// 核心6:判断当前文件项是否是普通表单(表单分为:普通表单type=text... 文件域表单:type=file)
if(fileItem.isFormField()){ // 如果是普通表单则为true
// 获取表单的name值
String name = fileItem.getFieldName();
// 获取普通表单的value值
// String value = ();
String value = fileItem.getString("UTF-8"); // 解决中文乱码
System.out.println("普通表单:name属性值:"+name+" value属性值:"+value);
}else{ // 文件域表单
// 获取表单的name值
String name = fileItem.getFieldName();
// 额外功能2:文件类型限制------------------------------------------
List<String> extensionList = Arrays.asList("jpg","png","jpeg");
// 核心7:获取文件名(如果是普通表单文件项调用返回null)
String fileName = fileItem.getName(); //
/* String extension = ((".")+1); */
String extension = FilenameUtils.getExtension(fileName); // commons-io里的工具类
System.out.println("文件扩展名为:"+extension);
if(extensionList.contains(extension)){
// 额外功能3:解决文件名重复引起的覆盖问题
String newFileName = System.currentTimeMillis()+"_header."+extension;
// 最核心:文件上传
File file = new File("d:/"+newFileName); // 指定文件地址
fileItem.write(file);
out.print("文件上传成功!");
}else{
out.print("不支持此类文件格式!支持的文件格式有:jpg,png,jpeg");
}
}
}
}else{
out.print("非法文件上传!");
}
}catch(FileUploadBase.SizeLimitExceededException e){
out.print("文件上传超过大小限制!");
}catch(Exception e){
out.print("上传失败!请重试!");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
分页查询
分页查询所需数据
1.每页显示多少条数据 pageSize
2.总共有多少条数据 totalCount
3.当前页 pageNo
4.本页查询到的数据 List result
5.总共有多少页 totalPage
6.起始下标 startIndex
代码
- 分页工具类代码
package cn.kgc.util;
import java.util.List;
/**
* 分页查询工具类
*/
public class PageBean<T> {
/**每页显示的条数*/
private Integer pageSize;
/**当前页*/
private Integer pageNo;
/**总记录数*/
private Integer totalCount;
/**起始下标*/
private Integer startIndex;
/**总页数*/
private Integer totalPage;
/**
*查询到的结果 T:代表泛型是任意类型 这个类型归当前类来约束
*当此类的泛型是啥的时候那么返回的列表泛型必须是啥
*/
private List<T> result;
public Integer getPageNo() {
return pageNo;
}
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getTotalCount() {
return totalCount;
}
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
}
public Integer getStartIndex() {
// 计算出起始下标 (当前页-1)*每页显示的条数
startIndex = (pageNo-1)*pageSize;
return startIndex;
}
public void setStartIndex(Integer startIndex) {
this.startIndex = startIndex;
}
public Integer getTotalPage() {
totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public List<T> getResult() {
return result;
}
public void setResult(List<T> result) {
this.result = result;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 页面
// 查询新闻列表
NewsDetailService newsDetailService = new NewsDetailServiceImpl();
// 设置起始页 如果前台没有传递参数 就代表你是第一次进入前台 肯定查询的第一页
// 将字符串类型转化为integer类型
Integer pageNo = ("pageNo") == null ? 1 : (("pageNo"));
// 设置每页显示的条数
Integer pageSize = 5;
// 进行分页查询
PageBean<NewsDetail> newsPage =(pageNo,pageSize);
// 设置数据到作用域中
("newsPage",newsPage);
// 跳转
("../pages/").forward(request,response);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- newsDetailService类关键代码
/**
* 分页查询业务
* @param pageNo
* @param pageSize
* @return
*/
@Override
public PageBean<NewsDetail> getNewsPage(Integer pageNo, Integer pageSize) {
PageBean<NewsDetail> newsPage = new PageBean<NewsDetail>();
newsPage.setPageSize(pageSize);
newsPage.setPageNo(pageNo);
// 分页业务代码
// 1.查询总记录数
int count = newsDao.getCount();
newsPage.setTotalCount(count);
// 2.查询分页的结果集
List<NewsDetail> newsList = newsDao.getNewsList(newsPage.getStartIndex(),newsPage.getPageSize());
newsPage.setResult(newsList);
// 最终都存入到pageBean 返回
return newsPage;
}/**
* 分页查询业务
* @param pageNo
* @param pageSize
* @return
*/
@Override
public PageBean<NewsDetail> getNewsPage(Integer pageNo, Integer pageSize) {
PageBean<NewsDetail> newsPage = new PageBean<NewsDetail>();
newsPage.setPageSize(pageSize);
newsPage.setPageNo(pageNo);
// 分页业务代码
// 1.查询总记录数
int count = newsDao.getCount();
newsPage.setTotalCount(count);
// 2.查询分页的结果集
List<NewsDetail> newsList = newsDao.getNewsList(newsPage.getStartIndex(),newsPage.getPageSize());
newsPage.setResult(newsList);
// 最终都存入到pageBean 返回
return newsPage;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 数据库查询关键代码
@Override
public int getCount() {
int count = 0;
String sql = " select count(*) from news_detail ";
try {
select(sql);
while (rs.next()){
count = rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
closeAll();
} catch (Exception e) {
e.printStackTrace();
}
}
return count;
}
@Override
public List<NewsDetail> getNewsList(Integer startIndex, Integer pageSize) {
List<NewsDetail> newsList = new ArrayList<>();
String sql = " select * from news_detail limit ?,? ";
try {
select(sql,startIndex,pageSize);
while (rs.next()){
int id = rs.getInt("id");
int categoryId = rs.getInt("categoryId");
String title = rs.getString("title");
String summary = rs.getString("summary");
String content = rs.getString("content");
String picPath = rs.getString("picPath");
String author = rs.getString("author");
Date createDate = rs.getDate("createDate");
Date modifyDate = rs.getDate("modifyDate");
NewsDetail newsDetail = new NewsDetail(id,categoryId,title,summary,content,picPath,author,createDate,modifyDate);
newsList.add(newsDetail);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
closeAll();
} catch (Exception e) {
e.printStackTrace();
}
}
return newsList;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 接收数据
// 接收分页查询到的数据
PageBean<NewsDetail> newsPage = (PageBean<NewsDetail>) request.getAttribute("newsPage");
- 1
- 2
- 遍历数据
<%
for (NewsDetail newsDetail : newsPage.getResult()) {
%>
<tr class="admin-list-td-h2">
<td>
<a href='?id=2'><%=newsDetail.getTitle()%></a>
</td>
<td><%=newsDetail.getAuthor()%></td>
<td><%=newsDetail.getModifyDate() != null ? format.format(newsDetail.getModifyDate()):""%></td>
<td>
<a href='?id=2'>修改</a>
<%-- get请求 请求携带参数是的衔接符号 ? 多个参数用 & 符号隔离 --%>
<a href="javascript:=' <%=()%>/controller/?id=<%=()%> '" >删除</a>
</td>
</tr>
<%
}
%>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 完成上下页跳转
<ul class="page-num-ul clearfix">
<li>共<%=newsPage.getTotalCount()%>条记录 <%=newsPage.getPageNo()%>/<%=newsPage.getTotalPage()%>页</li>
<a href="javascript:='<%=()%>/controller/?pageNo=1'">首页</a>
<%
if (newsPage.getPageNo() > 1){
%>
<a href="javascript:='<%=()%>/controller/?pageNo=<%=()-1 %>'">上一页</a>
<%
}
if (newsPage.getTotalPage() > newsPage.getPageNo()){
%>
<a href="javascript:='<%=()%>/controller/?pageNo=<%=()+1 %>'">下一页</a>
<%
}
%>
<a href="javascript:='<%=()%>/controller/?pageNo=<%=() %>'">最后一页</a>
</ul>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 实现页面跳转
<button type="button" class="page-btn" onClick="jump_to([1],('inputPage').value)">GO</button>
- 1
function jump_to(form,num){
// 页数不能小于1 不能大于总页数
var totalPage = $("input[name='totalPage']").val()
if (num > totalPage){
alert("输入的页数不能大于"+totalPage)
}else if (num < 1){
alert("输入的页数不能小于于1")
}else{
// 设置pageNo的值
$("input[name='pageNo']").val(num)
// 提交表单
form.submit()
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
El与JSTL
由于jsp脚本还有一些不足的地方:
- 代码结构混乱
- 脚本与HTML混合,容易出错.
- 代码不易维护
所以为了解决这些不足,出现了El表达式与JSTL
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5K2XSYDc-1640771308150)(/imgs/2021/12/)]
El功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zi1fb0oD-1640771308151)(/imgs/2021/12/)]
EL表达式的用法
<%--用el表达式来获取值--%>
${name}
<%-- ${age}--%>
<%--获取对象的属性 直接写属性名 --%>
<%-- el表达式获取对象的值 前提条件是通过get方法获取的set设置参数--%>
${}
${}
${}
<%--获取列表中的值--%>
${userList[0].name}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
EL表达式运算符
${empty } 判空
${ ! && || } 逻辑
${ () += - * / } 运算
- 1
- 2
- 3
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nVZ5zhsM-1640771308151)(/imgs/2021/12/)]
JSTL基础:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSgEZ5pc-1640771308152)(/imgs/2021/12/)]
标签/导入方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gqm4G4I2-1640771308153)(/imgs/2021/12/)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TsAtIHGQ-1640771308154)(/imgs/2021/12/)]
JSTL用法
<c:if test="${empty name}">
没有这个名字
</c:if>
out标签 向页面输出
escapeXml
false : 转义
true : 不转义
<c:out value="<h1>Hello jstl</h1>" default="hello" escapeXml="true"/>
<%--设置变量--%>
<c:set var="name" value="吴昊铭" scope="request"/>
<%--
var:遍历出来的每一项
items: 要遍历的集合
varStatus:索引下标
count:从1开始 计数
index:从0开始 下标
begin:从什么地方开始遍历
end:到什么地方结束
step:步长
--%>
<c:forEach var="str" items="${list}" varStatus="stat" >
${}
${str}
</c:forEach>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 上课代码
<%@ page import="" %>
<%@ page import="" %>
<%@ page import="" %><%--
Created by IntelliJ IDEA.
: 10044
Date: 2021/12/27
Time: 17:00
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导包--%>
<%@taglib uri="/jstl/core_rt" prefix="c" %>
<%@taglib uri="/jsp/jstl/fmt" prefix="f"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:if test="${empty name}">
没有这个名字
</c:if>
<%--if判断结构,代表如果name为空...--%>
<%--test:判断的表达式--%>
<%--<c:out value="<h1>Hello jstl</h1>" default="hello" escapeXml="true"/>--%>
<%--false与 true表示 转义与不转义(对前面的语句进不进行转义)--%>
<%--设置变量--%>
<%--<c:set var="name" value="红细胞" scope="request"/>
${name}--%>
<%-- <%
User user = new User();
("user",user);
%>--%>
<%--<c:set target="${user}" property="name" value="细胞"/>
<%–获取对象的值–%>
${}--%>
<%--遍历集合--%>
<%
List<String> list = new ArrayList<>();
("血细胞");
("白细胞");
("细菌");
("抗体");
("抗原");
("list", list);
%>
<%--
var:遍历出来的每一项
items: 要遍历的集合
varStatus:索引下标
count:从1开始 计数
index:从0开始 下标
begin:从什么地方开始遍历
end:到什么地方结束
step:步长
--%>
<c:forEach var="str" items="${list}" varStatus="stat" >
${}
${str}
</c:forEach>
<%--<table>
<c:forEach begin="0" end="10" varStatus="stat">
<c:if test="${ % 2 == 0}">
<tr style="color: red">
<td>Hello </td>
</tr>
</c:if>
<c:if test="${ % 2 != 0}">
<tr style="color: chartreuse">
<td>Hello </td>
</tr>
</c:if>
</c:forEach>
</table>--%>
<%--超链接标签--%>
<%--<a href="<c:url value=""/>">跳转</a>--%>
<%--导入标签--%>
<%--<c:import url=""/>--%>
<%--参数标签--%>
<%--<c:param name="name" value="神经元" />
<c:out value="${}" />--%>
<%
Date date = new Date();
// 创建格式化对象 .format()
("date", date);
("number", "7758521");
%>
<f:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss"/>
<f:formatNumber value="${number}" pattern="0.3"/>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
制作隔行变色效果
<table>
<c:forEach begin="0" end="10" varStatus="stat">
<c:if test="${ % 2 == 0}">
<tr style="color: red">
<td>Hello </td>
</tr>
</c:if>
<c:if test="${ % 2 != 0}">
<tr style="color: chartreuse">
<td>Hello </td>
</tr>
</c:if>
</c:forEach>
</table>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lsVzIeQ7-1640771308155)(/imgs/2021/12/)]
Servlet与过滤器and监听器
servlet
什么是Servlet?
servlet就是一种在服务器端运行的java小程序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ypIdYeuu-1640771308156)(/imgs/2021/12/)]
运行原理示意图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPGx5SM1-1640771308157)(/imgs/2021/12/)]
Servlet与Jsp之间的关系(父子关系)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbfOZ0lY-1640771308158)(/imgs/2021/12/)]
servlet的三种实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HK2lbQ0u-1640771308159)(/imgs/2021/12/)]
1.实现servlet接口
public class MyController implements Servlet {
// 最原始的servlet 包含了Servlet所有方法
/**
* 初始化
* @param servletConfig
* @throws ServletException
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("初始化了");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
2.继承genericServlet补充
/**
* 第二种写servlet的方式 抽象了 默认实现了servlet接口
* 为你实现了其他的所有方法 只保留了一个 servlet
*/
public class MyController1 extends GenericServlet {
/**
* 只有一个方法了
* 请求和响应有很多中 我们只做 http请求
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
3.继承HttpServlet
/**
* servlet的最终形态
* 第一形态: 实现servlet接口 里面的所有方法都需要实现
* 第二形态: 继承GenericServlet 将一些方法默认实现了
* 只保留了一个service 可以处理servlet的所有请求方式: http ftp ....
* 因为我们javaServlet只做http请求
* 第三形态 : 继承 http Servlet
* http协议的请求 :
* service方法包含很多请求 get post put delete ....
* 我们专门处理的一般都是get 和 post
*
* 最终版: 不去实现service方法
* 重写doGet 和 doPost方法
* 由于你也不太清除啥时候是get请求 啥时候是post请求
* 所以我们要让所有的亲求都经历get和post方法
*/
public class MyServlet extends HttpServlet {
public MyServlet() {
System.out.println("构造方法执行了");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 以后所有的代码写在这
String name = req.getParameter("name");
System.out.println(name);
System.out.println("执行了servlet doGet请求");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
doGet(req,resp);
System.out.println("执行了servlet doPost请求");
}
@Override
public void init() throws ServletException {
super.init();
System.out.println("servlet 初始化了");
}
@Override
public void destroy() {
super.destroy();
System.out.println("servlet 销毁了");
}
/**
* 专门处理http协议的请求
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
/*@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
("service 方法执行了");
}*/
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
编写请求
<%--请求--%>
<form action="myServlet" method="post">
<p>
用户名: <input type="text" name="name">
</p>
<p>
<input type="submit" value="提交">
</p>
</form>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
编写–(参数初始化)
<!--编写一个servlet-->
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class></servlet-class>
</servlet>
<!--编写一个servlet的映射 将用户的url请求 映射道某个servlet类中 -->
<servlet-mapping>
<servlet-name>myServlet</servlet-name><!--被映射的类-->
<url-pattern>/myServlet</url-pattern> <!--用户的请求url-->
</servlet-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Servlet生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MDuvCASh-1640771308160)(/imgs/2021/12/)]
web请求业务流程
总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rgw8M5OP-1640771308161)(/imgs/2021/12/)]
过滤器
概念与实现原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sD6hMkWG-1640771308162)(/imgs/2021/12/)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3GoNYH03-1640771308163)(/imgs/2021/12/)]
实现:
1.编写过滤器类
- (导包时注意要导这个包)
package cn.kgc.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
String characterEncoding = null;
/**
* 初始化 : 当程序启动时
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 当程序初始化的时候
characterEncoding = filterConfig.getInitParameter("characterEncoding");
}
/**
* 每次有请求和响应都会经过此方法
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 请求的时候设置请求的字符编码 响应的时候设置响应的字符编码
if (servletRequest != null){
// 设置post请求的字符编码
servletRequest.setCharacterEncoding(characterEncoding);
}
if (servletResponse != null){
// 设置响应的字符编码
servletResponse.setCharacterEncoding(characterEncoding);
// 响应一个页面
servletResponse.setContentType("text/html;charset="+characterEncoding);
}
// 放行
filterChain.doFilter(servletRequest,servletResponse);
}
/**
* 销毁
*/
@Override
public void destroy() {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
2.编写
<!--配置过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class></filter-class>
<!--配置初始化参数-->
<init-param>
<param-name>characterEncoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!--让所有的请求去找这个过滤器 完全匹配中: / 匹配目录 : /admin/* 匹配某些类型的请求: /*.do 匹配所有的请求: /*-->
<url-pattern>/*</url-pattern>
</filter-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
过滤器应用场合:
监听器
- 作用: 在web程序种 一旦servletContext httpSession servletRequest 对象发生状态改变 就会被监听
统计用户实时登录人数监听器实现思路:
1.编写全局上下文监听器 在项目初始化的时候触发
/**
* 应用程序上下文监听器
*/
public class OnlineUserListListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("上下文监听器已经初始化了");
List<User> userList = new ArrayList<>();
sce.getServletContext().setAttribute("ONlIST_USER",userList);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
2.为要被操作用户类 实现感知型监听器 当对象被添加到session作用域 就会调用valueBound()方法 当用户对象在session作用域中被删除调用valueUnbound()方法
/**
* 当session 添加数据时会调用
* @param event
*/
@Override
public void valueBound(HttpSessionBindingEvent event) {
// 获取application 对象
ServletContext application = event.getSession().getServletContext();
// 把当前的用户对象存入application作用域列表中
List<User> userList = (List<User>) application.getAttribute("ONlIST_USER");
userList.add(this);
System.out.println("当前登录的用户是:"+this.getUserName()+"已被添加到用户列表中");
System.out.println("上线一人,当前人数是:"+userList.size()+"人!");
}
/**
* 当session 销毁或者删除数据时会调用
* @param event
*/
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
ServletContext application = event.getSession().getServletContext();
List<User> userList = (List<User>) application.getAttribute("ONlIST_USER");
userList.remove(this);
System.out.println("当前下线的用户是:"+this.getUserName()+"已被删除到用户列表中");
System.out.println("下线一人,当前人数是:"+userList.size()+"人!");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
常用的监听器
mvc设计模式
model1
view + controller -> jsp
model -> service+ dao + entity
model2
view -> jsp
controller -> servlet
model -> service + dao + entity
JavaWeb重点补充
jsp脚本
1.编写脚本的位置
<% %>
2.输出语句
<%=%>
out.print()
3.成员变量 成员方法 在_jspService方法外面
<%! int a = 10; public void show(){} %>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
request
1.获取表单数据
String request.getParameter()
2.获取多个相同name的表单数据
String[] request.getParameterValues()
3.存取作用域属性
Object request.getAttribute()
request.setAttribute()
4.设置字符编码
request.setCharacterEncoding()
5.请求转发
request.getRequestDispatcher().forward(request,response)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
response
1.重定向
response.sendRedirect()
- 1
- 2
session
1.设置作用域属性
session.setAttribute()
2.获取作用域属性
session.getAttribute()
3.删除属性
session.removeAttribute()
4.清除session属性
session.invalidate()
5.设置session有效期
session.setMaxInactiveInterval(int interval);
6.获取sessionid
session.getId()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
cookie
1.获取cookie request
Cookie[] getCookies()
2.添加cookie response
addCookie(Cookie cookie)
3.这只cookie的有效期 s:秒
setMaxAge()
- 1
- 2
- 3
- 4
- 5
- 6
application
1.存取作用域属性
application.getAttribute()
application.setAttribute()
- 1
- 2
- 3
四大作用域的区别
request | response | session | application |
---|---|---|---|
一次请求 | 一次请求 | 一次会话中包含多次请求 | 整个app应用程序,所有数据都能 共享 |
JDBC
1.加载驱动
Class.forName("")
2.获取连接对象
String url = "jdbc:mysql://localhost:3306/数据库名?useUnicode=true;&charactorEncoding=utf-8";
Connection conn = DriverManager.getConnection(url,"root","root")
3.获取语句执行者对象
Statement state = conn.createStatement()
state.executeQuery()
state.executeUpdate()
4.有预编译的执行者对象
PreparedStatement prep = conn.prepareStatement(String sql)
设置参数
prep.setxxx(1,"")
5.执行sql语句获取结果集
ResultSet rs = prep.executeQuery()
int row = prep.executeUpdate()
6.遍历结果集
rs.next() 判断是否有下一个元素
rs.getxxx() 获取元素
7.关流
xxx.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
dao模式
BaseDao
1. 获取连接封装
public static Connection getConnection() throws Exception{
// 1.加载驱动
Class.forName(driver);
// 2.获取连接对象 ():连接对象是关闭状态也要创建对象
if (conn == null || conn.isClosed()){
conn = DriverManager.getConnection(url,username,password);
}
return conn;
// 通过连接池技术获取连接对象 每次关闭连接对象时并不会关闭掉 而是让连接对象返回到连接池
/*Context context = new InitialContext();
DataSource dataSource = (DataSource) ("java:comp/env/jdbc/news");
conn = ();*/
}
2. 通用的增删改
public static int update(String sql,Object...obj) throws Exception{
getConnection();
ps = conn.prepareStatement(sql);
if (obj != null){
for (int i = 0; i < obj.length; i++) {
ps.setObject((i+1),obj[i]);
}
}
return ps.executeUpdate();
}
3. 通用的查询
public static void select(String sql,Object...obj) throws Exception{
getConnection();
ps = conn.prepareStatement(sql);
if (obj != null){
// 设置参数
for (int i = 0; i < obj.length; i++) {
ps.setObject((i+1),obj[i]);
}
}
rs = ps.executeQuery();
}
4. 通用的关流
public static void closeAll() throws Exception{
if (rs != null){
rs.close();
}
if (ps != null){
ps.close();
}
if (conn != null){
conn.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
配置文件
# 链接地址
url=jdbc:mysql://localhost:3306/kgcnews?useUnicode=true&characterEncoding=utf-8
# 驱动
driver=
# 用户名
username=root
#密码
password=root
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
读取配置文件
static{
//部署项目 -> tomcat -> 被编译后的文件
// 读取配置文件获取io流 通过类加载器加载配置文件成为输入流
InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("");
Properties prop = new Properties();
try {
prop.load(is);// 通过输入流加载配置文件对象
} catch (IOException e) {
e.printStackTrace();
}
// 通过key 获取值
url = prop.getProperty("url");
driver = prop.getProperty("driver");
username = prop.getProperty("username");
password = prop.getProperty("password");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
单例模式
1.饿汉模式 Single
私有化构造
private Single(){}
私有化静态属性创建对象
private static Single single = new Single();
公共的获取实例的方法返回对象
public static Single getInstence(){
return single;
}
2.懒汉模式
私有化构造
private Single(){}
私有化静态属性
private static Single single;
公共的获取实例的方法 有线程问题加线程同步锁
public static Single getInstence(){
if(single != null){
return single;
}else{
return new Single;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
连接池
1.修改timcat中conf/
<!--
name:自行设置 唯一
auth:Container 固定 容器来托管数据源
type: 当服务器启动的时候 会自动帮你创建一个DataSource数据源的实现类
maxActive:最大活跃 (最大连接)
maxIdle:最大闲置(备胎)
maxWait:最大等待时间
username:数据库用户名
password:数据库密码
driverClassName:驱动名称
url:数据库地址
& :与符号&
useUnicode=true&characterEncoding=utf-8 防止项目编码和数据库编码不一致的情况 统一采用UTF-8
-->
<Resource name="jdbc/news" auth="Container" type=""
maxActive="100" maxIdle="30" maxWait="10000" username="root"
password="root" driverClassName=""
url="jdbc:mysql://127.0.0.1:3306/kgcnews?
useUnicode=true&characterEncoding=utf-8" />
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
2.修改获取连接对象的方式
// 通过连接池技术获取连接对象 每次关闭连接对象时并不会关闭掉 而是让连接对象返回到连接池
Context context = new InitialContext();
DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/news");
conn = dataSource.getConnection();
- 1
- 2
- 3
- 4
分层开发
数据访问层 | dao | 操作数据库 |
---|---|---|
业务逻辑层 | service | 处理业务代码 事务 … |
表示层(视图展示) | jsp | 展示数据的(请求控制) |
JSP 标签
将公共部分的代码放入到一个jsp中
就可以用以下标签引入到其他页面中 实现页面的拼接
<jsp:include page="URL">
- 1
- 2
- 3