JavaWeb
基本概念
静态web
- *htm, *html 这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取,通络。
html,css
- 静态web的缺点
-
Web页面无法动态更新,多个用户看到的都是同一个页面
-
- 轮播图,点击特效
- JavaScript
- VBSvript
-
-
他无法和数据库交互(数据无法持久化,用户无法交互)
动态web
提供给所有人看的数据之中会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同
web的页面展示的效果因人而异
- 淘宝,几乎是所有网站
- 技术栈:Servlet/Jsp,PHP
在java中,动态web资源开发的技术统称为Javaweb
- 缺点
- 加入服务器的动态web自愿出现了错误,我们需要重新编写我们的后台程序,重新发布(停机维护)
- 优点
- Web页面可以动态更新,多个用户看到的不是同一个页面
- 他可以与数据库交互,(数据持久化,注册,商品信息,用户信息)
web应用程序
- 什么是程序
web应用程序,可以提供浏览器访问的程序:
- a.html。b.html…多个资源,这些web资源可以被外界访问,对外界提供服务
- 能访问到的任何一个页面或者资源,都存在这个世界的某一个角落的计算机上
- URL
- 这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat服务器
- 一个web应用由多部分组成(静态web,动态web)
(1)html,css,js
(2) jsp,servlet
(3)java程序
(4)jar包
(5)配置文件(Properties)
web应用程序编写完以后,弱项提供给外界访问,需要一个服务器来统一管理
Web服务器
技术讲解
ASP:
- 微软:国内最早的流行的就是ASP
- 在HTML中嵌入VB的脚本,ASP+COM
- 在ASP开发中,基本一个页面都有几千行业务代码,页面极其混乱
- 维护成本高
- C#
PHP
- PHP开发速度很快,功能很强大,跨平台,代码简单
- 无法承载大访问量的情况(局限性);
JSP/Servlet
B/S :浏览器和服务器
C/S :客户端和服务器
- sun公司主推的B/S架构
- 基于java语言
- 可以承载三高问题(高并发,高可用,高性能)带来的影响
- 语法像ASP,ASP–>JSP,机枪市场强度
web服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些相应信息
IIS
微软的:ASP(Windows中自带的)
Tomcat
面向百度编程
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。Tomcat最新版本为10.0.5**。**
下载Tomcat
- 安装
- 了解配置文集
- 作用
Tomcat
安装Tomcat
启动Tomcat
关闭Tomcat
Tomcat配置
- server.xml
可以配置启动的端口号
-
Tomcat的默认端口号8080
-
mysql:3306
-
http
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
可以配置主机的名称
-
默认的主机名,localhost:127.0.0.1
-
默认的网站应用存放的位置 webapps
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题
网站是如何进行访问的
- 输入一个域名;回车
- 检查本机的 C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射
1.有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
2.没有:去DSN服务器找,找到的话就返回,找不到就返回找不到
配置环境变量(可选)
发布一个web网站
- 将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了
网站应有的结构
--webapps :Tomcat服务器的web目录
-ROOt
-SplitStudy :网站的目录名
-index.html(jsp)
-WEB-INF
-classes:java程序
-lib:web应用所依赖的jar包
-web.xml:网页配置文件
-web.html 默认的首页
-static
-css
-style.css
-js
-img
解决问题
- web.xml 替换为webapp4.0和Tomcat一致
Maven
Maven仓库的使用
上网搜
servlet
简介
servlet 是由web服务器调用,web服务器在收到浏览器请求之后,会
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
最早支持Servlet标准的是JavaSoft的Java Web Server,此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。
helloservlet
package com.split.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//响应的类型text
resp.setContentType("text/html");
//获得响应的输出流
PrintWriter out = resp.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>你好世界</h1>");
out.println("</body>");
out.println("</html>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<!--web.xml中是配置我们的核心应用-->
<!-- 注册servlet-->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.split.servlet.HelloServlet</servlet-class>
</servlet>
<!-- 一个servlet对应一个Mapping-->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<!-- 映射的请求路径-->
<url-pattern>/splits</url-pattern>
</servlet-mapping>
</web-app>
原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qXjNN1qK-1637760112927)(JavaWeb.assets/servlet.png)]
Mapping问题
- 一个servlet可以指定一个映射路径
<!-- 一个servlet对应一个Mapping-->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<!-- 映射的请求路径-->
<url-pattern>/splits</url-pattern>
</servlet-mapping>
- 一个servlet可以指定多个映射路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/splits</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/splits1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/splits2</url-pattern>
</servlet-mapping>
- 一个servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/split/*</url-pattern>
</servlet-mapping>
- 制定一些后缀或者前缀等等
可以自定义后缀实现请求
注意点:*前面不能加项目映射的路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>*.splits</url-pattern>
</servlet-mapping>
- 默认请求路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
- 优先级问题
指定了固有的映射路径优先级最高,如果过找不到就会走默认的处理请求
<!-- 404-->
<servlet>
<servlet-name>erroe</servlet-name>
<servlet-class>com.split.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>erroe</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
ServletContext
HttpServletResponse
3.验证码功能
- 前端实现
- 后端实现,需要用到java图片类,生成一个图片
//如何让浏览器五秒刷新一次
resp.setHeader("refresh","3");
//在内存中创建图片
BufferedImage bufferedImage = new BufferedImage(80,20,BufferedImage.TYPE_3BYTE_BGR);
//得到图片
Graphics2D g = (Graphics2D) bufferedImage.getGraphics(); //笔
//设置图片的背景颜色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.black);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告诉浏览器,这个请求用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no cache");
//把图片写给浏览器
ImageIO.write(bufferedImage,"jpg",resp.getOutputStream());
}
//生成随机数
private String makeNum(){
Random random = new Random();
String num=random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i <7-num.length(); i++) {
sb.append("0");
}
num=sb.toString()+num;
return num;
}
4.实现重定向
一个web资源收到客户端请求,他会通知客户端去访问另外一个web资源
测试
// resp.setHeader("location","img");
// resp.setStatus(302);
resp.sendRedirect("image");
重定向和转发的区别
相同点
- 页面都会跳转
不同点
- 请求转发的时候,url不会产生变化 307
- 重定向的时候,URL地址栏会发生变化 302
用户登录
//处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+";"+password);
//重定向时候一定要注意,路径问题,否则404
resp.sendRedirect("success.jsp");
<%@ page pageEncoding="utf-8" %>
<form action="${pageContext.request.contextPath}/login" method="get">
用户名: <input type="text" name="username"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit">
</form>
<h1>李小帅</h1>
HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会封装到HttpServletRequest,通过这个HttpServletRequest的方法获得客户端的所有信息
获取前端传递的参数,请求转发
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobbys");
System.out.println("-----------------------------------------");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
System.out.println("------------------------------------------");
//通过请求转发
req.getRequestDispatcher("success.jsp").forward(req,resp);
- 登录页面
<%--
Created by IntelliJ IDEA.
User: jd
Date: 2021/11/18
Time: 16:29
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h1>登录</h1>
<div style="text-align: center">
<%-- 这里表单表达的意思:以post方式提交表单,提交到我们的login请求--%>
<form action="${pageContext.request.contextPath}/login" method="post">
用户名 <input type="text" name="username" required> <br>
密码 <input type="password" name="password" required> <br>
爱好
<input type="checkbox" name="hobbys" value="女孩">美女
<input type="checkbox" name="hobbys" value="黑丝">黑丝
<input type="checkbox" name="hobbys" value="白丝">白丝
<input type="checkbox" name="hobbys" value="渔网">渔网
<br>
<input type="submit">
</form>
</div>
</body>
</html>
- 跳转页面
<html>
<head>
<title>成功</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>
Cooike,Session
会话
会话:用户打开了一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程可以成为会话
有状态会话 例:曾经来过,称为有状态会话
一个网站,怎样证明你来过
客户端 服务端
- 服务端给客户端一个信件,客户端下次访问客户端带上信件就可以
- 服务器登记你来过,下次匹配 session
保存会话的两种技术
Cookie
- 客户端技术,(响应,请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息,我们可以把信息或者数据放在session中
常见场景:网站登录之后,你下次不用再登录了,第二次访问就直接进去了
Cookie
- 从请求中拿到cookie信息
- 服务器响应个客户端cookie
Cookie[] cookies = req.getCookies(); //获取cookie
"LastLoginTime".equals(cookie.getName()) //获得cookie中的key
cookie.getValue() //获得cookie中值
new Cookie("LastLoginTime",System.currentTimeMillis()+"");//新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
cookie:一般会保存在本地的用户目录下APPdate
细节
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- cookie的大小有限制4kb
- 300个cookie浏览器上限
删除cookie
- 不设置有效期,关闭浏览器,自动失效
- 设置有效值为0
编码解码:
Cookie cookie = new Cookie("name", "李小帅");
out.write(URLDecoder.decode(cookie1.getValue(),"utf-8"));
Session
什么是session
- 服务器会给每一个用户创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
- 用户登录之后,整个网站他都可以访问->保存用户信息,保存购物车信息
Session和Cookie的区别
- Cookie是吧用户的数据写给浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到用户独占Session中,服务器端保存(保存重要信息,减少服务器资源的浪费)
- Session对象由服务器创建
使用场景:
- 保存一个登录用户的信息;
- 购物车信息
- 在整个网站中经常会使用的数据,他们会保存在Session中
使用Session
//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
// 得到Session
HttpSession session = req.getSession();
session.setAttribute("name",new person("split",1));
//获取Session的id
String sessionId = session.getId();
//判断是不是新创建的Session
if (session.isNew()) {
resp.getWriter().write("session创建成功,ID为"+sessionId);
}else {
resp.getWriter().write("session已经在服务器中存在了,ID"+sessionId);
}
//Session创建的时候做了一个什么事情
Cookie cookie = new Cookie("JSESSIONID",sessionId);
resp.addCookie(cookie);
//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
// 得到Session
HttpSession session = req.getSession();
person person=(person) session.getAttribute("name");
System.out.println(person);
HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销Session
session.invalidate();
package com.split.pojo;
public class person{
private String name;
private int age;
public person() {
}
public person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<!-- 设置Session默认的失效时间-->
<session-config>
<!-- 15分钟后Session自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
JSP
什么是JSP
java servlet pages java服务器端页面,也和servlet一样,用于开发动态web
最大的特点
- 写JSP像写HTML
- 区别
- HTML只给用户提供静态的数据
- JSP中可以嵌入java代码,为用户提供动态数据
JSP原理
-
代码层面:没有任何问题
-
服务器内部工作
Tomcat中有一个work目录
IDEA中使用Tomcat的会在IDEA的Tomcat中生成一个work目录
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
JSP最终也会被转化成一个java类
JSP本质上就是一个Servlet
- 判断请求
- 内置一些对象
- 输出页面增加的代码
- 以上的这些对象我们在JSP中可以直接使用
JSP基础语法
任何语言都有自己的语法,JAVA中有。JSP作为java技术的一种应用,他拥有一些自己的扩充语法,java多有语法都支持
JSP表达式
<%--JSP表达式--%>
<%--作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%=new java.util.Date()%>
jsp脚本片段
<%-- jsp脚本片段--%>
<%
int sum=0;
for (int i = 0; i <=100; i++) {
sum+=i;
}
out.print("<h1>sum="+sum+"</h1>");
%>
脚本片段的再实现
<%
int x=10;
out.print(x);
%>
<p>这是一个jsp文档</p>
<%
int y=10;
out.print(y);
%>
<hr>
<%-- 在代码嵌入Html元素--%>
<%
for (int i = 0; i <5; i++) {
%>
<h1>hello <%=i%></h1>
<%
}
%>
JSP声明
<%!
static{
System.out.println("Loading Servlet");
}
private int globalVar=0;
public void split(){
System.out.println("进入了方法split");
}
%>
JSP声明:会被编译到jsp生成java的类中!其他的,就会被生成到JspServlet方法中
在jsp中嵌入java代码即可
<%%>
<%=%>
<%!%>
jsp的注释,不会在客户端显示,HTML就会
JSP指令
<%@page ...%>
<%--定制错误页面--%>
<%--<%@ page errorPage="error/500.jsp" %>--%>
<%--显示声明这是一个错误页面--%>
<%@page isErrorPage="true" %>
<%--@ include会把两个页面合二为一--%>
<%@ include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@ include file="common/footer.jsp"%>
<%--jsp:include拼接页面--%>
<jsp:include page="common/header.jsp"></jsp:include>
<h1>网页主体</h1>
<jsp:include page="common/footer.jsp"/>
9大内置对象
- PageContext 存东西
- Request 存东西
- Response
- Session 存东西
- Application 【ServletContext】 存东西
- config【ServletConfig】
- out
- page 不用
- exception
<%--内置对象--%>
<%
pageContext.setAttribute("name1","split1"); //保存的数据只在一个页面中有效
request.setAttribute("name2","split2"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","split3"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","split4"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%--脚本片段中的代码,会被原封不动的生成JSP.java
要求:这里的代码,必须保证java语法的重要性
--%>
<%
//通过pageContext取出我们保存的值,通过寻找的方式
//以底层到高层(作用域)
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String)pageContext.findAttribute("name3");
String name4 = (String)pageContext.findAttribute("name4");
%>
<%--使用EL表达式输出--%>
<h1>取出的值为</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<%
pageContext.forward("/index.jsp");
%>
request:客户端服务器发送请求,产生的数据,用户看完就没用了。例如:新闻
session: 客户端向服务器发送请求,产生的数据,用户用完了一会还有用。例如:购物车
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用。例如:聊天数据
JSP标签,JSTL标签,EL表达式
EL表达式
- 获取数据
- 执行运算
- 获取web开发的常用对象
- 调用java方法
JSP标签
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="split"></jsp:param>
<jsp:param name="age" value="12"></jsp:param>
</jsp:forward>
JSTL标签
JSTL标签库的使用就是为了弥补HTML标签的不足,他自定义许多标签,可以供我们使用,标签的功能和java代码一样
核心标签
<%--引入JSTL标签库,我们才能使用JSTL标签,core--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
SQL标签
XML标签
JSTL标签库的使用
-
引用对应的taglib
-
使用其中的方法
-
在Tomcat也需要引入jstl的包,否则会报错:jstl解析错误
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>if测试</h3>
<hr>
<form action="/coreif.jsp" method="get">
<%--
EL表达式获取表中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断如果提交的用户名是管理员,则登陆成功--%>
<%--<%--%>
<%--if (request.getParameter("username").equals("admin")){--%>
<%-- out.print("登陆成功");--%>
<%--}--%>
<%--%>--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎您"></c:out>
</c:if>
<c:out value="${isAdmin}"></c:out>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--定义一个变量score 值为85--%>
<c:set value="85" var="score"></c:set>
<c:choose>
<c:when test="${score>=90}">
你很优秀
</c:when>
<c:when test="${score>=80}">
一般
</c:when>
<c:when test="${score>=70}">
良好
</c:when>
<c:when test="${score>=60}">
及格
</c:when>
<c:when test="${score<60}">
继续努力
</c:when>
</c:choose>
</body>
</html>
<%
ArrayList<String> people =new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"李小帅");
people.add(4,"前几");
request.setAttribute("list",people);
%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"></c:out><br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
<c:out value="${people}"></c:out><br>
</c:forEach>
JAVABean
实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据局库的字段做映射 ORM
- 表>>类
- 字段>>属性
- 行记录>>对象
id | name | age | address |
---|---|---|---|
1 | split1 | 3 | 地球 |
2 | split2 | 6 | 地球 |
3 | split3 | 8 | 地球 |
class People{
private int id;
private String name;
private int age;
private String address;
}
class A{
new People (1,"split1",3,"地球");
new People (2,"split2",6,"地球");
new People (3,"split3",8,"地球");
}
<jsp:useBean id="people" class="com.split.pojo.People" scope="page"/>
<jsp:setProperty name="people" property="address" value="地球"></jsp:setProperty>
<jsp:setProperty name="people" property="id" value="001"></jsp:setProperty>
<jsp:setProperty name="people" property="age" value="55"></jsp:setProperty>
<jsp:setProperty name="people" property="name" value="split"></jsp:setProperty>
姓名<jsp:getProperty name="people" property="name"/>
年龄<jsp:getProperty name="people" property="age"/>
id<jsp:getProperty name="people" property="id"/>
地址<jsp:getProperty name="people" property="address"/>
package com.split.pojo;
//实体类 我们一般都是和数据库中的表结构一一对应
public class People {
private int id;
private String name;
private int age;
private String address;
public People() {
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setAddress(String address) {
this.address = address;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return "People{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
MVC三层架构
什么是MVC:Model view Controller 模型,视图,控制器
早年
用户直接访问控制层,控制层就可以直接操作数据库
servlet ==>CRUD===>数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中,处理请求,响应,视图跳转,处理JDBC,处理业务代码,处理逻辑代码
MVC三层架构
model
- 业务处理,业务逻辑(service)
- 数据持久层:CRUD(Dao)
view
- 展示数据
- 提供链接发起servlet请求(a,form,img…)
controller
- 接收用户的请求(req:请求参数,session信息)
- 交给业务层处理对应的代码
- 控制视图的跳转
登录--->接收用户的登录请求(获取用户登录的参数,username,password)--->交给业务层处理登录业务(判断用户密码是否正确)--->Dao层查询用户名和密码是否正确--->数据库
Filter(过滤器)
Filter:过滤器,用来过滤网站的数据
- 处理中文乱码
- 登录验证
Chain
- 过滤器中的所有代码,在过滤特定请求的时候都会执行
- 必须要让过滤器继续执行
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("执行前");
filterChain.doFilter(servletRequest, servletResponse);//让我们的请求继续走,如果不写,程序到这里就拦截停止了
System.out.println("执行后");
}
@Override
public void destroy() {
System.gc();
System.out.println("销毁");
}
- 在web.xml中配置filter
<filter>
<filter-name>Characterencodingfilter</filter-name>
<filter-class>com.split.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Characterencodingfilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
监听器
实现一个监听器的接口;(有n种)
-
编写一个监听器
监听器的接口
//创建session监听 // 一旦创建一个session就会触发一个这个事件 @Override public void sessionCreated(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); Integer onlineCount =(Integer) ctx.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount=new Integer(1); }else { int count=onlineCount.intValue(); onlineCount=new Integer(count+1); } ctx.setAttribute("OnlineCount",onlineCount); } //销毁session监听 // 一旦销毁一个session就会触发一个这个事件 @Override public void sessionDestroyed(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); Integer onlineCount =(Integer) ctx.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount=new Integer(0); }else { int count=onlineCount.intValue(); onlineCount=new Integer(count-1); } ctx.setAttribute("OnlineCount",onlineCount); }
-
web.xml中注册监听器
<!-- 注册监听器--> <listener> <listener-class>com.split.lisener.OnlineCountListener</listener-class> </listener>
-
看情况是否使用
过滤器和监听器的应用
监听器:GUI编程中经常使用
public static void main(String[] args) {
Frame frame = new Frame("正顺是个掉毛"); //新建一个窗体
Panel panel = new Panel(null); //面板
frame.setLayout(null); //设置窗体的布局
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(0,0,255));
panel.setBounds(50,50,300,300);
panel.setBackground(new Color(233, 124, 236));
frame.add(panel);
frame.setVisible(true);
//监听关闭事件
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
System.out.println("打开");
}
@Override
public void windowClosing(WindowEvent e) {
System.out.println("关闭ing");
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
System.out.println("关闭ed");
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
System.out.println("激活");
}
@Override
public void windowDeactivated(WindowEvent e) {
System.out.println("未激活");
}
});
}
用户登录之后才能进入主页,用户注销之后就不能进入主页
- 用户登录之后,向Session中放入数据
- 进入主页的时候要判断与欧诺个户是否已经登录,在过滤器中实现
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
request.getSession().getAttribute("USER_SESSION");
if (request.getSession().getAttribute("USER_SESSION")==null){
response.sendRedirect("error.jsp");
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
JDBC
什么是JDBC:java连接数据库
需要jar包的支持
- java.sql
- javax.sql;
- mysql-conneter-java…连接驱动
实验环境搭建
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES (1,'李小帅','12345','lixiaoshuai@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES (2,'李大帅','1234','lixishuai@qq.com','2000-02-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES (3,'李不帅','123','lixshuai@qq.com','2000-03-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES (4,'李帅','12','lishuai@qq.com','2000-03-01');
SELECT * FROM users;
解决中文乱码
?useUnicode=true&characterEncoding=utf-8"
导入数据库依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
IDEA中连接数据库
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password = "123456";
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
// 3.向数据库发送SQL的对象statement :CRUD
Statement statement = connection.createStatement();
// 4.编写SQL
String sql="select * from users";
// 5.执行SQL 返回一个resultSet:结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id="+rs.getObject("id"));
System.out.println("name="+rs.getObject("name"));
System.out.println("password="+rs.getObject("password"));
System.out.println("email="+rs.getObject("email"));
System.out.println("birthday="+rs.getObject("birthday"));
}
// 6.关闭连接,释放资源,先开后关
rs.close();
statement.close();
connection.close();
}
JDBC固定步骤
- 加载驱动
- 连接数据库,代表数据库
- 向数据库发送SQL的对象Statement:CRUD
- 编写SQL(根据业务,不同的SQL)
- 执行SQL
- 关闭连接
预编译SQL
public static void main(String[] args) throws Exception {
//配置信息
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password = "123456";
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//
// 3.编写SQL
String sql="insert into users (id, name, password, email, birthday) VALUES(?,?,?,?,?);";
// 4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,6);//给第一个占位符? 的值赋值为1
preparedStatement.setString(2,"split");//给第一个占位符? 的值赋值为split
preparedStatement.setString(3,"123456");//给第一个占位符? 的值赋值为"123456
preparedStatement.setString(4,"sshihi@qq.com");//给第一个占位符? 的值赋值为sshihi@qq.com
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第一个占位符? 的值赋值为new Date(new java.util.Date().getTime()
// 5.执行SQL
int i = preparedStatement.executeUpdate();
if(i>0){
System.out.println("插入成功");
}
// 6.关闭连接,释放资源,先开后关
preparedStatement.close();
connection.close();
}
事务
要么都成功,要么都失败
ACID:保证数据的安全
1.开启事务
2.事务提交 commit()
3.事务回滚 rollback()
4.关闭事务
Junit单元测试
依赖:
<!-- 单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
简单使用
@Text注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行
@Test
public void test(){
System.out.println("hello");
}
搭建一个环境
public class TextJdbc3 {
@Test
public void test() {
Connection connection=null;
//配置信息
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
// 1.加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
// 2.连接数据库,代表数据库
connection = DriverManager.getConnection(url, username, password);
// 3.通知数据库开启事务 false是开启
connection.setAutoCommit(false);
String sql = "update account set money=money-100 where name='A'";
connection.prepareStatement(sql).executeUpdate();
// 制造错误
//int i = 1 / 0;
String sql2 = "update account set money=money+100 where name='B'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit(); //以上两条事务都执行成功,就提交事务
System.out.println("提交成功");
} catch (Exception e) {
try {
// 如果出现异常,就通知数据库回滚事务
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}