学习视频:B站 狂神说Java – https://www.bilibili.com/video/BV12J411M7Sj
学习资料笔记:CSDN – https://blog.csdn.net/DDDDeng_/article/details/106826674
JavaWeb:网页编程 B/S
网络编程:TCP/IP C/S
web开发:
在Java中,动态web资源开发的技术统称为 JavaWeb。
Cookie: 曲奇饼干
session:会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器这个过程可以称之为会话。
有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过
那么对于一个网站而言,如何证明你来过呢 ?下面是两种方式:
客户端、服务端:
意思就相当于:
cookie
session
常见问题:
网站登录之后,下次不用再登录了,第二次就直接上去了。 这就是客户端和服务端成功的进行了匹配, 把曾经两个人之间的交易记录(存放在 cookie / session)拿出来能够成功比对。
查看一下Cookie类:都是一些 get 和 set 的方法,用来存放和获取数据的。
Cookie: 服务端给访问的客户端开了一个证明/信件, 下一次 客户端拿着信件/证明来, 就能直接进去服务端。
客户端技术的例子:
cookie:
创建一个Servlet程序,CookieDemo01:服务器先请求客户端,得到其cookie信息。然后服务器响应客户端,生成一个cookie。
package com.AL.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Date;
// 保存用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器告诉你, 你来的时间.把这个时间封装成一个发票,你下次带着发票来,我就知道是你来了
// 解决中文乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=utf-8");
PrintWriter out = resp.getWriter();
// Cookie,服务器从客户端获取,查看你的发票. 查看你啥时来的,是不是这个班的人
Cookie[] cookies = req.getCookies(); //返回的是数组,表明cookie可能存在多个
// 判断cookie是否存在
if (cookies!=null){
// 当存在时的输出
out.write("你上次访问的时间为:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (cookie.getName().equals("lastLoginTime")){
// 获取cookie的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else {
out.write("This is you first time");
}
// 服务器给客户端响应一个cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// cookie有效期设置为1天. 以秒为单位
cookie.setMaxAge(24*60*60);
resp.setCharacterEncoding("utf-8");
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
web.xml配置文件。进行注册Servlet 和 Servlet的路径映射。
<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>CookieDemo01servlet-name>
<servlet-class>com.AL.servlet.CookieDemo01servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo01servlet-name>
<url-pattern>/c1url-pattern>
servlet-mapping>
web-app>
启动Tomcat,进行测试。输入 localhost:8080/c1,结果为:
删除cookie:
1.创建一个cookie,且名字必须和要删除的名字一样:
package com.AL.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建一个cookie. 名字必须要和删除的目标cookie一样
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// 将cookie有效期设置为0, 立马失效
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2.配置文件web.xml:
<servlet>
<servlet-name>CookieDemo02servlet-name>
<servlet-class>com.AL.servlet.CookieDemo02servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo02servlet-name>
<url-pattern>/c2url-pattern>
servlet-mapping>
3.启动Tomcat,进行测试。 localhost:8080/c2, 结果显示 cookie立马失效。
小结:
cookie:
在这个实现cookie中使用的函数有:
Cookie[] cookies=req.getCookiles();//获得cookie
cookie.getName();//获得cookie中的key
cookie.getValue();//获得cookie中的value
new Cookie("lastLoginTime",System.currentTimeMillis()+"");//新建一个cookie
cookie.setMaxAge(24*60*60);//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie
cookie:一般会保存在本地的 用户目录下 appdata
一个网站cookie是否存在上限?
删除cookie:
一关闭浏览器,cookie就自动失效了。
中文数据传递
创建一个cookie:
package com.AL.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
public class CookieDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
//服务器告诉你, 你来的时间.把这个时间封装成一个发票,你下次带着发票来,我就知道是你来了
// Cookie,服务器从客户端获取,查看你的发票. 查看你啥时来的,是不是这个班的人
Cookie[] cookies = req.getCookies(); //返回的是数组,表明cookie可能存在多个
PrintWriter out = resp.getWriter();
// 判断cookie是否存在
if (cookies!=null){
// 当存在时的输出
out.write("你上一次访问的时间是:");
//out.write("you last time is:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (cookie.getName().equals("name")){
// 获取cookie的值
//out.write(cookie.getValue());
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8")); // 解码
}
}
}else {
out.write("这是你第一次访问本站");
}
// 服务器给客户端响应一个cookie. 编码: URLEncoder.encode()
Cookie cookie = new Cookie("name", URLEncoder.encode("坤坤","utf-8"));
// cookie有效期设置为1天. 以秒为单位
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
web.xml配置文件。发布Servlet程序。
<servlet>
<servlet-name>CookieDemo03servlet-name>
<servlet-class>com.AL.servlet.CookieDemo03servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo03servlet-name>
<url-pattern>/c3url-pattern>
servlet-mapping>
处理请求参数传递编码问题: 使用编码和解码的方式,使中文不产生乱码。
什么是Session:
Session和cookie的区别:
Session使用场景:
保存一个登陆用户的信息;
购物车信息;
在整个网站中经常会使用的数据,我们将它保存在session中
创建一个Session程序
package com.AL.servlet;
import com.AL.pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
// session。 存放一个字符串
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=utf-8"); // 使文档可以访问,还有编码
//得到一个session
HttpSession session = req.getSession();
// 给session中存放东西。 服务器对客户进行登记
//session.setAttribute("name", new Person("鑫仔",1));
session.setAttribute("name", "鑫仔");
// 获取session的ID。 且每个客户端的sessionID是唯一的
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);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
<servlet>
<servlet-name>SessionDemo01servlet-name>
<servlet-class>com.AL.servlet.SessionDemo01servlet-class>
servlet>
<servlet-mapping>
<servlet-name>SessionDemo01servlet-name>
<url-pattern>/s1url-pattern>
servlet-mapping>
获取Session的程序
1.创建一个获取Session的session程序:
package com.AL.servlet;
import com.AL.pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
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.toString());
String name = (String) session.getAttribute("name");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2.配置 web.xml文件。 这个相当于web容器,发布 Servlet程序。
<servlet>
<servlet-name>SessionDemo02servlet-name>
<servlet-class>com.AL.servlet.SessionDemo02servlet-class>
servlet>
<servlet-mapping>
<servlet-name>SessionDemo02servlet-name>
<url-pattern>/s2url-pattern>
servlet-mapping>
3.启动Tomcat,进行测试: localhost:8080/s2。在java控制台可以得到输出。
Session存储一个类
创建一个Person类,建立 name,age 这个属性。session不仅可以存储字符串,也能去存储一个类:
1.创建一个Person类: 此时的属性为私有属性,所以利用快捷键 ALT+ INSERT创建公共属性。
package com.AL.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 void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.在创建的Session类中,去存储一个 person 类:
package com.AL.servlet;
import com.AL.pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
// session。 存放一个字符串
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=utf-8"); // 使文档可以访问,还有编码
//得到一个session
HttpSession session = req.getSession();
// 给session中存放东西。 服务器对客户进行登记
session.setAttribute("name", new Person("鑫仔",1));//存储一个 person类
// 获取session的ID。 且每个客户端的sessionID是唯一的
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);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.启动Tomcat测试。
Session注销:
创建一个Session。
package com.AL.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
// 手动注销session
session.invalidate();
System.out.println("over!!!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
配置web.xml文件:
<servlet>
<servlet-name>SessionDemo03servlet-name>
<servlet-class>com.AL.servlet.SessionDemo03servlet-class>
servlet>
<servlet-mapping>
<servlet-name>SessionDemo03servlet-name>
<url-pattern>/s3url-pattern>
servlet-mapping>
如果想要自动注销session,那么在web.xml配置文件中进行:
<session-config>
<session-timeout>1session-timeout>
session-config>
那么, 一个网站,究竟如何证明你来过 ?
假如两个用户去想要得到对方的数据,就需要==ServletContext,即 applicatiContext:==就好比前面的多个servlet程序中共享数据一样。
javaweb 动态web的技术栈有 JSP/Servlet。
前面我们已经创建一个Servlet程序完成了简单的动态web。
这里讲解使用 JSP 技术栈的动态 web。
什么是JSP?
Java Server Pages:Java服务器端页面,也和Servlet一样,用于动态web技术!
最大的特点:
写jsp就像在写HTML
区别:
思路:JSP究竟是如何执行的?
代码层面没有任何问题
服务器内部工作
tomcat中有一个work目录;
在IDEA中使用Tomcat的,会在IDEA中的tomcat中产生一个work目录
我的电脑上的地址为:C:\Users\ASUS.IntelliJIdea2019.3\system\tomcat\Unnamed_javaweb-02_servlet\work\Catalina\localhost\r1\org\apache\jsp
在此页面下转换成了 java程序:
所以 jsp到底怎么执行?
上面的图片中可以发现, jsp 最终也会被转换成一个 java类。
我们去查看里面的代码:
//初始化
public void _JspInit(){
}
//销毁
public void _jspDestroy(){
}
//JSPService
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response){}
在这个 jspService 中的代码的内容有:
判断请求:
内置一些对象:
final javax.servlet.jsp.PageContext pageContext;//页面上下文
javax.servlet.http.HttpSession session=null; //session
final javax.servlet.ServletContext application;//applicationContext
final javax.servlet.ServletConfig config;//config
javax.servlet.jsp.JspWriter out = null;//out
final java.lang.Object page = this;//page:当前页
javax.servlet.jsp.JspWriter _jspx_out = null; //请求
javax.servlet.jsp.PageContext _jspx_page_context = null;//响应
输出页面前增加的代码:
response.setContentType("text/html; charset=UTF-8"); //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, false, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
out = pageContext.getOut();
_jspx_out = out;
以上这些对象我们可以在jsp中直接使用。
我们在 index.jsp中输入的代码为:
<%
String name = "鑫仔";
%>
name:<%=name%>
在jsp页面中,只要是java代码就会原封不动的输出
String name = "鑫仔"; /
如果是html代码,就会转换为 下面的格式进行输出到前端。
out.write(" name:");
out.print(name);
out.write("\n");
所以 JSP的本质就是一个 Servlet。浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
Tomcat 容器是如何创建 Servlet 类实例?用到了什么原理?
从前面的jsp本质上就是一个 Servlet。(自己的理解)jsp前端页面的信息,会经过转换成 *.java文件,再编译变为 *jsp.class 类。 等价于 Servlet类后, 那么这时候 原先的jsp(Servlet类)和Servlet类 会在 web容器中的 web.xml 文件被解析。 读取Servlet注册信息; 然后进行类加载 通过反射的方式实例化 Servlet 类。 有的是 在客户端第一次请求实例化 Servlet类, 然后客户端处理这个经过服务器处理完毕后的 class对象,即Servlet。
1、Jsp 经编译后就变成了 Servlet(Jsp 的本质就是 Servlet,JVM 只能识别 Java 的类,不能识别 Jsp 的代码,Web 容器将 Jsp 的代码编译成 JV M能够识别的 Java 类);
2、Jsp 更擅长表现于页面显示,servlet 更擅长于逻辑控制;
3、Servlet 中没有内置对象,Jsp 中的内置对象都是必须通过 HttpServletRequest 对象、HttpServletResponse 对象以及 HttpServlet 对象得到;
4、Jsp 是 Servlet 的一种简化,使用 Jsp 只需要完成程序员需要输出到客户端的内容,Jsp 中的 Java 脚本如何镶嵌到一个类中,由 Jsp 容器完成。而 Servlet 则是个完整的 Java类,这个类的 Service 方法用于生成对客户端的响应。
我们可以直接在创建Maven项目的时候, 选择 一个maven模板进行创建。
另外一种添加webapp模板 maven项目的方法:在创建一个空的maven项目后,在下图位置处,选择添加,然后找到 web application点击添加。
添加所需要的jar包, 即导入 maven依赖:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.ALgroupId>
<artifactId>javaweb-jspartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>3.0-alpha-1version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2-rev-1version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
dependencies>
project>
基础语法:
任何语言都有自己的语法,JAVA中有。JSP作为java技术的一种应用,它拥有一些自己扩充的语法(了解知道即可),java所有语法都支持!需要符合java语法,所以这个<% %>这个里面的代码注释用//,<% %> 里面是用来写 java代码的 更需要符合java语法。
在jsp,嵌入java代码即可:
<%%>脚本片段
<%= %>输出变量或者表达式
<%! %>声明
<%–注释–%>
jsp表达式:
<%–jsp表达式 作用:将程序的输出,输出到客户端
<% = 变量或者表达式 %> --%>
<% = new java.util.Date() %>
注释写在这样的符号中:<%–注释 --%>
jsp脚本片段:
<%–jsp脚本片段–%>
<%
int sum=0;
for (int i = 0; i <=100 ; i++) {
sum+=i;
}
out.println("Sum="+sum+"
");
%>
<%–脚本再实现,在代码嵌入HTML元素–%>
<%
for (int i = 0; i <5 ; i++) {
%>
hello,world
<%
}
%>
jsp声明:
<%!
static{
System.out.println("Loading Servlet!");
}
private int globalVar =0;
public void kuang(){
System.out.println("进入了方法狂!");
}
%>
JSP声明会被编译到JSP生成java的类中!其他的,会被生成到JSPService方法中。即在IDEA中的tomcat文件中查看root文件里面的java代码可以发现。
我们查看启动Tomcat运行后, 在work文件中root文件中找到 jsp 下的 index_jsp.java 代码:
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
// JSP 的声明写在了
static{
System.out.println("Loading Servlet!");
}
private int globalVar =0;
public void xinxin(){
System.out.println("进入了春天!");
}
jsp的注释,不会在客户端显示。html会显示:
<%-- 我是JSP的注释--%>
写变量的时候,<%=%> 也可以写成**${}** 这样的形式。
<%-- 变量表达式
<%=%>
${} EL表达式
--%>
<%
for (int i = 0; i < 5; i++) { %>
hello,girl${i}!
<% }%>
上述三种基础语法的代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- $END$ --%>
<%-- JSP表达式
<% = 变量或者表达式 %> --%>
<%= new java.util.Date()%>
<br>
<%
String name = "鑫仔";
%>
name:<%=name%>
<br>
<%-- jsp 脚本片段
<% %>脚本片段 --%>
<%
int sum=0;
for (int i = 0; i <=100 ; i++) {
sum+=i;
}
out.println("Sum="
+sum+"");
%>
<br>
<%-- jsp声明 <%! %>声明--%>
<%!
static{
System.out.println("Loading Servlet!");
}
private int globalVar =0;
public void xinxin(){
System.out.println("进入了春天!");
}
%>
<br>
<%--注释--%>
<!--我是 HTML的注释 -->
<%-- 我是JSP的注释--%>
<%-- 变量表达式
<%=%>
${} EL表达式
--%>
<%
for (int i = 0; i < 5; i++) { %>
<h1>hello,girl${i}!</h1>
<% }%>
</body>
</html>
我们在访问页面的时候,有时候会出现访问错误的界面, 如何去定制。
代码 int x =1/0; 错误代码, 因为除数不能为0. 我们定制一个错误的页面,想要在出现 500错误的时候,去跳转到一个500错误的特定信息界面。
设置一个出错的页面。
定义跳转路径。 表示当发生错误的时候,则页面跳转到 error/500.jsp 文件这个界面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- 定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
<%@ page errorPage="error/404.jsp" %>
Title
<%
int x=1/0;
%>
自定义的500的错误的 jsp文件,
我们可以直接让此页面显示 500错误文字信息, 在这里,我们将500错误页面去换成一个图片。 扫描 web 路径下的图片。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%-- 这个是用来设置字体大小的
自定义500错误的界面
--%>
在web.xml中进行配置文件的修改。
—另一种方式:不用在 jsp 文件中定义跳转页面。出现了响应状态码,到对应的jsp页面。
我们也可以直接在 web.xml文件中进行配置修改:这样出现了错误,就直接去跳转到对应的jsp文件执行。
<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-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.cssurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.jsurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.jpgurl-pattern>
servlet-mapping>
<error-page>
<error-code>404error-code>
<location>/error/404.jsplocation>
error-page>
<error-page>
<error-code>500error-code>
<location>/error/500.jsplocation>
error-page>
web-app>
启动,进行测试。
文件夹格式:
JSP指令:
<%@page … %>
<%@>
测试指令**<%@include … %>**:拼接指令。
创建两个jsp文件。 header.jsp 和footer.jsp文件:,且这两个 jsp文件建立在 web目录下的common文件中。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
我是header
Title
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
我是footer
Title
定义一个 jsp3.jsp文件。 想要去展现拼接两个页面的结果。**<%@include … %>**指令
<%--JSP的注释--%>
<%--两个页面拼接在一起: 合二为一--%>
<%@include file="common/header.jsp"%>
网页主体
<%@include file="common/footer.jsp"%>
采用**jsp:include 指令**进行页面拼接。 斜杠 / 表示外部的路径。
<%--两个页面拼接在一起: 单独存在,页面进行拼接--%>
网页主体
启动tomcat,进行测试观察者这两种方式的结果。http://localhost:8080/jsp3.jsp
粗略的看,这两种指令 @include 和 jsp.include 完成的效果一样。 但还是存在着一些区别。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%--JSP的注释--%>
<%--两个页面拼接在一起: 合二为一--%>
<%@include file="common/header.jsp"%>
网页主体
<%@include file="common/footer.jsp"%>
<%--两个页面拼接在一起: 单独存在,页面进行拼接--%>
网页主体
@include 是将两个页面合二为一;jsp:include是将页面进行拼接。
例子: pageContextDemo01.jsp
使用存放东西的这几个内置对象: pageContext、request、session、 application 去存放数据。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%-- 内置对象
在脚本片段的代码,会原封不动生成.jsp.java 要遵循java语法
--%>
<%
pageContext.setAttribute("name1","鑫仔1号");//保存的数据只在一个页面中有效
request.setAttribute("name1","鑫仔2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name1","鑫仔3号");//保存的数据只在一次会话中有效,从打开浏览器道关闭浏览器
application.setAttribute("name1","鑫仔4号");//保存的数据只在服务器中有效,从打开服务器道关闭服务器
%>
<% //从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");
String name5 = (String) pageContext.findAttribute("name5");
%>
<%--使用EL表达式输出 形式为:${}--%>
取出的值为:
${name1}
${name2}
${name3}
${name4}
保存的数据,作用的区域不同,从==底层到高层的作用域分别为:page、request(请求)、session(会话)、application==
pageContext.setAttribute("name1","鑫仔1号");//保存的数据只在一个页面中有效
request.setAttribute("name1","鑫仔2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name1","鑫仔3号");//保存的数据只在一次会话中有效,从打开浏览器道关闭浏览器
application.setAttribute("name1","鑫仔4号");//保存的数据只在服务器中有效,从打开服务器道关闭服务器
新建一个 pageContextDemo02.jsp.
查看哪个有效? 因为作用域不同,存活的时间也是不一样的。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<% //从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");
String name5 = (String) pageContext.findAttribute("name5");
%>
<%--使用EL表达式输出 形式为:${}--%>
取出的值为:
${name1}
${name2}
${name3}
${name4}
${name5}
当我们从 pageContext取出时, 我们通过寻找的方式来。即pageContext.findAttribute()方法。
作用域的顺序为: page->request -> session ->application。类似于JVM中的双亲委任机制。
双亲委任机制: 先找最大,级别最高的,一开始就继承的那个类。 没有了再从高往低找。
Jsp 中的四种作用域包括 page、request、session 和 application,具体来说:
1、page 代表与一个页面相关的对象和属性;
2、request 代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多
个页面,涉及多个 Web 组件,需要在页面显示的临时数据可以置于此作用域;
3、session 代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关
的数据应该放在用户自己的 session 中;
4、application 代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web
应用程序,包括多个页面、请求和会话的一个全局作用域。
对应于上面这4种作用域,
不同的作用域它们之间的关系:
在使用这些标签的时候,需要相应的 jar包。
在 pom.xml文件中 导入maven依赖:
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2-rev-1version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
dependencies>
project>
EL表达式: ${}
我们使用美元符号大括号进行 获取数据和执行运算。
jsp:forward page 页面跳转标签。
在jsptag.jsp中写入一个程序,并指定跳转页面。 去观察跳转的结果。
定义一个页面,功能就是用来跳转的,并给这个页面一些数据信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<h1>1h1>
<%--jsp:include jsp标签--%>
<%--页面跳转标签 jsp:forward page --%>
<jsp:forward page="jsptag2.jsp">
<jsp:param name="name" value="ALZN"/>
<jsp:param name="age" value="18"/>
jsp:forward>
body>
html>
对应的跳转页面 jsptag2.jsp。 利用request.getParameter() 去获取信息。
功能是用来得到来自跳转页面的信息。用来展示信息的:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<h1>2h1>
<%--取出参数
<%=变量名%> <${}> 这两种方式等价
--%>
<%--取出参数--%>
名字:<%=request.getParameter("name")%>
年龄:<%=request.getParameter("age")%>
body>
html>
获取参数的两种方式:
3.这种 jsp 标签页面跳转。 是不需要像 Servlet程序那样进行 web发布的。 直接启动Tomcat进行测试就行了。
输入:http://localhost:8080/jsptag.jsp 结果为:
可以发现, 我们定义的 jsptag.jsp 页面就是会直接发生跳转,响应到 jsptag2.jsp的信息。但是url路径却没变。
关于JSTL标签的简单使用链接:https://www.runoob.com/jsp/jsp-jstl.html
JSTL表达式:
JSTL标签:
核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
标签 | 描述 |
---|---|
用于在JSP中显示数据,就像<%= … > | |
用于保存数据 | |
用于删除数据 | |
用来处理产生错误的异常状况,并且将错误信息储存起来 | |
与我们在一般程序中用的if一样 | |
本身只当做 |
|
检索一个绝对或相对 URL,然后将其内容暴露给页面 | |
基础迭代标签,接受多种集合类型 | |
根据指定的分隔符来分隔内容并迭代输出 | |
用来给包含或重定向的页面传递参数 | |
重定向至一个新的URL. | |
使用可选的查询参数来创造一个URL |
JSTL标签库使用步骤:
例子:
在coreif.jsp文件下:
导入对应的taglib: 这个和前面的 <%@ include 类似。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
使用其中的方法:
if代码测试:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- 引入JSTL核心标签库, 我们才能去使用JSTL标签 core--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Title
if测试
<%--使用EL表达式获取表单中的数据
${param.参数名}
--%>
<%--判断 如果用户提交的是管理员,则登录成功--%>
corewhen.jsp文件下测试 jstl标签库中的
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Title
<%--定义一个变量score,值为85--%>
你的成绩为优秀
你的成绩为一般
你的成绩为良好
你的成绩为不及格
coreforeach.jsp文件下测试:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.ArrayList" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Title
<%
ArrayList people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"赵六");
people.add(4,"田七");
request.setAttribute("list",people);
%>
<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin, 哪里开始
end, 到哪里
step, 步长
--%>
实体类
JavaBean有特定的写法:
一般用来和数据库的字段做映射 ORM;
ORM:对象关系映射
people表:
id | name | age | address |
---|---|---|---|
1 | 鑫仔1号 | 1 | 山西 |
2 | 鑫仔2号 | 2 | 山西 |
3 | 鑫仔3号 | 3 | 山西 |
这个表去对应位一个类的话:
class People{
private int id;
private String name;
private String adress
}
class A{
new People(1,"鑫仔1号",1,"山西");
new People(2,"鑫仔2号",2,"山西");
new People(3,"鑫仔3号",3,"山西");
}
JavaBean 例子:
people类 java程序。
属性私有化:即 private, 这种属性子类不能直接继承,需要get/set方法去将属性创建为一些公共属性去进行调用。
package com.AL.pojo;
public class people {
private int id;
private String name;
private int age;
private String address;
public people() {
}
public people(int id, String name, int age, String address) {
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "people{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
创建数据库。 数据库为jdbc,表名为people:
创建javabean.jsp文件。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%--
换行
是html标签 表示一条直线
--%>
姓名:
年龄:
id:
地址:
启动Tomcat进行测试:http://localhost:8080/javabean.jsp
什么是MVC:Model View Controller 模型、视图、控制器
用户直接访问控制层,控制层就可以直接操作数据库;
就好比,我们前面创建的一个javaweb的 Servlet程序+jsp。 不过jsp主要是用来渲染界面的,虽然本质上也是一个Servlet。 客户端访问服务端,我们在Servlet程序中接收到请求 req, 然后回响应 resp。而当加入数据库后,直接在Servlet代码中进行 JDBC的工作,处理数据库的数据, 然后把操作得到的数据返回给客户端,并且你改了数据还要在服务端中对数据库完成同步 数据持久化。 代码臃肿,不利于维护。
servlet–CRUD–>数据库
弊端:程序十分臃肿,不利于维护 (要在Servlet里面写JDBC的代码)
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序猿调用
|
JDBC (实现该接口)
|
Mysql Oracle SqlServer …(不同厂商)
改进:MVC架构如下所示, Model、View、Controller
三层架构中,各自主要负责的功能为:
Model
View
Controller (Servlet):
在MVC三层架构中, 我们不再让Servlet独自一人完成刚才的 请求、响应、视图跳转、JDBC、业务代码等工作。
Filter:过滤器,用来过滤网站的数据;
创建maven项目。导入maven依赖,这里特地增加了 数据库连接的依赖。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.ALgroupId>
<artifactId>javaweb-filterartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>3.0-alpha-1version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2-rev-1version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
dependencies>
project>
编写过滤器 filter类。
我们想要去进行过滤所有的代码,让其进行编码 UTF-8。 新建一个 CharacterEncodingFilter 类。
注意:此时的过滤器导入的包为 java.servlet.* 。
package com.AL.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
// 初始化: web服务器启动,就已经初始化了,随时等待过滤对象出现
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//Chain:链
/*
* 1.过滤中的所有代码,在过滤特定请求的时候都会执行
* 2.必须要让过滤器继续同行
* chain.doFilter(request,response);
* */
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("CharacterEncodingFilter执行前");
filterChain.doFilter(servletRequest,servletResponse); //让我们的请求继续走,如果不写的话,程序到这里就被拦截停止
System.out.println("CharacterEncodingFilter执行后");
}
// 销毁: web服务器关闭的时候,过滤器就会被销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
编写Servlet类。
新建一个showFilter,servlet程序。添加编码和没有编码,分别进行调试:
注意:如果有1000个servlet程序响应, 那么我们就要输1000次编码 utf-8。 所以我们想要过滤器去做这件事情。
package com.AL.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.getWriter().write("你好,李焕英!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
编写web.xml配置文件.
注册Servlet类和 Servlet的映射路径。定义两种 添加编码和没有编码,分别进行调试: 即一种
过滤器 filetr的注册和映射路径。
<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>ShowServletservlet-name>
<servlet-class>com.AL.servlet.ShowServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>ShowServletservlet-name>
<url-pattern>/servlet/showurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>ShowServletservlet-name>
<url-pattern>/showurl-pattern>
servlet-mapping>
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>com.AL.filter.CharacterEncodingFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/servlet/*url-pattern>
filter-mapping>
web-app>
启动Tomcat进行测试。
设计一个过滤器的步骤:
在 servlet程序和服务器之间添加一些过滤器,完成请求和响应的一些功能,解决乱码和过滤不必要的请求。
实现一个监听器的接口;(有N种接口)
例子:
统计网站在线人数。
编写一个 session的监听器程序。 在服务器中存储这种 网站在线人数的信息, 不存放在 cookie里面。
创建session监听:每次创建session,就触发httpSessionEvent 事件。观察得到的ID
销毁session监听:
package com.AL.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineCountListener implements HttpSessionListener {
//创建 session监听: 查看你的一举一动
// 一旦创建了 Session就会触发一次这个事件
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
ServletContext ctx = httpSessionEvent.getSession().getServletContext();
System.out.println(httpSessionEvent.getSession().getId());
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就会触发一次这个事件!
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
ServletContext ctx = httpSessionEvent.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);
}
}
在index.jsp中去获得在线人数的数据,用于界面展示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title$
当前有 <%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>人在线
配置文件web.xml监听事件的注册:
<listener>
<listener-class>com.AL.listener.OnlineCountListenerlistener-class>
listener>
添加测试:查看是有几个,具体标号
//查看具体标号
System.out.println(httpSessionEvent.getSession().getId());
多开几个浏览器进行测试。此时java控制台显示的3个人的标号 getId. 三个人在线。
E94BC8A2E7DF88FE4397B8A0D0C032E4
DD3304FD19601E9BC73FF08F3AE96B81
123623BDC7FAE4355487EEEE0F801047
session销毁有自动和手动两种方式,如下所示:
手动销毁
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
ServletContext ctx = httpSessionEvent.getSession().getServletContext();
httpSessionEvent.getSession().invalidate();//手动销毁
自动销毁
<session-config>
<session-timeout>1session-timeout>
session-config>
监听事件的例子:
package com.AL.listener;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
//监听事件的例子
public class TestPanel {
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(0,255,0)); //设置背景颜色
frame.add(panel);
frame.setVisible(true);
//监听事件,监听关闭事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
}
});
}
}
1.登录界面 login.jsp。
在这里定义登录界面, 使用 post方法去获取页面前端参数。 请求路径为 /servlet/login。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
登录
2.创建一个 servlet程序。
获取前端的数据后,进行重定向,实现页面跳转。 方法和前端处的一样为 post。
package com.AL.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// 获取登录页面的参数信息
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取前端请求的参数
String username = req.getParameter("username");
if (username.equals("admin")){ //登录成功
req.getSession().setAttribute("USER_session", req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");
} else { //登录失败
resp.sendRedirect("/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.定义登录成功和失败的 jsp页面。
注意路径,success.jsp在 sys目录下。 error.jsp在同一级目录下。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
主页
error.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
错误
没有权限,用户名错误
返回登录界面
4.web.xml配置文件。
<servlet>
<servlet-name>LoginServletservlet-name>
<servlet-class>com.AL.servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>LoginServletservlet-name>
<url-pattern>/servlet/loginurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>LogoutServletservlet-name>
<servlet-class>com.AL.servlet.LogoutServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>LogoutServletservlet-name>
<url-pattern>/servlet/logouturl-pattern>
servlet-mapping>
启动Tomcat进行测试:在浏览器中输入 localhost:8080/login.jsp, 然后在接收到请求后,即提交动作 submit会 会在web.xml文件中找到此Servlet的注册信息去进行 servlet ,对前端客户端的信息进行获取,然后去响应 进行重定向 页面跳转。
成功进入登录页面:
在用户名错误的时候:
无法登录成功.
但是在测试的时候,你直接输入http://localhost:8080/sys/success.jsp 也会直接进入 登录成功的页面。 我们要使用过滤器 去阻止这种操作。 页面拦截的作用、
5.过滤器拦截。
对于登录成功的页面:/sys/success.jsp 这个界面。 我们设置了一个 USER_SESSION 去获取 session的ID, 当ID==null的时候,这说明没有进行页面登录中进行登录成功的 事件, 所以会直接拦截,让其去跳转到 错误页面。
package com.AL.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
// 初始化: web服务器启动,就已经初始化了,随时等待过滤对象出现
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//SysFilter过滤器
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
if (request.getSession().getAttribute("USER_SESSION") == null) {
response.sendRedirect("/error.jsp");
}
chain.doFilter(request, response);
}
// 销毁: web服务器关闭的时候,过滤器就会被销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
在拦截器 Servlet接口实现类的步骤:
6.过滤器的web.xml配置文件信息。
<filter>
<filter-name>SysFilterfilter-name>
<filter-class>com.AL.filter.SysFilterfilter-class>
filter>
<filter-mapping>
<filter-name>SysFilterfilter-name>
<url-pattern>/sys/*url-pattern>
filter-mapping>
启动Tomcat进行测试,直接输入:localhost:8080/sys/success.jsp 发现此时无法将纳入登录成功的页面:
简单的来说 JDBC就是一个统一驱动, 用于 java去连接 数据库驱动。
我们在 mysql数据库学习中, 在IDEA中去进行JDBC练习时,导入的jar包有:
需要jar包的支持:
在这里,我们使用Maven,创建 maven项目后,直接导入 maven的依赖即可:
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
dependencies>
创建数据库:
CREATE TABLE `users` (
`id` INT(11) NOT NULL,
`name` VARCHAR(40) DEFAULT NULL,
`password` VARCHAR(40) DEFAULT NULL,
`email` VARCHAR(40) DEFAULT NULL,
`birthday` DATE DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
向其中添加几组数据: 例子:
-- 注意,在进行创建数据库的时候, 关于 列表名 column 要使用 飘号进行包裹, 而不是单引号,
-- 因为在这里的意义不是字符串,而是属性段
INSERT INTO `users`(`id`,`name`,`password`,`email`,`birthday`)
VALUES('3','坤坤','123456','[email protected]','2021-1-1'),('4','略略','123456','[email protected]','2021-1-1')
INSERT INTO `users`(`id`,`name`,`password`,`email`,`birthday`)
VALUES('5','坤坤','123456','[email protected]','2021-1-1');
INSERT INTO `users`(`id`, `name`, `password`, email, birthday)
VALUES(6,'呜呜','123456','[email protected]','2021-1-1');
JDBC的步骤,整个流程:
普通的SQL执行对象 Statement:
package com.AL.test;
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 数据库的配置信息
// useUnicode=true&characterEncoding=utf-8 解决中文乱码
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. 用这个对象去完成 操作CRUD
Statement statement = connection.createStatement();
// 4.编写 SQL语句
String sql = "select * from users";
// 5.使用 statement 即能够执行sql的对象 去 进行具体的sql语句。 查询语句返回的是一个结果集: ResultSet
ResultSet rs = statement.executeQuery(sql); // 查询使用executeQuery. 增删改使用executeUpdate()
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();
}
}
采用预编译的方法。
package com.AL.test;
import java.sql.*;
public class TestJDBC2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 数据库的配置信息
// useUnicode=true&characterEncoding=utf-8 解决中文乱码
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. 预编译. 向数据库发送 SQL的对象 PreparedStatement: CRUD. 用这个对象去完成 操作CRUD
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,7); //给第一个占位符?的赋值为 1;
preparedStatement.setString(2, "乌日三省吾身");
preparedStatement.setString(3,"787878");
preparedStatement.setString(4,"[email protected]");
preparedStatement.setString(5, String.valueOf(new Date(new java.util.Date().getTime())));
// 5.使用 preparedStatement 即能够执行sql的对象 去 进行具体的sql语句。
// 查询语句返回的是一个结果集: ResultSet.查询使用executeQuery.
// 增删改使用executeUpdate(). 返回的是一个
int i = preparedStatement.executeUpdate();
if (i>0) System.out.println("插入成功");
// 6.关闭连接,释放资源。 遵循先开后关的原则
preparedStatement.close();
connection.close();
}
}
事务的性质: ACID原则:原子性、一致性、隔离性、持久性。
事务:
事务完成的步骤:
需要导入的jar包: Junit单元测试
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
简单使用
@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!
@Test
public void test(){
System.out.println("Hello");
}
搭建一个环境去设计事务: 银行转账
创建数据库:
-- 创建账单 account 数据表
CREATE TABLE `account`(
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET = utf8
INSERT INTO `account`(`name`,`money`)
VALUES ('A',2000.00),('B',1000);
-- 此时输入的A是字符串的意思,并不是表名,所以用单引号,不用`。
JDBC程序:
但是需要添加事务回滚 rollback, 所以采用 try catch方法去进行判断:事务失败则回滚,
package com.AL.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC3 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 数据库的配置信息
// useUnicode=true&characterEncoding=utf-8 解决中文乱码
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. 用这个对象去完成 操作CRUD
// Statement statement = connection.createStatement();
try {
// 3.通知数据库开启事务, false开启
connection.setAutoCommit(false);
String sql = "update account set money = money-1000 where name='A';";
connection.prepareStatement(sql).executeUpdate();
// 制造错误
//int i =1/0;
String sql2 = "update account set money = money-200 where name='B';";
connection.prepareStatement(sql2).executeUpdate();
connection.commit(); //以上两条SQL都执行成功了,就提交事务
System.out.println("success");
} catch (Exception e) {
try {
//如果出现异常,就通知数据库回滚事务
connection.rollback();
}catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}