JavaWeb
web开发
网页开发
静态web
动态web
- 数据库交互
- 常用技术栈:servlet,ASP,PHP
在java中,动态web资源开发的技术统称为JavaWeb
web应用程序
是一种可以通过Web访问的应用程序
静态web
动态web
web服务器
ASP
- ASP即Active Server Pages,是Microsoft公司开发的服务器端脚本环境,可用来创建动态交互式网页并建立强大的web应用程序。
- 在html中嵌入VB脚本,ASP+COM;
- 在ASP开发,基本页面代码量大,逻辑混乱
- C#
- IIS
JSP/Servlet
Tomcat
启动关闭
dns查询步骤
网站结构
HTTP
http协议簇
1、HTTP简介
HTTP(超文本传输协议),它是一种请求/响应式的协议,客户端与服务器建立连接后,就可以向服务器发送请求,这种请求被称为HTTP请求,服务器端收到请求后会做出响应,称为HTTP响应,客户端与服务器端在HTTP下的交互过程如图所示。
2、HTTP1.0和HTTP2.0
(1) HTTP1.0
客户端与服务器连接后,只能发送一个请求,断开连接。
(2) HTTP2.0
客户端与服务器连接后,发送N个请求,断开连接。
3、HTTP请求消息
一个完整的请求消息是由请求行,请求头和实体三部分组成,每部分的功能各不相同。
1、请求行
HTTP请求行包括几个部分,请求方式,资源路径…
HTTP的8种请求方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| GET在浏览器回退时是无害的,而POST会再次提交请求。 ● GET产生的URL地址可以被Bookmark,而POST不可以。 ● GET请求会被浏览器主动cache,而POST不会,除非手动设置。 ● GET请求只能进行url编码,而POST支持多种编码方式。 ● GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。 ● GET请求在URL中传送的参数是有长度限制的,而POST么有。 ● 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。 ● GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。 ● GET参数通过URL传递,POST放在Request body中。
|
2、请求消息头
请求消息头主要用于向服务器端传递附加消息,例如,客户端可以接收的数据类型、压缩方法、语言以及发送请求的超链接所属页面的URL地址等消息。
1 2 3 4 5 6
| Accept: 告诉浏览器,它所支持的数据类型 Accept-Encoding: 支持那种编码格式 Accept-Language: 指定客户端期望服务器返回哪个国家语言文档 Host:指定资源所在的主机名和端口号 Referer:常被网站管理人员用来查看网站的访问者是如何导航进入网站的。也可以用于网站的防盗链 Authorization:Proxy-Authorization:if-Match:if-Modified-Since:Range:if-RangeMax-Forward:User-Agent:
|
4、响应消息
当服务器收到浏览器的请求后,会回送响应给客户端。一个完整的响应消息主要包括响应状态行、响应消息头和实体内容
1、响应状态行
它包括三个部分,分别是HTTP版本,表示成功还是错误的状态码和对状态码进行描述的文本信息
例如:
响应状态码
状态码由3位数组成,第1个数定义了响应的类别,后面两位没有具体的分类
1
| 1XX:表示请求已接收,需要继续处理2XX:表示请求已成功被服务器接收、理解,并接收3XX:请求重定向4XX:客户端的请求有错误5XX:服务器端出现错误
|
400(错误请求)服务器不理解请求的语法 参数错误
401表示发送的请求需要有通过HTTP认证的认证信息 没有认证
403(禁止)服务器拒绝请求 无权限
404(未找到)服务器找不到请求网页 找不到
500 服务器错误
503 表示服务器处于停机维护或超负载,无法处理请求
2、响应消息头
向客户端传递附加消息,包括服务程序名、被请求资源需要的认证方式、客户端请求资源的最后修改时间、重定向地址等消息。
1
| Location:通知客户端获取请求文档新地址Refresh:告诉浏览器自动刷新的时间,以秒为单位Connection:告诉浏览器,请求完成是断开还是保证连接
|
Maven
架构管理工具
核心思想:约定大于配置
Maven会约束代码规范
环境配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <!-- localRepository | The path to the local repository maven will use to store artifacts. | Default: ${user.home}/.m2/repository localRepository 指定包下载的位置 --> <!-- 本地仓库位置 --> <localRepository>D:\java\m2</localRepository> ... <!-- 远程仓库位置 --> <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>aliyun maven</name> <url>http: </mirror>
|
镜像配置
本地仓库
IDEA项目创建
创建项目
可以使用idea开发工具构建,创建maven工程/web工程
创建完,需要配置坐标pom.xml文件
结束
一个干净的maven项目
标记文件夹
或者在project struct选择目录标记
配置Tomcat
创建配置文件
解决警告
maven命令
1 2 3 4 5
| mvn clean # 清理编译项目 mvn compile # 编译项目 mvn test # 测试项目 mvn package # 项目打包 mvn install # 安装到仓库中
|
pom配置文件
maven jar导入
搜索maven仓库,例如spring,并复制粘贴dependency,会自动导入jar以及所依赖的jar包
资源导出问题
搜索maven资源导出问题,copybuild代码到pom里面
maven生成目录树
Servlet
Servlet的工作过程
当用户通过 URL 发出一个请求时,这些 Java servlet 类就将之转换成一个 HttpServletRequest,并发送给 URL 所指向的目标。当服务器端完成其工作时,Java 运行时环境(JRE)就将结果包装在一个 HttpServletResponse 中,然后将原 HTTP 响应送回给发出该请求的客户机。
在与 Web 应用程序进行交互时,通常会发出多个请求并获得多个响应。所有这些都是在一个会话语境中,Java 语言将之包装在一个 HttpSession 对象中。在处理响应时,您可以访问该对象,并在创建响应时向其添加事件。它提供了一些跨请求的语境。
Servlet工作原理及架构
当Web服务器接收到一个HTTP请求时,它会先判断请求内容——如果是静态网页数据,Web服务器将会自行处理,然后产生响应信息;如果牵涉到动态数据,Web服务器会将请求转交给Servlet容器。此时Servlet容器会找到对应的处理该请求的Servlet实例来处理,结果会送回Web服务器,再由Web服务器传回用户端
针对同一个Servlet,Servlet容器会在第一次收到http请求时建立一个Servlet实例,然后启动一个线程。第二次收到http请求时,Servlet容器无须建立相同的Servlet实例,而是启动第二个线程来服务客户端请求。所以多线程方式不但可以提高Web应用程序的执行效率,也可以降低Web服务器的系统负担
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 1. 客户端 向Servlet容器(Tomcat)发出Http请求;
2. Servlet容器接收客户端的请求;
3. Servlet容器创建一个HttpRequest对象,将客户端请求的信息封装到这个对象中;
4. Servlet容器创建一个HttpResponse对象;
5. Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给 HttpServlet对象;
6. HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息;
7. HttpServlet调用HttpResponse对象的有关方法,生成响应数据;
8. Servlet容器把HttpServlet的响应结果传给客户端;
|
Servlet的生命周期
Http Servlet实现
继承HttpServlet类
继承GennerServlet类
实现Servlet类
web.xml配置
servlet标签和servlet mapping成对出现
1 2 3 4 5 6 7 8 9
| <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.loh.hservlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
|
- servlet标签处理当前请求需要使用哪个类进行处理
- mapping指定浏览器的映射路径
mapping问题
一个servlet可指定一个映射路径
1 2 3 4
| <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
|
一个servlet可指定多个映射路径
1 2 3 4 5 6 7 8 9 10 11 12
| <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping>
|
一个servlet可指定通用映射路径
1 2 3 4
| <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
|
可自定义指定前缀、后缀等
1 2 3 4
| <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*.do</url-pattern> </servlet-mapping>
|
指定了固定映射的mapping优先级最高,当找不到时会走默认处理请求
ServletContext
web容器在启动时会为每个web程序都创建一个对应的
ServletContext对象,代表了当前的web应用
为了解决Servlet程序直接进行IO操作导致效率低下的原因,ServletContext对象也能进行IO
1.共享数据
提交数据类
1 2 3
| ServletContext servletContext = this.getServletContext(); String username = "loh"; servletContext.setAttribute("username",username);
|
获取数据并输出
1 2 3 4 5 6
| ServletContext servletContext = this.getServletContext(); String username = (String) servletContext.getAttribute("username");
resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); resp.getWriter().print(username);
|
2.获取web参数
web.xml配置参数
1 2 3 4
| <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/mybatis</param-value> </context-param>
|
通过字段获取参数
1 2 3 4 5
| ServletContext context = this.getServletContext(); String url = context.getInitParameter("url");
PrintWriter printWriter = resp.getWriter(); printWriter.print(url);
|
3.请求转发
1 2 3 4 5
| ServletContext servletContext = this.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/hello"); requestDispatcher.forward(req,resp);
|
4.资源读取
resource文件夹新建properties
1 2
| username=loh password=123456
|
处理类从文件流中读取
1 2 3 4 5 6 7 8 9 10
| InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties(); prop.load(inputStream);
String user =prop.getProperty("username"); String pwd =prop.getProperty("password"); resp.getWriter().print(user+":"+pwd);
|
HttpServletResponse
我们再前面已经学过ServletContext(代表整个web应用的一个东西),我们了解到Servlet里面最重要的方法为service方法,service方法里面会有两个参数,为HttpServletRequest(请求),HttpServletResponse(响应)
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletResponse对象;
如果要获取客户端请求过来的参数:找HttpServletRequest
如果要给客户端响应一些信息:找HttpServletResponse
负责向浏览器发送数据的方法
(往外写出的方法)
1 2 3
| ServletOutputStream getOutputStream() throws IOException; PrintWriter getWriter() throws IOException;
|
负责向浏览器发送响应头的方法
这是ServletResponse里面的方法:
1 2 3 4
| void setCharacterEncoding(String var1); void setContentLength(int var1); void setContentLengthLong(long var1); void setContentType(String var1);
|
这是HttpServletResponse里面的方法
1 2 3 4 5 6 7 8 9 10 11
| void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
|
响应状态码
1 2 3 4 5
| int SC_CONTINUE = 100; int SC_OK = 200; int SC_NOT_FOUND = 404; int SC_INTERNAL_SERVER_ERROR = 500; int SC_BAD_GATEWAY = 502;
|
Response响应下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| String resourcePath = "G:\\Loh\\Code\\javaweb-maven\\ServletResponse\\src\\main\\resources\\2.png"; System.out.println("下载文件路径:"+resourcePath);
String fileName = resourcePath.substring(resourcePath.lastIndexOf("\\")+1);
resp.setHeader("Content-Disposition","attachment;fileName="+fileName);
FileInputStream in = new FileInputStream(resourcePath);
int len =0; byte[] buffer = new byte[1024];
ServletOutputStream out = resp.getOutputStream();
while ((len = in.read(buffer))!= -1){ out.write(buffer,0,len); }
in.close(); out.close();
|
转发和重定向的区别
HttpServletRequest
方法
验证码实现
实现思路
- 画笔绘制背景
- 画笔调用随机数生成方法生成随机数字验证码
- 浏览器参数设置绘制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setHeader("refresh","5");
BufferedImage Image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); Graphics2D g = Image.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0,0,80,20);
g.setColor(Color.black);
g.setFont(new Font("宋体",Font.BOLD,20));
g.drawString(makeNum(),0,20);
resp.setContentType("image/jpeg"); resp.setDateHeader("expires",-1); resp.setHeader("Cache-Control","no-cache"); resp.setHeader("Pragma","no-cache");
boolean jpg_out = ImageIO.write(Image, "jpg", resp.getOutputStream()); } private String makeNum(){ Random random = new Random(); String num = random.nextInt(9999999)+""; StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < 7-num.length(); i++) { stringBuffer.append("0"); } String s = stringBuffer.toString() + num; return num; }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
|
表单参数获取
前端提交参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <body> <h1>login</h1> <div> <%-- 当前项目路径获取--%> <form action="${pageContext.request.contextPath}login" method="post"> name:<input type="text" name="username"><br> password:<input type="password" name="password"><br> hobby: <input type="checkbox" name="hobby" value="code">code <input type="checkbox" name="hobby" value="sing">sing <input type="checkbox" name="hobby" value="watch movie">movie <br> <input type="submit"> <input type="reset"> </form> </div> </body>
|
后端获取
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name =req.getParameter("username"); String pwd =req.getParameter("password"); System.out.println(name); System.out.println(pwd);
}
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
|
请求转发
cookie
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();
if (cookies != null){ out.print("上次访问时间"); for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i];
if (cookie.getName().equals("lastLoginTime")){
long lastLoginTime = Long.parseLong(cookie.getValue()); Date date = new Date(lastLoginTime); out.write(date.toLocaleString()); } } }else { out.write("首次访问"); }
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
|
- cookie内容乱码可以用URLEncoder.encode和decode进行编解码内容
cookie设置path
session
session的两种实现方式
第一种方式的理解:就是把session的id 放在cookie里面(为什么是使用cookies存放呢,因为cookie有临时的,也有定时的,临时的就是当前浏览器什么时候关掉即消失,也就是说session本来就是当浏览器关闭即消失的,所以可以用临时的cookie存放。保存再cookie里的sessionID一定不会重复,因为是独一无二的。),当允许浏览器使用cookie的时候,session就会依赖于cookies,当浏览器不支持cookie后,就可以通过第二种方式获取session内存中的数据资源。
第二种方式的理解:在客户端不支持cookie的情况下使用。为了以防万一,也可以同时使用。
如果不支持cookie,必须自己编程使用URL重写的方式实现。
如何重写URL:通过response.encodeURL()方法
encodeURL()的两个作用
第一个作用:转码(说明:转中文的编码,或者一些其他特殊的编码。就好比如网页的链接中存在中文字符,就会转换成为一些百分号或者其他的符号代替。)
第二个作用:URL后面加入sessionID,当不支持cookie的时候,可以使用encodeURL()方法,encodeUTL()后面跟上sessionID,这样的话,在禁用cookie的浏览器中同时也可以使用session了。但是需要自己编程,只要链接支持,想用session就必须加上encodeURL()。
提示:若想程序中永远支持session,那就必须加上encodeURL(),当别人禁用了cookie,一样可以使用session
session的创建获取和销毁
Session创建
Session获取
Session注销
web.xml中session过期时间配置
使用场景
Cookie和Session的区别
1、数据存放位置不同:
cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、安全程度不同:
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
3、性能使用程度不同:
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
4、数据存储大小不同:
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。
5、会话机制不同
session会话机制:session会话机制是一种服务器端机制,它使用类似于哈希表(可能还有哈希表)的结构来保存信息。
cookies会话机制:cookie是服务器存储在本地计算机上的小块文本,并随每个请求发送到同一服务器。 Web服务器使用HTTP标头将cookie发送到客户端。在客户端终端,浏览器解析cookie并将其保存为本地文件,该文件自动将来自同一服务器的任何请求绑定到这些cookie。
JSP原理
JSP(Java Server Pages)是一种动态网页开发技术。JSP 文件就是在传统的 HTML 文件中插入 Java 代码和 JSP 标签,后缀名为.jsp
。
JSP 与 PHP、ASP、ASP.NET 等语言类似,都运行在服务端。通常返回给客户端的就是一个 HTML 文件,因此只要有浏览器就能查看 JSP 页面。
JSP 使用 JSP 标签在 HTML 网页中插入 Java 代码,标签通常以<%
开头,以%>
结束。JSP 标签有多种功能,比如访问数据库和 JavaBean 组件等,还可以在不同的网页之间传递和共享信息。
JSP 是 Servlet 的扩展,我们可以在 JSP 中使用 Servlet 的所有功能。另外,JSP 还提供了一些其他功能,例如 EL 表达式、自定义标签等。
JSP 依赖于 Servlet,用户访问 JSP 页面时,JS 1被翻译成 Servlet 代码,最终,以字符串的形式向外输出 HTML 代码。所以,JSP 只是在 Servlet 的基础上做了进一步封装。
JSP 通过表单获取用户输入的数据、访问数据库或其它数据源生成动态的 Web 内容。
jsp内置对象
语法
指令标识
指令标识主要用于设定整个JSP页面范围内都有效的相关信息,它是被服务器解释并执行的,不会产生任何输出到网页中的内容,也就是说指令标识对客户端浏览器是不可见的。
JSP指令标识的语法格式如下:
1
| <%@ 指令名 属性1="属性值" 属性2="属性值"......%>
|
- 指令名:用于指定指令名称,在JSP中包含page,include和taglib3条指令。
- 属性:用于指定属性名称,不同的指令包含不同的属性。一个指令可以设置多个属性,各属性之间用分号隔离。
- 属性值:用于指定属性值。
1.page指令
这是JSP页面最常用的指令,用于定义整个JSP页面的相关属性,这些属性在JSP被服务器解析成Servlet时会转换为相应的Java程序代码。page
指令的语法格式如下:
1
| <%@ page 属性1="属性值1" 属性2="属性值2"...%>
|
page指令提供了language、contentType、import、autoFlush、buffer、errorPage、extends、info、isELIgnored、isErrorSafe和session共13个属性。
下面对常用的属性进行介绍:
2.include指令
通过include指令可以在JSP页面中包含另一个JSP页面,不过该指令是静态包含指令,也就是说被被包含文件中的所有内容会被原样包含到该JSP页面中,即使被包含文件中有JSP代码,在包含时不会被编译执行。使用include指令最终将生成一个文件,所以在被包含和包含的文件中不能有相同名称的变量。
include指令的语法格式如下:
1
| <%@ include file="path"%>
|
该指令只有一个file属性,用于指定要包含文件的路径。该路径是相对路径,也可以是绝对路径,但不可以是通过<%=%>表达式所代表的文件。
3.taglib指令
在JSP文件中,可以通过taglib指令标识声明该页面中所使用的标签库,同时引用标签库,并指定标签的前缀。在页面中引用标签库后,就可以通过前缀来引用标签库中的标签。taglib指令的语法格式如下:
1
| <%@ taglib prefix="tagPrefix" uri="tagURI"%>
|
- prefix属性:用于指定标签的前缀。该前缀不能命名为jsp、jspx、java、javax、sun、servlet和sunw。
- uri属性:用于指定标签库文件的存放位置。
例:在页面中引用JSTL中的核心代码库,实例代码如下:
1
| <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
脚本标识
JSP表达式
JSP表达式用于向页面中输出信息,其语法格式如下:
- 表达式:可以是任何Java语言的完整表达式。该表达式的最终运算结果将转换为字符串。
例:使用JSP表达式在页面中输出信息,示例代码如下:
1 2 3 4 5 6
| <%String manager="mr"; %> <!--定义保存管理员名的变量--> 管理员:<%=manager %> <!--输出结果为:管理员: mr--> <%="管理员:"+manager %> <!--输出结果为:管理员: mr --> <%= 7+6 %> <!--输出结果为:13 --> <%String url="head01.jpg";%><!--定义保存文件名称的变量--> <img src="images/<%url %>"> <!--输出结果为:<img src="images/head01.jpg">-->
|
代码片段
所谓代码片段就是在JSP页面中嵌入的Java代码或脚本代码。代码片段将在页面请求的处理期间被执行,通过Java代码可以定义变量或流程控制语句等;而通过脚本代码可以应用JSP的内置对象在页面输出内容、请求处理和响应、访问session会话等。代码片段的语法格式如下:
代码片段的使用比较灵活,他所实现的功能是JSP表达式无法实现的。
例:通过代码片段和JSP表达式在JSP页面上输出九九乘法表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <body> <% String str=""; for(int i=0;i<=9;i++){ for(int j=0;j<=9;j++) { str+=j+"x"+i+"="+j*i; str+=" "; } str+=<"br">; } %> <div> <ul> <li id="title">九九乘法表</li> <li><%=str%><!--输出九九乘法表--></li> <ul> </div> </body>
|
声明标识
声明表示用于在JSP页面中定义全局的变量或方法。通过声明表示定义的变量和方法可以被整个JSP页面访问,所以通常使用该标识定义整个JSP页面都需要引用的变量或方法。
声明标识的语法格式如下:
例:通过声明标识声明一个全局变量和全局方法:
1 2 3 4 5 6 7
| <%! int number = 0; int count(){ number++; return number; } %>
|
jsp 9大内置对象
- PageContext 保存数据
- Request 保存数据
- Response
- Session 保存数据
- Application【ServletContext】 保存数据
- config【ServletConfig】
- out
- page
- exception
JSP标签、JSTL标签、EL表达式
EL表达式
- 获取数据
- 执行运算
- 获取web开发的常用对象
- 调用java
JSP标签
JSTL
实现了JSP页面的代码复用。基于标签库原理,重复率较高的代码块支持复用,提高效率。
书写JSP页面时可读性更强。长得像XML,方便前端查看和参与开发。
在应用程序服务器之间提供了一致的接口,最大程度地提高了WEB应用在各应用服务器之间的移植。
简化了JSP和WEB应用程序的开发。
- 通过jstl标签库弥补jsp使用原生html语法的不足
根据JSTL标签所提供的功能,可以将其分为5个类别。
核心标签
- ```
<%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core" %>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| - ![](JavaWeb开发/image-20230828202915257.png)
- **格式化标签**
- **SQL 标签**
- **XML 标签**
- **JSTL 函数**
![](JavaWeb开发/image-20230828203838019.png)
## jsp不能取值问题
web.xml头文件版本太低
# JavaBean
实体类
JavaBean特定写法
- 必须有一个无参构造 - 属性私有化 - 必有相应的get/set
一般用来和数据库字段做映射 ORM:
ORM:对象关系映射
- 表----->类 - 字段---->属性 - 行记录---->对象
# MVC架构
什么是MVC:
Model 模型
View 视图
Controller 控制器
早期业务架构
![](JavaWeb开发\image-20230831155054203.png)
![](JavaWeb开发\image-20230831155043558.png)
MVC架构
![](JavaWeb开发\image-20230831155733781.png)
model
- 业务处理:业务逻辑模型往往是对数据的处理,如订单和用户信息的修改。(service)
- 数据持久层:CRUD(Dao)
View
- 内容展示:视图是将模型的内容呈现出来 - 发起请求:用户可以通过对视图的操作进而操作模型,封装的是对数据源Model的显示
Controller(Servlet处理)
- 接受请求:(req携带请求参数,session信息等....) - 分析业务请求,想业务处理发起处理 - 控制视图跳转
![](JavaWeb开发\image-20230901134011155.png)
# 过滤器:Filter
## 过滤器简介
filter也称之为过滤器,它是javaWeb三大组件之一(Servlet程序、Listener监听器、Filter过滤器)
**作用:**既可以对请求进行拦截,也可以对响应进行处理。![](https://img-blog.csdnimg.cn/8f87baaec54244e08a6a33cdcff7be8f.png)
**常见场景:**权限检查,日记操作、拦截请求、过滤操作、对请求字符设置编码。
## filter开发步骤
### Maven依赖
```xml
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>
<dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency>
<dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
<dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>
|
类实现filter接口
导入包名
重写方法
servlet配置
改servlet通过servlet配置的两个路径均可访问,filter过滤servlet路径后,show路径仍为乱码,全路径不乱码
报错
- 错误日志内容:org.apache.catalina.core.StandardContext.startInternal Context [/16_filter] startup failed due to previous errors
filter类方法重写,所以方法体里自带一段super语句,删除这个语句Tomcat就可以正常运行了。
监听器:listener
开发步骤
实现监听器接口并重写方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package com.loh.listener;
import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import java.net.http.WebSocket;
public class OnlineCountListener implements HttpSessionListener {
@Override public void sessionCreated(HttpSessionEvent se) {
ServletContext sct = se.getSession().getServletContext();
Integer onlineCount = (Integer) sct.getAttribute("OnlineCount");
if(onlineCount==null){ onlineCount =Integer.valueOf(1); }else { int count = onlineCount.intValue(); onlineCount=Integer.valueOf(count+1); } sct.setAttribute("OnlineCount",onlineCount); }
@Override public void sessionDestroyed(HttpSessionEvent se) { ServletContext sct = se.getSession().getServletContext();
Integer onlineCount = (Integer) sct.getAttribute("OnlineCount");
if(onlineCount==null){ onlineCount =Integer.valueOf(0); }else { int count = onlineCount.intValue(); onlineCount=Integer.valueOf(count-1); } sct.setAttribute("OnlineCount",onlineCount); } }
|
注册监听器
1 2 3 4
| <listener> <listener-class>com.loh.listener.OnlineCountListener</listener-class> </listener>
|
jsp输出
1 2 3 4 5 6 7 8 9
| <html> <body> <%--以下为两行jsp表达式--%> <%@ page pageEncoding="utf-8"%> <h1>当前<span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1> <h1>当前<span><%=application.getAttribute("OnlineCount")%></span>人在线</h1> <h2>Hello World!</h2> </body> </html>
|
gui中应用监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| package com.loh.listener;
import javax.swing.*; import java.awt.*; import java.awt.event.WindowEvent; import java.awt.event.WindowListener;
public class TestPanel { public static void main(String[] args) {
Frame frame = new Frame("lets go");
Panel panel = new Panel();
frame.setLayout(null);
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(0,0,255));
panel.setBounds(50,50,300,300); panel.setBackground(new Color(0,255,0)); frame.add(panel); frame.setVisible(true);
frame.addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { }
@Override public void windowClosing(WindowEvent e) {
System.exit(1); }
@Override public void windowClosed(WindowEvent e) {
}
@Override public void windowIconified(WindowEvent e) {
}
@Override public void windowDeiconified(WindowEvent e) {
}
@Override public void windowActivated(WindowEvent e) {
}
@Override public void windowDeactivated(WindowEvent e) {
} }); } }
|
浏览器登录过滤器项目
描述 该项目共有三 个web资源,三个java类
其中login作为主登录页,主方法类LoginMethod添加seesion字段,并判断字段分辨用户是否登录,并跳转至相应页面
web
success
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <%--启用过滤器时注销下面的jsp代码--%> <%--<%--%> <%-- Object userSession = request.getSession().getAttribute("USER_SESSION");--%> <%-- if (userSession == null){--%> <%-- response.sendRedirect("/Login.jsp");--%> <%-- }--%> <%--%>--%> <p><a href="/servlet/logout">注销</a></p> </body> </html>
|
error
1 2 3 4 5 6 7 8 9 10
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>error</h1> <p><a href="/Login.jsp">返回首页</a></p> </body> </html>
|
login
1 2 3 4 5 6 7 8 9 10 11 12 13
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>login</h1> <form action="/servlet/login" method="post"> <input type="text" name="username"> <input type="submit"> </form> </body> </html>
|
java
LoginMethod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.loh.filter_admin;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
public class LoginMethod extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username"); if (username.equals("admin")){
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp"); }else { resp.sendRedirect("/error.jsp"); }
} @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
|
LogoutMethod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.loh.filter_admin;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
public class LogoutMethod extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Object userSession = req.getSession().getAttribute("USER_SESSION"); if (userSession != null){ req.getSession().removeAttribute("USER_SESSION"); resp.sendRedirect("/Login.jsp"); } }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
|
FilterDo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.loh.filter_admin;
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
public class FilterDo implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { }
@Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp;
if (request.getSession().getAttribute("USER_SESSION")==null){ response.sendRedirect("/error.jsp"); }
chain.doFilter(req,resp); }
@Override public void destroy() {
} }
|
注册filter
1 2 3 4 5 6 7 8 9
| <filter> <filter-name>SysFilter</filter-name> <filter-class>com.loh.filter_admin.FilterDo</filter-class> </filter>
<filter-mapping> <filter-name>SysFilter</filter-name> <url-pattern>/sys/*</url-pattern> </filter-mapping>
|
JDBC Relearn(复习)
加载数据库
连接数据库,代表数据库
向数据库发送sql对象statement:crud
编写sql
执行sql
关闭连接
1 2 3 4 5 6 7 8 9
| CREATE TABLE users( `id` INT PRIMARY KEY, `name` VARCHAR(40), `password` VARCHAR(40), `email` VARCHAR(60), `birthday` DATE );
INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)VALUES(1,'李四','123455','sss@qq.com','2021-01-09');
INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)VALUES(2,'王五','123455','sss@qq.com','2021-01-09');
INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)VALUES(3,'李四2','123455','sss@qq.com','2021-01-09');
SELECT * FROM users;
|
statement
查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package com.loh.test;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement;
public class TestJdbc01_Statement { public static void main(String[] args) throws Exception { String url = "jdbc:mysql://localhost:3306/JDBC_WEB?useUnicode=true&characterEncoding=utf-8"; String username = "root"; String password = "123456";
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement();
String sql = "select * from users";
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){ System.out.println("id=" + rs.getObject("id")); System.out.println("name=" + rs.getObject("name")); System.out.println("password=" + rs.getObject("password")); System.out.println("email=" + rs.getObject("email")); System.out.println("birthday=" + rs.getObject("birthday")); }
rs.close(); statement.close(); connection.close(); } }
|
增删改
代码与查询基本一致,statement方法以及返回类型不一致,注意,关闭方式相同
1 2 3 4 5 6
|
sql ="insert into jdbc_web.users(ID, NAME, PASSWORD, EMAIL, BIRTHDAY) VALUES(4,'DA','12234','21423@QQ.COM','2021-10-28')";
int i = statement.executeUpdate(sql); System.out.println("有"+i+"行受影响");
|
preparestatement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.loh.test;
import java.sql.*;
public class TestJdbc02_PrepareStatement { public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://localhost:3306/JDBC_WEB?useUnicode=true&characterEncoding=utf-8"; String username = "root"; String password = "123456";
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "insert into jdbc_web.users(id, name, password, email, birthday) VALUES (?,?,?,?,?);";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,5); preparedStatement.setString(2,"xaxa"); preparedStatement.setString(3,"54321"); preparedStatement.setString(4,"dasda@qq.com"); preparedStatement.setDate(5,new java.sql.Date(new java.util.Date().getTime()));
int rs = preparedStatement.executeUpdate();
if (rs > 0){ System.out.println("插入成功"); }else { System.out.println("错误"); }
preparedStatement.close(); connection.close(); } }
|