Web(含小型項目)
web
文章資源:
链接:https://pan.baidu.com/s/18YhBiuRQzC7-hrdw3LtkjA
提取码:8888
文章目录
- web
- 1.软件架构
- 2.资源分类
- 3.网络通讯三要素
- 4.web服务器软件
- Tomcat
- 1.概述
- 2.下载安装以及配置
- Servlet
- 1.概率
- 2.快速入门
- 3.执行原理
- 4.Servlet中的生命周期方法
- 4.Servlet 3.0以上
- 5.Servlet体系结构
- 6.Servlet的相关配置
- HTTP协议
- 1.概念
- 2.请求消息数据格式
- 3.响应消息数据格式
- Request
- 1.原理
- 2.Request对象继承体系结构
- 3.Request获取请求消息
- 4.登录案例
- Response
- 1.功能
- 2.重定向
- 3.服务器输出字符数据到浏览器
- 4.服务器输出字节数据到浏览器
- 5.验证码
- ServletContext
- 1.概念
- 2.获取
- 3.功能
- 4.文件下载
- 会话技术
- 1.会话技术
- 2.Cookie
- 1.概念
- 2.快速入门
- 3.实现原理
- 4.cookie的细节
- 5.Cookie的特点和作用
- 6.案例:记住上一次访问时间
- 3.Session
- 1.概念
- 2.快速入门
- 3.原理
- 4.细节
- 5.session的特点
- 6.案例:验证码
- JSP入门学习
- 1.概念
- 2.原理
- 3.JSP的脚本
- 4.JSP的内置对象
- 5.案例:改造Cookie案例
- JSP进阶
- 1.指令
- 2.注释
- 3.内置对象
- MVC:开发模式
- 1.jsp演变历史
- 2.MVC:
- EL表达式
- 1.概念
- 2.作用
- 3.语法
- 4.注意
- 5.使用
- 1.运算
- 2.获取值
- 3.隐式对象
- JSTL
- 1.概念
- 2.作用
- 3.使用步骤
- 4.常用的JSTL标签
- 5.练习
- 三层架构:软件设计架构
- 案例:用户信息列表展示
- 1.需求
- 2.设计
- 3.开发
- 1.环境搭建
- 2.编码
- 1.列表查詢分析
- 2.添加功能分析
- 3.刪除功能分析
- 4.修改功能分析
- 5.刪除选中功能分析
- 6.分页查询功能分析
- 7.复杂条件查询分析
- 4.测试
- 5.部署运维
- Filter:过滤器
- 1.概念
- 2.快速入门
- 3.过滤器细节
- 4.案例
- 1.案例1_登录验证
- 2.案例2_敏感词汇过滤
- Listener:监听器
- 1.概念
- 2.注解
1.软件架构
1.C/S:客户端/服务器端
2.B/S:浏览器/服务器端
2.资源分类
1.静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源,静态资源可以直接被浏览器解析
如:html、css、JavaScript
2.动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资 源,在返回给流量器
如:servlet/jsp、php、asp…
3.网络通讯三要素
1.IP:电子设备(如:计算机)在网络中的唯一标识。
2.端口:应用程序在计算机中的唯一标识。0~65536
3.传输协议:规定了数据传输的规则。
基础协议:
1.tcp:安全协议,三次握手。速度慢
2.upd:不安全协议。速度快
4.web服务器软件
1.服务器:按照了服务器软件的计算机。
2.服务器软件:接收用户的请求,处理请求,做出响应。
3.web服务器软件:接收用户的请求,处理请求,做出响应。
在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目
4.常见的java相关的web服务器软件:
1.webLogic:Oracle公司的,大型的JavaEE服务器,支持所有的JavaEE规范,需要收费的
2.webSphere:IBM公司的,大型的JavaEE服务器,支持所有的JavaEE规范,需要收费的
3.JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,需要收费的
4.Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范,开源免费的
5.JavaEE:Java语言在企业级开发中使用的技术规范的总和,一共规范了13项大的规范。
Tomcat
1.概述
Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范,开源免费的
2.下载安装以及配置
1.下载:https://tomcat.apache.org/
2.安装:解压压缩包即可
注意:安装目录建议不要有空格或中文
3.卸载:删除目录即可
4.启动
1.bin/startup.bat,双击运行该文件即可
2.访问:浏览器输入:http:localhost:8080 回车访问
3.可能遇到的问题
1.命令行窗口一闪而过:
原因:没有正确配置JAVA_HOME环境变量
解决方案:正确配置JAVA_HOME环境变量
Tomcat的启动需要依赖于JDK
2.启动报错
1.暴力:找到占用的端口号,并且找到对应的进程,杀死该进程
2.温柔:修改端口号
5.关闭
1.运行bin/shutdown.bat
2.ctrl+c
6.配置
部署项目的方式
1.直接将项目放到webapps目录下
运行:localhost:8080/hello/hello.html
2.简便方式,将运行的hello目录(里边有hello.html文件)先压缩,然后修改后缀名为*.war
运行:localhost:8080/hello/hello.html
3.配置conf/server.xml文件
运行:localhost:8080/hehe/hello.html
4.在conf\Catalina\localhost目录下创建任意名称的xml文件。在文件中编写图中内容
运行:localhost:8080/bbb/hello.html
Servlet
1.概率
Servlet:server applet
运行在服务器端的小程序
Servlet就是一个接口,定义了Java类被浏览器访问到(Tomcat识别)的规则。
将来我们自定义一个类,实现Servlet接口,复写方法。
2.快速入门
1.创建JavaEE项目
…
2.定义一个类,实现Servlet接口
这里需要注意:使用Servlet需要导包
在pom.xml中进行导包
<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency>
</dependencies>
测试代码
package com.kk.web.servlet;import javax.servlet.*;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : servlet快速入門*/
public class Demo01 implements Servlet {}
3.实现接口中的抽象方法
package com.kk.web.servlet;import javax.servlet.*;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : servlet快速入門*/
public class Demo01 implements Servlet {@Overridepublic void init(ServletConfig config) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}/*** 提供服務的方法* @param req* @param res* @throws ServletException* @throws IOException*/@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("Hello Servlet");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}
4.配置Sservlet
在web.xml中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- 配置Servlet--><servlet><servlet-name>demo01</servlet-name><servlet-class>com.kk.web.servlet.Demo01</servlet-class></servlet><servlet-mapping><servlet-name>demo01</servlet-name><url-pattern>/demo01</url-pattern></servlet-mapping></web-app>
運行結果
3.执行原理
1.当服务器接收到客户端浏览器的请求后,会解析请求url路径,获取访问的Servlet的资源路径
2.查找web.xml文件,是否有对应的标签体内容
3.如果有,则再找到对应的全类名
4.tomcat会将字节码文件加载进内存,并且创建其对象
5.调用其方法
4.Servlet中的生命周期方法
1.被创建:执行init方法,只执行一次
1.Servlet什么时候被创建?
默认情况下第一次被访问时,Servlet被创建。
2.可以配置指定Serlvet的创建时机
在web.xml中的<servlet>标签下配置
1.第一次被访问时,创建
的值为负数
2.在服务器启动时,创建
的值为0或正整数
3.Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
问题:多个用户同时访问时,可能存在线程安全问题。
解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量也不要对其修改值。``
2.提供服务:执行service方法,执行多次
每次访问Serlvet时,service方法都会被调用一次。
3.被销毁:执行destroy,只执行一次
1.Servlet被销毁时执行。服务器关闭时,Serlvet被销毁。
2.只有服务器正常关闭时,才会执行destroy。
3.destroy访问在Servlet被销毁之前执行,一般用于释放资源
代码
package com.kk.web.servlet;import javax.servlet.*;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : servlet的方法*/
public class Demo02 implements Servlet {/*** 初始化方法* 在Servlet被创建时被执行,只会执行一次** @param config* @throws ServletException*/@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("init...");}/*** 获取ServletConfig对象* ServletConfig:Servlet的配置对象* @return*/@Overridepublic ServletConfig getServletConfig() {return null;}/*** 提供服务方法* 每一次Servlet被访问时就执行,执行多次** @param req* @param res* @throws ServletException* @throws IOException*/@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("service...");}/*** 获取Serlvet的一些信息 版本、作者等...* @return*/@Overridepublic String getServletInfo() {return null;}/*** 消费方法* 在服务器正常关闭时执行,只会执行一次*/@Overridepublic void destroy() {System.out.println("destroy...");}
}
4.Servlet 3.0以上
|>好处
支持注解配置。可以不需要web.xml了。
|>步骤:
1.创建JavaEE项目,选择Servlet的版本3.0以上,可以不选择web.xml
2.定义一个类,实现Serlvet接口
3.复写方法
4.在类上使用@WebServlet注解,进行配置
@WebServlet(“资源路径”)
代码演示
package com.kk.web.servlet;import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : 注解配置访问路径*/
//@WebServlet(urlPatterns = "/demo03")
@WebServlet("/demo03")
public class Demo03 implements Servlet {@Override public void init(ServletConfig config) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("Serlvet 3.0+++");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}
5.Servlet体系结构
1.Servlet — 接口
|
2.GenericServlet — 抽象类
|
3.HttpServlet — 抽象类
|>GenericServlet:将Serlvet接口中的其他的方法做了默认空实现,只将service()方法作为抽象
将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
|>HttpServlet:对http协议的一种封装,简化操作
1.定义类继承HttpServlet
2.复写doGet/doPost方法
代码演示GenericServlet
package com.kk.web.servlet;import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : Servlet体系结构*/
@WebServlet("/demo05")
public class Demo05 extends GenericServlet {@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("GenericServlet--->service...");}
}
代码演示HttpServlet
package com.kk.web.servlet;import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : Servlet体系结构*/
@WebServlet("/demo06")
public class Demo06 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doGet...");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doPost...");}
}
在web目录下创建login.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/demo06" method="post"><label><input name="username"></label><input type="submit" value="提交"></form></body>
</html>
访问:http://localhost:8080/login.html
6.Servlet的相关配置
1.urlpartten:Servlet的访问路径
一个Servlet可以定义多个访问路径:@WebServlet({“/d07”,“/demo07”,“/de07”})
2.路径定义规则
|> /xxx
|> /xxx/xxx
|> *.do
代码演示
package com.kk.web.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : Servlet的相关配置*/
//@WebServlet({"/d07","/demo07","/de07"})
@WebServlet("/user/demo07")
//@WebServlet("/user/*")
//@WebServlet("*.do")
public class Demo07 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doGet--->Demo07...");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doPost--->Demo07...");}
}
HTTP协议
1.概念
Hyper Text Transfer Protocol:超文本传输协议
传输协议:定义了客户端和服务器端通信时,发送数据的格式
特点:
1.基于tcp/ip的高级协议
2.默认端口号:80
3.基于请求/响应模型,一次请求一次响应
4.无状态的:每次请求之间相互独立,不能交互数据
历史版本:
1.0:每一次请求都会建立新的连接
1.1:复用连接
2.请求消息数据格式
请求消息:客户端发生给服务器端的数据
1.请求行
请求方式 请求url 请求协议/版本
GET /login.html HTTP/1.1
请求方式:
HTTP协议中有7中请求方式,常用的有2种
|> GET
1.请求参数在请求行中,即在url后
2.请求的url长度是有限制的
3.不太安全
|> POST
1.请求参数在请求体中
2.请求的url长度是没有限制的
3.相对安全
2.请求头:客户端浏览器告诉服务器一些信息
请求头名称:请求头值
常见的请求头:
1.User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
可以在服务器端获取该头的信息,解决浏览器的兼容性问题
2.Referce:http://localhost/login.html
告诉服务器,我(当前请求)从哪里来
作用
防盗链:
统计工作:
3.请求空行
|> 空行,用于分割POST请求的请求头和请求体的
4.请求体(正文)
|> 封装POST请求消息的请求参数的
3.响应消息数据格式
响应消息:服务器端发生给客户端的数据
|> 数据格式:
1.响应行
1.组成:协议/版本 响应状态码 状态码描述
2.响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
1.状态码都是3位数字
2.分类:
|> 1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx多的状态吗。
|> 2xx:成功。代表:200
|> 3xx:重定向。代表:302(重定向),304(访问缓存)
|> 4xx:客户端错误。代表:404(请求路径没有对应的资源),405(请求方式没有对应的doXxx方法)
|> 5xx:服务器错误。代表:500(服务器内部出现异常)
2.响应头
1.格式:头名称:值
2.常见的响应头:
1.Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
2.Content-disposition:服务器告诉客户端以什么格式打开响应体数据
值:
in-line:默认值,在当前页面内打开
attachment:以附件形式打开响应体。文件下载
3.响应空行
4.响应体
传输的数据
Request
1.原理
|> request对象和response对象的原理
1.request和response对象是由服务器创建的。我们来使用他们
2.request对象是来获取请求消息,response对象是来设置响应消息
2.Request对象继承体系结构
|> ServletRequest – 接口
| 继承
|> HttpServletRequest – 接口
| 实现
|> org.apache.catalina.connector.RequestFacade 类(tomcat编写的)
3.Request获取请求消息
1.获取请求消息数据
1.获取请求行数据
GET /user/demo01/username=zhangsan HTTP/1.1
方法:
1.获取请求方式:GET
String getMethod()
2.获取虚拟目录:/user
String getContextPath()
3.获取Servlet路径:/demo01
String getServletPath()
4.获取get方式的请求方式:username=zhangsan
String getQueryString()
5.获取请求的URI:/user/demo01
String getRequestRUI(): /user/demo01
StringBuffer getRequestURL():http://localhost:8080/user/demo01
6.获取协议及版本:HTTP/1.1
String getProtocol()
7.获取客户机的IP地址
String getRemoteAddr()
代码演示
package com.kk.web.request;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : http://localhost:8080/requestDemo01?username=zhangsan*/
@WebServlet("/requestDemo01")
public class Demo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String method = request.getMethod();System.out.println(method);String contextPath = request.getContextPath();System.out.println(contextPath);String servletPath = request.getServletPath();System.out.println(servletPath);String queryString = request.getQueryString();System.out.println(queryString);String requestURI = request.getRequestURI();StringBuffer requestURL = request.getRequestURL();System.out.println(requestURI);System.out.println(requestURL);String protocol = request.getProtocol();System.out.println(protocol);String remoteAddr = request.getRemoteAddr();System.out.println(remoteAddr);/*** GET** /requestDemo01* username=zhangsan* /requestDemo01* http://localhost:8080/requestDemo01* HTTP/1.1* 0:0:0:0:0:0:0:1*/}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
2.获取请求头数据
方法:
String getHeader(String name):通过请求头的名称获取请求头的值
Enumeration getHeaderNames():获取所有的请求头名称
代码演示1
package com.kk.web.request;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Enumeration;
/*** @author : k* @Date : 2022/8/1* @Desc : 获取请求头数据*/@WebServlet("/requestDemo02")
public class Demo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取所有的请求头名称Enumeration<String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();//根据名称获取请求头的值String value = request.getHeader(name);System.out.println(name +":" + value);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
代码演示2
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;/*** @author : k* @Date : 2022/8/1* @Desc : 获取请求头数据*/@WebServlet("/requestDemo03")
public class Demo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求头数据 user-agentString agent = request.getHeader("user-agent");//判斷agent的浏览器版本if (agent.contains("Chrome")){System.out.println("谷歌");}else if (agent.contains("Firefox")){System.out.println("火狐");}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
代码演示3
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : 获取请求头数据*/@WebServlet("/requestDemo04")
public class Demo04 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求头数据 refererString referer = request.getHeader("referer");System.out.println(referer); //http://localhost:8080/login.html//防盗链//若正版连接 http://localhost:8080/youku/login.htmlif (referer != null) {if (referer.contains("/youku")) {//正常访问System.out.println("正常播放电影中...");response.setContentType("text/html;charset=utf-8");response.getWriter().write("正常播放电影中...");} else {//盗链//当不是这个连接(http://localhost:8080/youku/login.html)去访问(http://localhost:8080/requestDemo04)的时候会进行防盗链System.out.println("想看电影? 来优酷吧...");response.setContentType("text/html;charset=utf-8");response.getWriter().write("想看电影? 来优酷吧...");}}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/demo06" method="post"><label><input name="username"></label><input type="submit" value="提交"></form><a href="/requestDemo04">requestDemo04</a></body>
</html>
3.获取请求体数据
请求体:只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数
步驟:
1.获取流对象
BufferedReader getReader():获取字符输入流,只能操作字符数据
ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
2.再从流对象中拿数据
代码演示
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : 获取请求体数据*/@WebServlet("/requestDemo05")
public class Demo05 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求消息体 --- 请求参数//获取字符流BufferedReader br = request.getReader();//读取数据String line = null;while ((line = br.readLine())!=null){System.out.println(line);}}
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/requestDemo05" method="post"><input type="text" placeholder="请输入用户名" name="username"> <br><input type="text" placeholder="请输入密码" name="password"> <br><input type="submit" value="注册"></form>
</body>
</html>
4.其他功能
1.获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
1.String getParameter(String name):根据参数名称获取参数值
2.String[] getParameterValues(String name):根据参数名称获取参数值的数组
3.Enumeration getParameterNames():获取所有请求的参数名称
4.Map<String,String[]> getParameterMap():获取所有参数的map集合
代码演示
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;/*** @author : k* @Date : 2022/8/1* @Desc : 获取请求体数据*/@WebServlet("/requestDemo06")
public class Demo06 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//post获取请求参数String username = request.getParameter("username");System.out.println(username);System.out.println("--------------------------------------");//根据参数名称获取参数值的数组String[] hobbies = request.getParameterValues("hobby");for (String hobby : hobbies) {System.out.println(hobby);}System.out.println("--------------------------------------");//获取所有请求参数名称Enumeration<String> parameterNames = request.getParameterNames();while (parameterNames.hasMoreElements()){String name = parameterNames.nextElement();System.out.println(name);String value = request.getParameter(name);System.out.println(value);System.out.println("......");}System.out.println("--------------------------------------");//获取所有参数的map集合Map<String, String[]> parameterMap = request.getParameterMap();Set<String> keySet = parameterMap.keySet();for (String name : keySet) {//根据键获取值String[] values = parameterMap.get(name);System.out.println(name);for (String value : values) {System.out.println(value);}System.out.println("......");}}
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/requestDemo06" method="post"><input type="text" placeholder="请输入用户名" name="username"> <br><input type="text" placeholder="请输入密码" name="password"> <br><input type="checkbox" name="hobby" value="game">游戏<br><input type="checkbox" name="hobby" value="study">学习<br><input type="submit" value="注册">
</form></body>
</html>
中文乱码问题
get方法:tomcat8以上已经将get方式乱码问题解决了
post方式:会乱码
解决:
在获取参数前,设置request的编码
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;/*** @author : k* @Date : 2022/8/1* @Desc : 获取请求体数据*/@WebServlet("/requestDemo06")
public class Demo06 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置流的字符集request.setCharacterEncoding("utf-8");//post获取请求参数String username = request.getParameter("username");System.out.println(username);}
}
2.请求转发
|> 一种在服务器内部的资源跳转方式
|> 步骤
1.通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path);
2.使用RequestDispatcher这个对象来进行转换:forward(ServletRequest request, ServletResponse response)
|> 特点
1.浏览器地址栏路径没有发生变化
2.只能转发到当前服务器内部资源中
3.转发是一次请求
代码演示
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;/*** @author : k* @Date : 2022/8/1* @Desc : 请求转发*/@WebServlet("/requestDemo07")
public class Demo07 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Demo07被访问了...");//转发到demo8资源request.getRequestDispatcher("/requestDemo08").forward(request, response);}
}
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;/*** @author : k* @Date : 2022/8/1* @Desc : 请求转发*/@WebServlet("/requestDemo08")
public class Demo08 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Demo08被访问了...");}
}
3.共享数据
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源共享数据
方法:
1.void setAttribute(String name,Object obj):存储数据
2.Object getAttribute(String name):通过键获取值
3.void removeAttribute(String name):通过键移除键值对
代码演示
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;/*** @author : k* @Date : 2022/8/1* @Desc : 请求转发*/@WebServlet("/requestDemo07")
public class Demo07 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Demo07被访问了...");//存取数据到request域中request.setAttribute("message","hello");//转发到demo8资源request.getRequestDispatcher("/requestDemo08").forward(request, response);}
}
package com.kk.web.request;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;/*** @author : k* @Date : 2022/8/1* @Desc : 请求转发*/@WebServlet("/requestDemo08")
public class Demo08 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Demo08被访问了...");//获取数据Object message = request.getAttribute("message");System.out.println(message);}
}
4.获取ServletContext
ServletContext getServletContext()
代码演示
package com.kk.web.request;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc : 获取ServletContext*/@WebServlet("/requestDemo09")
public class Demo09 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ServletContext servletContext = request.getServletContext();System.out.println(servletContext);}
}
4.登录案例
用户案例需求:
1.编写login.html登录页面
username & password 两个输入框
2.使用Druid数据库连接池技术,操作mysql中的user表
3.使用jdbcTemplate技术封装jdbc
4.登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您
5.登录失败跳转到FaildServlet展示:登录失败,用户名或密码错误
分析
开发步骤
1.创建项目导入html页面,配置文件以及导包
html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Login</title>
</head>
<body><form action="" method="post">用户名:<input type="text" name="username"> <br>密码:<input type="password" name="password"> <br><input type="submit" value="登录"></form></body>
</html>
配置文件
放置在resources目录下
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db1?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
characterEncoding=utf-8
username=root
password=123456initialSize=5maxActive=10maxWait=3000validationQuery=SELECT 1testWhileIdle=true
导包
<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.4</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.11</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.20</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>compile</scope></dependency>
</dependencies>
2.创建数据库环境
/*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 80027Source Host : localhost:3306Source Schema : db1Target Server Type : MySQLTarget Server Version : 80027File Encoding : 65001Date: 01/08/2022 22:20:13
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT,`username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`password` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'admin', '123456');
INSERT INTO `user` VALUES (2, 'test', '123456');SET FOREIGN_KEY_CHECKS = 1;
3.创建domain包在里边创建User实体类
package com.kk.web.domain;/*** @author : k* @Date : 2022/8/1* @Desc :*/
public class User {private Integer id;private String username;private String password;public User() {}public User(Integer id, String username, String password) {this.id = id;this.username = username;this.password = password;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
4.创建dao包,创建接口UserDao,提供login方法,创建实现类UserDaoImpl实现UserDao方法
UserDao
package com.kk.web.dao;import com.kk.web.domain.User;/*** @author : k* @Date : 2022/8/1* @Desc :*/
public interface UserDao {/*** 登录方法* @param user* @return*/User login(User loginUser);
}
UserDaoImpl
package com.kk.web.dao;import com.kk.web.domain.User;import com.kk.web.util.jdbcUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;/*** @author : k* @Date : 2022/8/1* @Desc :*/
public class UserDaoImpl implements UserDao {//声明JdbcTemplate对象共用private JdbcTemplate template = new JdbcTemplate(jdbcUtils.getDataSource());@Overridepublic User login(User loginUser) {//编写sqlString sql = "select * from user where username = ? and password = ?";//调用template方法User user = template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),loginUser.getUsername(),loginUser.getPassword());return user;}
}
5.测试UserDaoImpl
import com.kk.web.dao.UserDao;
import com.kk.web.dao.UserDaoImpl;
import com.kk.web.domain.User;
import org.junit.Test;/*** @author : k* @Date : 2022/8/1* @Desc :*/
public class test {@Testpublic void test1() {UserDao userDao = new UserDaoImpl();User loginUser = new User();loginUser.setUsername("admin");loginUser.setPassword("123456");User user = userDao.login(loginUser);System.out.println(user);}
}
6.编写LoginSerlvet类继承HttpServlet
package com.kk.web.servlet;import com.kk.web.dao.UserDao;
import com.kk.web.dao.UserDaoImpl;
import com.kk.web.domain.User;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;/*** @author : k* @Date : 2022/8/1* @Desc :*/
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置编码req.setCharacterEncoding("utf-8");//获取请求参数String username = req.getParameter("username");String password = req.getParameter("password");//封装User对象User loginUser = new User();loginUser.setUsername(username);loginUser.setPassword(password);//调用UserDao的login方法UserDao userDao = new UserDaoImpl();User user = userDao.login(loginUser);//判断userif (user == null) {req.getRequestDispatcher("/failServlet").forward(req, resp);} else {req.setAttribute("user", user);req.getRequestDispatcher("/successServlet").forward(req, resp);};}
}
package com.kk.web.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc :*/@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置编码resp.setContentType("text/html;charset=utf-8");//输出resp.getWriter().write("登录失败,用户名或密码错误");}
}
package com.kk.web.servlet;import com.kk.web.domain.User;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/1* @Desc :*/@WebServlet("/successServlet")
public class SuccessServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取req域中共享数据User user = (User) req.getAttribute("user");if (user != null) {//设置编码resp.setContentType("text/html;charset=utf-8");//输出resp.getWriter().write("登录成功" + user.getUsername() + ",欢迎您");}}
}
7.login.html中的form表单的action路径写法
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Login</title>
</head>
<body><form action="/loginServlet" method="post">用户名:<input type="text" name="username"> <br>密码:<input type="password" name="password"> <br><input type="submit" value="登录"></form></body>
</html>
9.BeanUtils工具类,简化数据封装
导包
<dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.4</version>
</dependency>
代碼演示
package com.kk.web.servlet;import com.kk.web.dao.UserDao;
import com.kk.web.dao.UserDaoImpl;
import com.kk.web.domain.User;
import org.apache.commons.beanutils.BeanUtils;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Objects;/*** @author : k* @Date : 2022/8/1* @Desc :*/
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置编码req.setCharacterEncoding("utf-8");// //获取请求参数
// String username = req.getParameter("username");
// String password = req.getParameter("password");
//
// //封装User对象
// User loginUser = new User();
// loginUser.setUsername(username);
// loginUser.setPassword(password);//获取所有请求参数Map<String, String[]> map = req.getParameterMap();//创建User对象User loginUser = new User();//使用BeanUtils封装try {BeanUtils.populate(loginUser, map);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}//调用UserDao的login方法UserDao userDao = new UserDaoImpl();User user = userDao.login(loginUser);//判断userif (user == null) {req.getRequestDispatcher("/failServlet").forward(req, resp);} else {req.setAttribute("user", user);req.getRequestDispatcher("/successServlet").forward(req, resp);};}
}
BeanUtils工具类,简化数据封装
用于封装JavaBean
1.JavaBean:标准的Java类
1.要求:
1.类必须被public修饰
2.必须提供空参的构造器
3.成员变量必须使用private修饰
4.提供公共setter和getter方法
2.功能:封装数据
2.概念:
成员变量:
属性:setter和getter方法截取后的产物
3.方法:
1.setProperty()
2.getProperty()
3.populate(Object obj,Map map):将map集合的键值信息封装到对应的JavaBean对象中
代码演示
import com.kk.web.dao.UserDao;
import com.kk.web.dao.UserDaoImpl;
import com.kk.web.domain.User;
import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;
import org.springframework.context.annotation.Bean;import java.lang.reflect.InvocationTargetException;/*** @author : k* @Date : 2022/8/1* @Desc :*/
public class TestDome {@Testpublic void test() {User user = new User();try {BeanUtils.setProperty(user, "username","zhangsan");System.out.println(user);String username = BeanUtils.getProperty(user, "username");System.out.println(username);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}}
Response
1.功能
設置响应消息
1.设置响应行
1.格式:HTTP/1.1 200 ok
20设置响应码:setStatus(int sc);
2.设置响应头
setHeader(String name,String value)
3.设置响应体
使用步骤:
1.获取输出流
1.字符输出流:PrintWrite getWriter()
2.字节输出流:ServletOutputStream getOutputStream()
2.使用输出流,将数据输出到客户端浏览器或控制台
2.重定向
|> 重定向:资源跳转的方式
|> 代码实现:
//访问 /responseDemo01 会自动跳转到 /responseDemo02 资源
设置状态码为302
resp.setStatus(302);
//设置响应头
resp.setHeader(“location”,“/responseDemo02”);
//简单的重定向方法
resp.sendRedirect(“/responseDemo02”);
|> 转发的特点:forward
1.转发地址栏路径不变
2.转发只能访问当前服务器下的资源
3.转发只能一次请求,可以使用request对象来共享数据
|> 重定向的特点:redirect
1.地址栏发生变化
2.重定向可以访问其他站点(服务器)的资源
3.重定向是两次请求,不能使用response对象来共享数据
|> 路径写法:
1.路径分类
1.相对路径:通过相对路径不可以确定唯一资源
如:./index.html
不以 / 开头, 以 . 开头路径
规则:找到访问当前资源和目标资源之间的相对位置关系
./:代表当前目录
…/:代表后退一级目录
2.绝对路径:通过绝对路径确定唯一资源
如:http://localhost:8080/responseDemo01 /responseDemo01
以 / 开头的路径
规则:判断定义的路径是给誰用的?判断请求将来从哪发出
给客户端浏览器用的:需要虚拟目录(项目的访问路径)如:重定向
建议虚拟目录动态获取:req.getContextPath();
、 、重定向
给服务器使用:不需要加虚拟目录。如:转发
代码演示
package com.kk.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/2* @Desc : 重定向*/
@WebServlet("/responseDemo01")
public class Demo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("Demo01...");//动态获取虚拟目录String contextPath = req.getContextPath();//访问 /responseDemo01 会自动跳转到 /responseDemo02 资源//设置状态码为302//resp.setStatus(302);//设置响应头//resp.setHeader("location","/responseDemo02");//简单的重定向方法resp.sendRedirect(contextPath+"/responseDemo02");//resp.sendRedirect("https://www.baidu.com");}
}
package com.kk.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/2* @Desc : 重定向*/
@WebServlet("/responseDemo02")
public class Demo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("Demo02...");}
}
3.服务器输出字符数据到浏览器
步骤:
1.获取字符输出流
2.输出数据
注意:
乱码问题
1.PrintWriter pw = resp.getWriter();获取的流的默认编码是IOS-8859-1
2.设置该流的默认编码
3.告诉浏览器响应体的编码
注意是需要在获取流之前设置:
resp.setContentType(“text/html;charset=utf-8”);
代码演示
package com.kk.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @author : k* @Date : 2022/8/2* @Desc : */
@WebServlet("/responseDemo04")
public class Demo04 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取流对象之前,设置流的默认编码(IOS-8859-1),将其设置为GBK//resp.setCharacterEncoding("utf-8");//告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码//resp.setHeader("content-type","text/html;charset=utf-8");//简单的形式设置编码resp.setContentType("text/html;charset=utf-8");//获取字符输出流PrintWriter pw = resp.getWriter();//输出数据pw.write("hello responseDemo04 ");pw.write("<h1>hello responseDemo04</h1>");pw.write("<h1>你好 responseDemo04</h1>");}
}
4.服务器输出字节数据到浏览器
代码演示
package com.kk.servlet;import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @author : k* @Date : 2022/8/2* @Desc : 服务器输出字节数据到浏览器*/
@WebServlet("/responseDemo05")
public class Demo05 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//简单的形式设置编码resp.setContentType("text/html;charset=utf-8");//获取字节输出流ServletOutputStream sos = resp.getOutputStream();//输出数据sos.write("hello".getBytes());sos.write("你好".getBytes("utf-8"));}
}
5.验证码
1.本质:图片
2.目的:防止恶意表单注册
代码演示
package com.kk.servlet;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;/*** @author : k* @Date : 2022/8/2* @Desc : 验证码*/
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int width = 100;int height = 50;//创建一对象,在内存中图片(验证码图片对象)BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//美化图片//填充背景色Graphics g = image.getGraphics(); //画笔对象g.setColor(Color.PINK); //设置画笔颜色g.fillRect(0, 0, width, height);//画边框g.setColor(Color.BLUE);g.drawRect(0, 0, width - 1, height - 1);String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvuvwxyz0123456789";//生产随机角标Random ran = new Random();for (int i = 1; i <= 4; i++){int index = ran.nextInt(str.length());//获取字符char ch = str.charAt(index); //随机字符//写验证码g.drawString(ch+"", width/5*i, height/2);}//画干扰线g.setColor(Color.GREEN);//随机生成坐标点for (int i = 0; i < 10; i++) {int x1 = ran.nextInt(width);int x2 = ran.nextInt(width);int y1 = ran.nextInt(width);int y2 = ran.nextInt(width);g.drawLine(x1,y1,x2,y2);}//将图片输出到页面展示ImageIO.write(image, "jpg", resp.getOutputStream());}
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script>/*分析:点击超链接或者图片,需要换一张1.给超链接和图片绑定单击事件2.重新设置图片的src属性值*/window.onload = function (){//获取图片var img = document.getElementById("checkCode")//绑定单击事件img.onclick = function () {//加时间戳var date = new Date().getTime();img.src = "/checkCodeServlet?"+date;}//获取a标签var a = document.getElementById("change")a.onclick = function (){//加时间戳var date = new Date().getTime();img.src = "/checkCodeServlet?"+date;}}</script></head>
<body><img id="checkCode" src="/checkCodeServlet" ><a id="change" href="javascript:;">看不清,换一张</a>
</body>
</html>
ServletContext
1.概念
|> 代表整個web應用,可以和程序的容器(服務器)來通信
2.获取
1.通過request對象獲取
|> request.getServletContext();
2.通過HttpServlet獲取
|> this.getServletContext();
代碼演示
package com.kk.servletcontext;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc :*/
@WebServlet("/servletContextDemo01")
public class Demo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletContext對象獲取ServletContext context1 = req.getServletContext();ServletContext context2 = this.getServletContext();System.out.println(context1==context2);//trueSystem.out.println(context1);System.out.println(context2);}
}
3.功能
1.獲取MIME類型
MIME類型:在互聯網通信過程中定義的一種文件數據類型
格式:大類型/小類型 text/html image/jpeg
獲取:String getMimeType(String file)
代碼演示
package com.kk.servletcontext;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : 獲取MIME類型*/
@WebServlet("/servletContextDemo02")
public class Demo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletContext功能ServletContext context = this.getServletContext();//定義文件名稱String fileName = "a.jpg";//獲取MIME類型String mimeType = context.getMimeType(fileName);System.out.println(mimeType);}
}
2.域對象:共享數據
1.setAttribute(String name,Object value)
2.getAttribute(String name)
3.removeAttribute(String name)
該ServletContext对象范围:所有用戶請求的數據
代码演示
package com.kk.servletcontext;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : 域對象:共享數據*/
@WebServlet("/servletContextDemo03")
public class Demo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletContext功能ServletContext context = this.getServletContext();//設置數據context.setAttribute("message","hello");}
}
package com.kk.servletcontext;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : 域對象:共享數據*/
@WebServlet("/servletContextDemo04")
public class Demo04 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletContext功能ServletContext context = this.getServletContext();//獲取數據Object message = context.getAttribute("message");System.out.println(message);}
}
3.獲取文件的真實(服務器)路徑
方法:String getRealPath(“”)
代码演示
package com.kk.servletcontext;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : 獲取文件的真實(服務器)路徑*/
@WebServlet("/servletContextDemo05")
public class Demo05 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletContext功能ServletContext context = this.getServletContext();//獲取文件的真實(服務器)路徑String realPath = context.getRealPath("/pro.properties");System.out.println(realPath);File file = new File(realPath);String pro = context.getRealPath("/WEB-INF/classes/pro.properties"); //src目錄下的資源(resources)下的路徑System.out.println(pro);}
}
4.文件下载
文件下载需求
1.页面显示超链接
2.点击超链接后弹出下载提示框
3.完成图片文件下载
分析
1.超链接指向的资源如果能被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
2.任何资源都必须弹出下载提示框
3.使用响应头设置资源的打开方式:
content-disposition:attachment;filename=xxx
步骤
1.定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
2.定义Servlet
1.获取文件得名称
2.使用字节输入流加载文件进内存
3.指定response的响应头:content-disposition:attachment;filename=xxx
4.将数据写出到response输出流
代碼演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><a href="/downLoadServlet?filename=011.jpeg">图片</a></body>
</html>
package com.kk.download;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc :*/
@WebServlet("/downLoadServlet")
public class downLoadServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求参数,即文件名称String filename = req.getParameter("filename");//使用字节输出流加载文件进内存//找到文件服务器路径ServletContext context = this.getServletContext();String realPath = context.getRealPath("/img/" + filename);//用字节流关联FileInputStream fis = new FileInputStream(realPath);//设置response的响应头//设置响应头类型 content-typeString mimeType = context.getMimeType(filename); //获取文件的mime类型resp.setHeader("content-type", mimeType);//设置响应头打开方式 content-dispositionresp.setHeader("content-disposition", "attachment;filename=" + filename);//将输入流的数据写出响应输出流中ServletOutputStream sos = resp.getOutputStream();byte[] buff = new byte[1024 * 8];int len = 0;while ((len = fis.read(buff)) != -1) {sos.write(buff, 0, len);}fis.close();}
}
問題
中文文件問題
解決思路:
1.獲取客戶端使用的瀏覽器版本信息
2.根據不用的版本信息,設置filename的編碼方式不同
代碼演示
package com.kk.download;import com.kk.utils.DownLoadUtils;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc :*/
@WebServlet("/downLoadServlet")
public class downLoadServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求参数,即文件名称String filename = req.getParameter("filename");//使用字节输出流加载文件进内存//找到文件服务器路径ServletContext context = this.getServletContext();String realPath = context.getRealPath("/img/" + filename);//用字节流关联FileInputStream fis = new FileInputStream(realPath);//设置response的响应头//设置响应头类型 content-typeString mimeType = context.getMimeType(filename); //获取文件的mime类型resp.setHeader("content-type", mimeType);//解決中文文件名問題//獲取user-agent請求頭String agent = req.getHeader("user-agent");//使用工具類方法編碼文件名即可filename = DownLoadUtils.getFileName(agent, filename);//设置响应头打开方式 content-dispositionresp.setHeader("content-disposition","attachment;filename="+filename);//将输入流的数据写出响应输出流中ServletOutputStream sos = resp.getOutputStream();byte[] buff = new byte[1024 * 8];int len = 0;while ((len = fis.read(buff)) != -1) {sos.write(buff, 0, len);}fis.close();}
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><a href="/downLoadServlet?filename=011.jpeg">图片</a><hr><a href="/downLoadServlet?filename=风景.jpeg">图片</a></body>
</html>
会话技术
1.会话技术
- 会话:一次会话中包含多次请求和响应。
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
- 功能:在一次会话的范围内的多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
2.Cookie
1.概念
客户端会话技术,将数据保存到客户端
2.快速入门
- 使用步骤:
- 创建Cookie对象,绑定数据
- new Cookie(String name, String value)
- 发送Cookie对象
- response.addCookie(Cookie cookie)
- 获取Cookie,拿到数据
- Cookie[] request.getCookies()
- 创建Cookie对象,绑定数据
代碼演示
package com.kk.cookie;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : Cookie快速入門*/@WebServlet("/cookieDemo01")
public class CookieDemo01 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//創建Cookie對象Cookie cookie = new Cookie("msg", "hello");//發送Cookieresp.addCookie(cookie);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
package com.kk.cookie;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : Cookie快速入門*/@WebServlet("/cookieDemo02")
public class CookieDemo02 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//獲取CookieCookie[] cs = req.getCookies();//獲取數據,遍歷Cookiesif (cs != null) {for (Cookie c : cs) {String name = c.getName();String value = c.getValue();System.out.println(name + ":" + value);}}}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
3.实现原理
- 基于响应头set-cookie和请求头cookie实现
4.cookie的细节
一次可不可以发送多个cookie?
可以
- 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
package com.kk.cookie;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : 一次可不可以发送多个cookie?*/@WebServlet("/cookieDemo03") public class CookieDemo03 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//創建Cookie對象Cookie c1 = new Cookie("msg", "hello");Cookie c2 = new Cookie("name", "zhangsan");//發送Cookieresp.addCookie(c1);resp.addCookie(c2);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);} }
cookie在浏览器中保存多长时间?
默认情况下,当浏览器关闭后,Cookie数据被销毁
持久化存储:
* setMaxAge(int seconds)1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效2. 负数:默认值3. 零:删除cookie信息
package com.kk.cookie;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : cookie在浏览器中保存多长时间?*/@WebServlet("/cookieDemo04")
public class CookieDemo04 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//創建Cookie對象Cookie c1 = new Cookie("msg", "setMaxAge");//設置將cookie的存活時間c1.setMaxAge(30); //將cookie持久化到硬盤,30秒后會自動刪除cookies//c1.setMaxAge(-1); //默认值//c1.setMaxAge(0); //删除cookie信息//發送Cookieresp.addCookie(c1);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
- cookie能不能存中文?
- 在tomcat 8 之前 cookie中不能直接存储中文数据。
- 需要将中文数据转码—一般采用URL编码(%E3)
在tomcat 8 之后,cookie支持中文数据
。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
cookie共享问题?
- 假设在
同一个tomcat服务器中
,部署了多个web项目,那么在这些web项目中cookie能不能共享?
默认情况下cookie不能共享
setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
- 如果要共享,则可以将path设置为"/"
不同的tomcat服务器
间cookie共享问题?
- setDomain(String path):如果设置
一级域名相同
,那么多个服务器之间cookie可以共享- setDomain(“.baidu.com”),那么
tieba.baidu.com
和news.baidu.com中cookie
可以共享
- setDomain(“.baidu.com”),那么
package com.kk.cookie;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : cookie能不能存中文?*/@WebServlet("/cookieDemo05") public class CookieDemo05 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//創建Cookie對象Cookie c1 = new Cookie("msg", "你好");c1.setPath("/");//發送Cookieresp.addCookie(c1);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);} }
- 假设在
5.Cookie的特点和作用
- cookie
存储数据在客户端浏览器
- 浏览器
对于单个cookie 的大小有限制(4kb)
以及对同一个域名下的总cookie数量也有限制(20个)
- 作用:
- cookie
一般用于存出少量的不太敏感的数据
在不登录的情况下,完成服务器对客户端的身份识别
- cookie
6.案例:记住上一次访问时间
需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
分析:
- 可以采用Cookie来完成
- 在服务器中的Servlet判断是否有一个名为lastTime的cookie
- 有:不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:2018年6月10日11:50:20
- 写回Cookie:lastTime=2018年6月10日11:50:01
- 没有:是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie:lastTime=2018年6月10日11:50:01
- 有:不是第一次访问
代碼演示
package com.kk.cookie;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @author : k* @Date : 2022/8/3* @Desc :* 需求:* <p>* 1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。* 2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串*/
@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置响应的消息体的数据格式以及编码resp.setContentType("text/html;charset=utf-8");//獲取所有的cookieCookie[] cookies = req.getCookies();boolean flag = false; //沒有cookie為lastTime//遍歷cookies數組if (cookies != null && cookies.length > 0) {for (Cookie cookie : cookies) {//獲取cookies的名稱String name = cookie.getName();//判斷名稱是否是lastTimeif ("lastTime".equals(name)) {//有該cookie不是第一次訪問flag = true; //有lastTime的cookie//设置cookie的 value//获取当前时间的字符串,重新设置cookie的值,并且重新发送cookieDate date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");String str_date = sdf.format(date);System.out.println("編碼前的数据" + str_date);//URL编码str_date = URLEncoder.encode(str_date, "utf-8");System.out.println("編碼后的数据" + str_date);cookie.setValue(str_date);//設置cookie的存活時間cookie.setMaxAge(60 * 60 * 24 * 30); //一個月resp.addCookie(cookie);//响应数据//获取cookie的value 时间String value = cookie.getValue();System.out.println("解码前:" + value);//URL解码value = URLDecoder.decode(value, "utf-8");System.out.println("解码后:" + value);resp.getWriter().write("<h1>欢迎回来,您上次访问时间为:" + value + "</h1>");break;}}}if (cookies == null || cookies.length == 0 || flag == false) {//沒有 第一次訪問//设置cookie的 value//获取当前时间的字符串,重新设置cookie的值,并且重新发送cookieDate date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");String str_date = sdf.format(date);System.out.println("編碼前的数据" + str_date);//URL编码str_date = URLEncoder.encode(str_date, "utf-8");System.out.println("編碼后的数据" + str_date);Cookie cookie = new Cookie("lastTime", str_date);cookie.setValue(str_date);//設置cookie的存活時間cookie.setMaxAge(60 * 60 * 24 * 30); //一個月resp.addCookie(cookie);resp.getWriter().write("<h1>您好,欢迎您首次访问</h1>");}}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
3.Session
1.概念
服务器端会话技术
,在一次会话的多次请求间共享数据
,将数据保存在服务器端的对象中。HttpSession
2.快速入门
- 获取HttpSession对象:
HttpSession session = request.getSession(); - 使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
代码演示
package com.kk.session;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/*** @author : k* @Date : 2022/8/3* @Desc :*/
@WebServlet("/sessionDemo01")
public class SessionDemo01 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//使用session共享数据//获取sessionHttpSession session = req.getSession();session.setAttribute("msg","hello session");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
package com.kk.session;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc :*/
@WebServlet("/sessionDemo02")
public class SessionDemo02 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//使用session共享数据//获取sessionHttpSession session = req.getSession();Object msg = session.getAttribute("msg");System.out.println(msg);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
3.原理
- Session的实现是依赖于Cookie的。
4.细节
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
- 默认情况下。不是。
- 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
Cookie c = new Cookie(“JSESSIONID”,session.getId());
c.setMaxAge(60*60);
response.addCookie©;
package com.kk.session;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?*/ @WebServlet("/sessionDemo03") public class SessionDemo03 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取sessionHttpSession session = req.getSession();//期望客户端关闭后,session也能相同Cookie cookie = new Cookie("JSESSIONID",session.getId());cookie.setMaxAge(60*60);resp.addCookie(cookie);System.out.println(session);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);} }
客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
- 不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
- session的钝化:
* 在服务器正常关闭之前,将session对象系列化到硬盘上 - session的活化:
* 在服务器启动后,将session文件转化为内存中的session对象即可。
- session的钝化:
package com.kk.session;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;/*** @author : k* @Date : 2022/8/3* @Desc : 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?*/
@WebServlet("/sessionDemo04")
public class SessionDemo04 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取sessionHttpSession session = req.getSession();System.out.println(session);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
- session什么时候被销毁?
- 服务器关闭
- session对象调用invalidate() 。
- session默认失效时间 30分钟
选择性配置修改
<session-config><session-timeout>30</session-timeout></session-config>
5.session的特点
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据
- session与Cookie的区别:
session存储数据在服务器端,Cookie在客户端
session没有数据大小限制,Cookie有
session数据安全,Cookie相对于不安全
6.案例:验证码
案例需求:
- 访问带有验证码的登录页面login.jsp
- 用户输入用户名,密码以及验证码。
- 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登录页面,提示:验证码错误
- 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
分析:
代码演示
生成二维码
package com.kk.servlet;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int width = 100;int height = 50;//1.创建一对象,在内存中图片(验证码图片对象)BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//2.美化图片//2.1 填充背景色Graphics g = image.getGraphics();//画笔对象g.setColor(Color.PINK);//设置画笔颜色g.fillRect(0,0,width,height);//2.2画边框g.setColor(Color.BLUE);g.drawRect(0,0,width - 1,height - 1);String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";//生成随机角标Random ran = new Random();StringBuffer sb = new StringBuffer();for (int i = 1; i <= 4; i++) {int index = ran.nextInt(str.length());//获取字符char ch = str.charAt(index);//随机字符sb.append(ch);//2.3写验证码g.drawString(ch+"",width/5*i,height/2);}String checkCode_session = sb.toString();//将验证码存入sessionrequest.getSession().setAttribute("checkCode_session",checkCode_session);//2.4画干扰线g.setColor(Color.GREEN);//随机生成坐标点for (int i = 0; i < 10; i++) {int x1 = ran.nextInt(width);int x2 = ran.nextInt(width);int y1 = ran.nextInt(height);int y2 = ran.nextInt(height);g.drawLine(x1,y1,x2,y2);}//3.将图片输出到页面展示ImageIO.write(image,"jpg",response.getOutputStream());}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request,response);}
}
登录LoginServlet
package com.kk.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Map;/*** @author : k* @Date : 2022/8/4* @Desc :*/
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置req编码req.setCharacterEncoding("utf-8");//获取参数String username = req.getParameter("username");String password = req.getParameter("password");String checkCode = req.getParameter("checkCode");//先获取生成的验证码HttpSession session = req.getSession();String checkCode_session = (String) session.getAttribute("checkCode_session");//删除session中存储的验证码session.removeAttribute("checkCode_session");//先判断验证码是否正确if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)) {//验证码忽略大小写比较字符串//判断用户名和密码是否一致if ("admin".equals(username) && "123".equals(password)) {//需要调用UserDao查询数据库,这里省略//登录成功//存储用户信息session.setAttribute("username", username);//重定向到success.jspresp.sendRedirect(req.getContextPath() + "/success.jsp");} else {//登录失败//存储提示信息到reqreq.setAttribute("login_error", "用户名或密码错误");//转发到登录页面req.getRequestDispatcher("/login.jsp").forward(req, resp);}} else {//验证码不一致//存储提示信息到reqreq.setAttribute("cc_error", "验证码错误");//转发到登录页面req.getRequestDispatcher("/login.jsp").forward(req, resp);}}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}
}
jsp页面
<%--Created by IntelliJ IDEA.User: 30666Date: 2022/8/4Time: 15:41To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>login</title><script>window.onload = function () {document.getElementById("img").onclick = function () {this.src = "${pageContext.request.contextPath}/checkCodeServlet?time=" + new Date().getTime();}}</script><style>div {color: red;}</style></head>
<body><form action="${pageContext.request.contextPath}/loginServlet" method="post"><table><tr><td>用户名</td><td><input type="text" name="username"></td></tr><tr><td>密码</td><td><input type="password" name="password"></td></tr><tr><td>验证码</td><td><input type="text" name="checkCode"></td></tr><tr><td colspan="2"><img id="img" src="${pageContext.request.contextPath}/checkCodeServlet"></td></tr><tr><td colspan="2"><input type="submit" value="登录"></td></tr></table>
</form><div><%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%>
</div>
<div><%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error") == null%>
</div></body>
</html>
<%--Created by IntelliJ IDEA.User: 30666Date: 2022/8/4Time: 16:01To 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><%=request.getSession().getAttribute("username")%>,欢迎您</h1></body>
</html>
JSP入门学习
1.概念
Java Server Pages: java服务器端页面
可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
用于简化书写!!!
代码演示
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>$Title$</title></head><body><%System.out.println("hello jsp");%><h1>hi jsp</h1></body>
</html>
2.原理
JSP本质上就是一个Servlet
3.JSP的脚本
JSP定义Java代码的方式
- <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
- <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。
- <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
代码演示
<%--Created by IntelliJ IDEA.User: 30666Date: 2022/8/3Time: 17:36To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>$Title$</title>
</head>
<body><%System.out.println("hello jsp");%><%!int i = 3;%><%=i%><h1>hi jsp</h1>
</body>
</html>
4.JSP的内置对象
- 在jsp页面中不需要获取和创建,可以直接使用的对象
- jsp一共有9个内置对象。
- 今天学习3个:
- request
- response
- out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
- response.getWriter()和out.print()的区别:
- 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
- response.getWriter()数据输出永远在out.print()之前
- response.getWriter()和out.print()的区别:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HVGDfcWA-1659791971308)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220803234523243.png)]
5.案例:改造Cookie案例
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.net.URLEncoder" %>
<%@ page import="java.net.URLDecoder" %><%--Created by IntelliJ IDEA.User: 30666Date: 2022/8/3Time: 23:46To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>showTime</title>
</head>
<body><%//獲取所有的cookieCookie[] cookies = request.getCookies();boolean flag = false; //沒有cookie為lastTime//遍歷cookies數組if (cookies != null && cookies.length > 0) {for (Cookie cookie : cookies) {//獲取cookies的名稱String name = cookie.getName();//判斷名稱是否是lastTimeif ("lastTime".equals(name)) {//有該cookie不是第一次訪問flag = true; //有lastTime的cookie//设置cookie的 value//获取当前时间的字符串,重新设置cookie的值,并且重新发送cookieDate date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");String str_date = sdf.format(date);System.out.println("編碼前的数据" + str_date);//URL编码str_date = URLEncoder.encode(str_date, "utf-8");System.out.println("編碼后的数据" + str_date);cookie.setValue(str_date);//設置cookie的存活時間cookie.setMaxAge(60 * 60 * 24 * 30); //一個月response.addCookie(cookie);//响应数据//获取cookie的value 时间String value = cookie.getValue();System.out.println("解码前:" + value);//URL解码value = URLDecoder.decode(value, "utf-8");System.out.println("解码后:" + value);response.getWriter().write("<h1>欢迎回来,您上次访问时间为:" + value + "</h1>");break;}}}if (cookies == null || cookies.length == 0 || flag == false) {//沒有 第一次訪問//设置cookie的 value//获取当前时间的字符串,重新设置cookie的值,并且重新发送cookieDate date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");String str_date = sdf.format(date);System.out.println("編碼前的数据" + str_date);//URL编码str_date = URLEncoder.encode(str_date, "utf-8");System.out.println("編碼后的数据" + str_date);Cookie cookie = new Cookie("lastTime", str_date);cookie.setValue(str_date);//設置cookie的存活時間cookie.setMaxAge(60 * 60 * 24 * 30); //一個月response.addCookie(cookie);response.getWriter().write("<h1>您好,欢迎您首次访问</h1>");}%></body>
</html>
JSP进阶
1.指令
作用:用于配置JSP页面,导入资源文件
格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %>分类:
page:配置JSP页面的
- contentType:等同于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
- import:导包
- errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
- isErrorPage:标识当前也是是否是错误页面。
- true:是,可以使用内置对象exception
- false:否。默认值。不可以使用内置对象exception
代碼演示
<%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" errorPage="500.jsp" language="java" %> <html> <head><title>$Title$</title> </head> <body><%List<String> strings = new ArrayList<>();int i = 3/0;%> </body> </html>
<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" language="java" %> <html> <head><title>Title</title> </head> <body><h1>服務器繁忙...</h1><%String message = exception.getMessage();response.getWriter().write(message);%> </body> </html>
- contentType:等同于response.setContentType()
include:页面包含的。导入页面的资源文件
* <%@include file="top.jsp"%>> 代码演示``top.jsp`````java <%@ page contentType="text/html;charset=UTF-8" language="java" %> <h1>頁面logo 頁面標題</h1> `````home.jsp`````jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@include file="top.jsp"%> <html> <head><title>Title</title> </head> <body><h3>主题信息</h3></body> </html> ```
- taglib:导入资源
* <%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>- prefix:前缀,自定义的
2.注释
- html注释:
<! – – >:只能注释html代码片段 - jsp注释:推荐使用
<%-- --%>:可以注释所有
3.内置对象
在jsp页面中不需要创建,直接使用的对象
一共有9个:
变量名
真实类型
作用
- pageContext PageContext 当前页面共享数据,还可以获取其他八个内置对象
- request HttpServletRequest 一次请求访问的多个资源(转发)
- session HttpSession 一次会话的多个请求间
- application ServletContext 所有用户间共享数据
- response HttpServletResponse 响应对象
- page Object 当前页面(Servlet)的对象 this
- out JspWriter 输出对象,数据输出到页面上
- config ServletConfig Servlet的配置对象
- exception Throwable 异常对象
MVC:开发模式
1.jsp演变历史
- 早期只有servlet,只能使用response输出标签数据,非常麻烦
- 后来又jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表,造成难于维护,难于分工协作
- 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性
2.MVC:
M:Model,模型。JavaBean
- 完成具体的业务操作,如:查询数据库,封装对象
V:View,视图。JSP
- 展示数据
C:Controller,控制器。Servlet
获取用户的输入
调用模型
将数据交给视图进行展示
优缺点:
优点:
- 耦合性低,方便维护,可以利于分工协作
- 重用性高
缺点:
- 使得项目架构变得复杂,对开发人员要求高
EL表达式
1.概念
Expression Language 表达式语言
2.作用
替换和简化jsp页面中java代码的编写
3.语法
${表达式}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>${3>4}</body>
</html>
4.注意
- jsp默认支持el表达式的。如果要忽略el表达式
设置jsp中page指令中:isELIgnored=“true” 忽略当前jsp页面中所有的el表达式
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="true" %> <html> <head><title>Title</title> </head> <body>${3>4}</body> </html>
${表达式} :忽略当前这个el表达式
<%@ page contentType="text/html;charset=UTF-8" language="java"%> <html> <head><title>Title</title> </head> <body>${3>4}\${3>4}</body> </html>
5.使用
1.运算
- 运算符:
- 算数运算符: + - * /(div) %(mod)
- 比较运算符: > < >= <= == !=
- 逻辑运算符: &&(and) ||(or) !(not)
- 空运算符: empty
* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
* ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
* ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>${3>2}\${3>2}<hr><h3>算术运算符</h3>
${3+3} <br>
${3/3} <br>
${3 div 3} <br>
${3 % 3} <br>
${3 mod 3} <br><hr>
<h3>比较运算符</h3>
${3==3}<br><hr>
<h3>逻辑运算符</h3>
${3==3 && 3>2}<br>
${3==3 and 3>2}<br><hr>
<h3>empty运算符</h3>
<%String str = "abc";request.setAttribute("str",str);
%>
${empty str}<br>
${not empty str}<br>
</body>
</html>
2.获取值
el表达式只能从域对象中获取值
语法:
${域名称.键名}:从指定域中获取指定键的值
* 域名称:1. pageScope --> pageContext2. requestScope --> request3. sessionScope --> session4. applicationScope --> application(ServletContext)
* 举例:在request域中存储了name=张三
* 获取:${requestScope.name}```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>获取域中的数据</title>
</head>
<body><%//在域中存储数据request.setAttribute("name","zhangsan");session.setAttribute("age","22");
%><h3>el获取域中的数据</h3>
${requestScope.name}
${sessionScope.age}</body>
</html>
```
${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>获取域中的数据</title> </head> <body><%//在域中存储数据request.setAttribute("name","zhangsan");session.setAttribute("age","22");session.setAttribute("name","lisi"); %><h3>el获取域中的数据</h3>${requestScope.name} ${sessionScope.age}<hr> ${name} ${sessionScope.name}</body> </html>
获取对象、List集合、Map集合的值
- 对象:${域名称.键名.属性名}
* 本质上会去调用对象的getter方法``User`````javapackage com.kk.domain;import java.text.SimpleDateFormat;import java.util.Date;/*** @author : k* @Date : 2022/8/4* @Desc : JavaBean*/public class User {private String name;private Integer age;private Date birthday;
public String getBirStr() {
if (birthday != null) {
//格式化日期对象
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
//返回
return sdf.format(birthday);
} else {
return “”;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}}`````jsp`````jsp<%@ page import="com.kk.domain.User" %><%@ page import="java.util.Date" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>el获取對象中的数据</title></head><body>
<%
User user = new User();
user.setName(“张三”);
user.setAge(22);
user.setBirthday(new Date());
request.setAttribute(“user”,user);
%>
el获取对象中的值
${requestScope.user}
<%–通过对象的属性来获取数据
setter或getter方法,去掉set或get,再将剩余部门,首字母变为小写
setName —> Name —> name
--%>
${requestScope.user.name}
${requestScope.user.age}
${requestScope.user.birthday}
${requestScope.user.birthday.month+1}
${requestScope.user.birStr}
```
2. List集合:${域名称.键名[索引]}```jsp<%@ page import="com.kk.domain.User" %><%@ page import="java.util.Date" %><%@ page import="java.util.ArrayList" %><%@ page import="java.util.List" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>el获取List集合中的数据</title></head><body>
<%
User user = new User();
user.setName(“张三”);
user.setAge(22);
user.setBirthday(new Date());
List list = new ArrayList<>();
list.add(“aaa”);
list.add(“bbb”);
list.add(user);
request.setAttribute(“list”,list);
%>
<h3>el获取List集合中的数据</h3>${requestScope.list} <br>${requestScope.list[0]} <br>${requestScope.list[1]} <br>${requestScope.list[10]} <br>
${requestScope.list[2].name}
${requestScope.list[2].age}
${requestScope.list[2].birthday}
```
3. Map集合:
* ${域名称.键名.key名称}
* ${域名称.键名[“key名称”]}
<%@ page import="com.kk.domain.User" %>
<%@ page import="java.util.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>el获取Map集合中的数据</title>
</head>
<body><%User user = new User();user.setName("张三");user.setAge(22);user.setBirthday(new Date());Map<Object, Object> map = new HashMap<>();map.put("username","李四");map.put("password","123456");map.put("user",user);request.setAttribute("map",map);
%><h3>el获取Map集合中的数据</h3>
${requestScope.map} <br>
${requestScope.map.username} <br>
${requestScope.map["username"]} <br>
${requestScope.map.password} <br>
${requestScope.map["password"]} <br>${requestScope.map.user.name} <br>
${requestScope.map.user.age} <br>
${requestScope.map.user.birthday} <br></body>
</html>
3.隐式对象
- el表达式中有11个隐式对象
- pageContext:
- 获取jsp其他八个内置对象
* ${pageContext.request.contextPath}:动态获取虚拟目录
- 获取jsp其他八个内置对象
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>el的隐式对象</title>
</head>
<body>${pageContext.request} <br>
<h4>在jsp中动态获取虚拟目录</h4>
${pageContext.request.contextPath} <br></body>
</html>
JSTL
1.概念
JavaServer Pages Tag Library JSP标准标签库
- 是由Apache组织提供的开源的免费的jsp标签 <标签>
2.作用
用于简化和替换jsp页面上的java代码
3.使用步骤
导入jstl相关jar包
<dependencies><dependency><groupId>org.glassfish.web</groupId><artifactId>jstl-impl</artifactId><version>1.2</version></dependency> </dependencies>
引入标签库:taglib指令:<%@ taglib %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
使用标签
4.常用的JSTL标签
if:相当于java代码的if语句
属性:
- test 必须属性,接受boolean表达式
- 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
- 一般情况下,test属性值会结合el表达式一起使用
- test 必须属性,接受boolean表达式
注意:
- c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page import="java.util.List" %> <%@ page import="java.util.ArrayList" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %><html> <head><title>if标签</title> </head> <body><%--c:if标签1.属性test必须属性,接收boolean表达式如果表达式为true则显示if标签体内容,如果为false则不显示标签体内容--%><c:if test="true"><h1>你好</h1></c:if><hr><%//判斷request域中的一个list集合是否为空,如果不为空则显示遍历集合List<Object> list = new ArrayList<>();list.add("aaa");request.setAttribute("list",list);request.setAttribute("number",3);%><c:if test="${not empty list}">遍历集合...</c:if><br><c:if test="${number % 2 != 0}">${number}为奇数</c:if></body> </html>
choose:相当于java代码的switch语句
- 使用choose标签声明 相当于switch声明
- 使用when标签做判断 相当于case
- 使用otherwise标签做其他情况的声明 相当于default
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %><html> <head><title>choose标签</title> </head> <body><%--完成数字编号对应星期几案例1.域中存储数字2.使用choose标签取出数字 相当于 switch声明3.使用when标签作数字判断 相当于 case4.otherwise标签作其他情况的声明 相当于 default--%> <%request.setAttribute("number", 3); %><c:choose><c:when test="${number==1}">星期一</c:when><c:when test="${number==2}">星期二</c:when><c:when test="${number==3}">星期三</c:when><c:when test="${number==4}">星期四</c:when><c:when test="${number==5}">星期五</c:when><c:when test="${number==6}">星期六</c:when><c:when test="${number==7}">星期七</c:when><c:otherwise>数字输入有误</c:otherwise></c:choose></body> </html>
foreach:相当于java代码的for语句
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html>
<head><title>foreach标签</title>
</head>
<body>
<%--foreach:相当于java代码的for语句1.完成重复的操作for(int i = 0; i<10; i++){}属性:begin:开始值end:结束值var:临时变量step:步长varStatus:循环状态对象index:容器中元素的索引,从0开始count:循环次数,从1开始2.遍历容器List<User> list;for(User user : list){}属性:items:容器对象 listvar:容器中元素的临时变量 user--%><c:forEach begin="1" end="10" var="i" step="1">${i} <br>
</c:forEach><hr><%List<Object> list = new ArrayList<>();list.add("aaa");list.add("bbb");list.add("ccc");request.setAttribute("list",list);%><c:forEach items="${list}" var="str" varStatus="s">${s.index} ${s.count} ${str} <br>
</c:forEach></body>
</html>
5.练习
- 需求:在request域中有一个存有User对象的List集合。需要使用jstl+el将list集合数据展示到jsp页面的表格table中
User实体类
package com.kk.domain;import java.text.SimpleDateFormat;
import java.util.Date;/*** @author : k* @Date : 2022/8/4* @Desc : JavaBean*/
public class User {private String name;private Integer age;private Date birthday;public String getBirStr() {if (birthday != null) {//格式化日期对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//返回return sdf.format(birthday);} else {return "";}}public User() {}public User(String name, Integer age, Date birthday) {this.name = name;this.age = age;this.birthday = birthday;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}
}
jsp页面
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page import="com.kk.domain.User" %>
<%@ page import="java.util.Date" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>test</title>
</head>
<body><%List<User> list = new ArrayList<>();list.add(new User("张三",22,new Date()));list.add(new User("李四",21,new Date()));list.add(new User("王五",23,new Date()));request.setAttribute("list",list);
%><table border="1" width="500" align="center"><tr><th>编号</th><th>姓名</th><th>年龄</th><th>生日</th></tr><c:forEach items="${list}" var="user" varStatus="s"><c:if test="${s.count % 2 != 0}"><tr bgcolor="#afb1b3"><td>${s.count}</td><td>${user.name}</td><td>${user.age}</td><td>${user.birStr}</td></tr></c:if><c:if test="${s.count % 2 == 0}"><tr><td>${s.count}</td><td>${user.name}</td><td>${user.age}</td><td>${user.birStr}</td></tr></c:if></c:forEach></table></body>
</html>
三层架构:软件设计架构
- 界面层(表示层):用户看的得界面。用户可以通过界面上的组件和服务器进行交互
- 业务逻辑层:处理业务逻辑的。
- 数据访问层:操作数据存储文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L5A6Y4gC-1659791971309)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220804205556359.png)]
案例:用户信息列表展示
1.需求
用户信息的增删改查操作
2.设计
技术选型:Servlet+JSP+MySQL+JDBCTempleat+Duird+BeanUtilS+tomcat
数据库设计:
/*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 80027Source Host : localhost:3306Source Schema : db2Target Server Type : MySQLTarget Server Version : 80027File Encoding : 65001Date: 04/08/2022 21:05:18 */SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`gender` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`age` int NULL DEFAULT NULL,`address` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`qq` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (1, '张三', '男', 22, '广东省', '30666', '30666@qq.com'); INSERT INTO `user` VALUES (2, '李四', '男', 25, '广东省', '3066688', '3066688@qq.com'); INSERT INTO `user` VALUES (3, '王晓', '女', 21, '广东省', '30666', '30666@qq.com');SET FOREIGN_KEY_CHECKS = 1;
3.开发
1.环境搭建
- 创建数据库环境
- 创建项目,导入需要的jar包
<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.4</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.11</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.20</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>compile</scope></dependency><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.4</version></dependency><dependency><groupId>org.glassfish.web</groupId><artifactId>jstl-impl</artifactId><version>1.2</version></dependency></dependencies>
2.编码
1.列表查詢分析
2.添加功能分析
3.刪除功能分析
4.修改功能分析
5.刪除选中功能分析
6.分页查询功能分析
7.复杂条件查询分析
代码地址
…
4.测试
5.部署运维
Filter:过滤器
1.概念
- 生活中的过滤器:净水器,空气净化器,土匪、
- web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
- 过滤器的作用:
- 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…
2.快速入门
- 步骤:
- 定义一个类,实现接口Filter
- 复写方法
- 配置拦截路径
- web.xml
- 注解
- 代码:
package com.kk.web.filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;/*** @author : k* @Date : 2022/8/6* @Desc :快速入门*/
@WebFilter("/*") //访问所有资源之前都会执行该过滤器
public class Demo01 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("Demo01被執行了...");//放行chain.doFilter(request, response);}@Overridepublic void destroy() {Filter.super.destroy();}
}
3.过滤器细节
web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><filter><filter-name>demo01</filter-name><filter-class>com.kk.web.filter.Demo02</filter-class></filter><filter-mapping><filter-name>demo01</filter-name> <!-- 拦截路径--><url-pattern>/*</url-pattern></filter-mapping></web-app>
过滤器执行流程
执行过滤器
执行放行后的资源
回来执行过滤器放行代码下边的代码
过滤器生命周期方法
init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
doFilter:每一次请求被拦截资源时,会执行。执行多次
destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
过滤器配置详解
- 拦截路径配置:
- 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
- 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
- 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
- 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
- 拦截方式配置:资源被访问的方式
- 注解配置:
- 设置dispatcherTypes属性
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
- 设置dispatcherTypes属性
- web.xml配置
- 设置标签即可
- 注解配置:
- 过滤器链(配置多个过滤器)
执行顺序:如果有两个过滤器:过滤器1和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
- 如: AFilter 和 BFilter,AFilter就先执行了。
- web.xml配置: 谁定义在上边,谁先执行
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
4.案例
1.案例1_登录验证
- 需求:
- 访问day17_case案例的资源。验证其是否登录
- 如果登录了,则直接放行。
- 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。
分析
2.案例2_敏感词汇过滤
需求:
- 对day17_case案例录入的数据进行敏感词汇过滤
- 敏感词汇参考《敏感词汇.txt》
- 如果是敏感词汇,替换为 ***
分析:
- 对request对象进行增强。增强获取参数相关方法
- 放行。传递代理对象
- 增强对象的功能:
- 设计模式:一些通用的解决固定问题的方式
- 装饰模式
- 代理模式
- 概念:
- 真实对象:被代理的对象
- 代理对象:
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
- 概念:
- 实现方式:
静态代理:有一个类文件描述代理模式
动态代理:在内存中形成代理类
- 实现步骤:
- 代理对象和真实对象实现相同的接口
- 代理对象 = Proxy.newProxyInstance();
3. 使用代理对象调用方法。
4. 增强方法
- 增强方式:
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
- 实现步骤:
Listener:监听器
1.概念
web的三大组件之一。
事件监听机制
- 事件 :一件事情
- 事件源 :事件发生的地方
- 监听器 :一个对象
- 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码
ServletContextListener:监听ServletContext对象的创建和销毁
- 方法:
- void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
- void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法
- 步骤:
定义一个类,实现ServletContextListener接口
复写方法
配置
- web.xml
cn.itcast.web.listener.ContextLoaderListener
- 方法:
* 指定初始化参数
2.注解
- @WebListener
Web(含小型項目)相关推荐
- java网站开发框架搭建手册_Javaweb項目框架搭建
前言 Java從大二開始學習到現在大四也有差不多兩年了,但是由於之前一直在玩,沒有認真學過,直到現在才開始重新學習.也是很湊巧,看到了黃勇老師的<架構探險>,於是便開始學習寫Java We ...
- Django項目部署到Ubuntu服務器
1.将DjanGo项目配置文件中的 ALLOWED_HOSTS设置为:当前服务器IP或*: ALLOWED_HOSTS = ["*",] 2.uwsgi a.在服務器安裝uwsgi ...
- qt mysql now()_Qt + mysql 運用 (項目一)
自己整合了一些資料方便以后查看,另外參考了一些資料嘗試做了個學生管理系統 以下資料若有錯誤或有侵權的地方,請前輩們指正,謝謝! 在Qt項目中右鍵執行qmake,之后在運行. 另外一種方法是在MVS20 ...
- p2p項目”復活“之想
http://blog.csdn.net/christopherwu/article/details/23976503 原來以為p2p項目就要夭折,墮入絕望無奈的深淵之時,與多位朋友的交流,抬頭看見了 ...
- Android小項目之---時間線程應用(附源碼)
进程 在Android 中,进程是应用程序的完整实现,而不是用户通常了解的那样.他们主要用途很简单: • 提高稳定性和安全性,将不信任或者不稳定的代码移动到其他进程. • 可将多个.apk 包运行在同 ...
- Android小項目之---吃飯選哪?--》選擇對話框(附源碼)
還記得早先我們做的記算器的例子嗎?當中的驗證判斷用到了對話框,今天我們來做一個不一樣的對話框,要做的這個小例子是一個可供選擇效果的對話框 即層層迭迭的Alert Dialog:界面方面我們擺放一個Bu ...
- Android小項目之---ListView实现论坛管理效果(附源碼)
在android系統中,ListView的用法稍微複雜一點,配置Adpater就有幾種方法,如ArrayAdapter,SimpleAdapter等.查了一些網上的相關例子,有很多都是用ListAct ...
- android dex2oatd e,解決android項目Error:Execution failed for task ':app:dexDebug'.ebug'錯誤
先上錯誤信息:Error:Execution failed for task ':app:dexDebug'.> com.android.ide.common.process.ProcessEx ...
- java利用穿透_Java本地的項目,怎么可以讓別人通過外網訪問-內網穿透
一.點擊鏈接 https://natapp.cn/ 注冊個免費的賬戶 NATAPP官網 二.登陸進去以后查看authtoken.復制這個,等下要在客戶端用到! 分配的authtoken 三.點擊個人中 ...
最新文章
- Vue PDF文件预览vue-pdf
- 设计模式 — 行为型模式 — 命令模式
- 关于angular的$resource中的isArray属性问题
- 编写一个函数itob(int n,char s[], int b),将整数n转换为以b进制的数。保存到s中。...
- java面试题十一 基本数据类型
- 业务模块化打造单体和分布式部署同步支持方案
- iOS LLDB console debug总结
- Python函数式编程指南(一):概述
- 云计算(1)---基础知识
- 手机电脑壁纸!让你的桌面变得超酷
- 《Windows Mobile平台应用与开发》写作工作顺利进行中
- ubuntu 编译android .img_全网可用交叉编译工具链大全
- linux中vim中文显示乱码
- 【干货】高盛合伙人制度和激励机制!
- pygame小游戏——英语单词挑战
- 单例模式的懒汉模式和饿汉模式
- 使用流程图描述程序的功能与流程
- poi实现多线程大数据导出
- Yapieasyapi文档管理平台安装与使用
- su [user] 和 su - [user]的区别
热门文章
- OpenGL3.3-细分着色器
- 世图兹公司与TSI公司合作设计模块化数据中心产品
- 音视频基础知识(流媒体、多媒体),视频文件等
- honeywell FTE桥接模块TK-FTEB01 51309512-175
- 托勒密天文学与希腊化科学
- 【智能家居入门篇】入坑智能家居前先等等,啥是网关?蓝牙、zigbee,原来区别这么大
- 直播平台开发,验证码工具类
- Java重写+malformed,java.lang.IllegalArgumentException: MALFORMED 问题解决
- 汽车标定知识整理(一):标定简介与CCP报文协议简介
- 盘点2021年Apache年报中出现的国产项目