技术
1、 数据库
2、 Java代码
3、 网页技术(HTML、CSS)
4、 动态网页技术:Jsp、Servlet
环境配置
第一步:
下载Tomcat:https://tomcat.apache.org/download-90.cgi
把Java和Tomcat连接起来
第二步:
新建一个Dynamic Web Project
Targete runtime 选Tomcat对应的版本
第三步:
在WebContent里面新建HTML文件
建一个文件夹放图片
B/S结构和C/S结构
B/S结构:(B/S最大优势为客户端免维护,适用于用户群庞大,或客户需求经长发生变化的情况。)
B/S结构(Browser/Server,浏览器/服务器模式),是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。
c/s结构:(C/S功能强大,可以减轻服务器端压力,如果用户的需求特别复杂,用C/S。)
Client/Server结构(C/S结构)是大家熟知的客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。
对比
一、C/S
1.优点:
(1)安全性:需要其特定的客户端,所以面向对象比较确定,将所进行的信息安全处于一个可控的范围
(2)效率:客户端的服务器直接相连,省却了中间环节,数据的传输比较快
(3)个性化:有特定的客户端,所以可以在较大程度上满足客户的个性化要求
(4)稳定性:结构比较稳定,有较强的事务处理能力,可以实现较复杂的业务逻辑
2.缺点:
(1)特定的客户端:对pc机有一定的要求,如:操作系统,并且它就像订在墙上的石头桌子,不可再利用
(2)中间环节:因为省却了中间环节,所以当客户端达到一定的量时,同时访问服务器,造成服务器的相应变慢,效率变低
二、B/S
1.优点:
(1)范围:零安装,拥有一个浏览器,即可访问,面向的范围更广
(2)维护性:维护简单,更新页面,即可实现面向所有用户的更新
(3)共享性:通过浏览器访问,共享性强,就像买来的餐桌,可以再利用
2.缺点:
(1)安全性:面向的范围广,所以安全性比较低
(2)个性化:因为面向的范围广,所以它是一种公共审美,无法满足个性化的需求
Servlet
b/s结构下,以常见的自来水供水系统为例来说,整个web系统好比完整的供水系统,用户只需要有水龙头(Broswer),水管相当于计算机网络(network),自来水公司的供水系统(即Server),其中的压力水罐就是容器(Container)了。
大家都知道Servlet,但是不一定很清楚servlet框架,这个框架是由两个Java包组成:javax.servlet和javax.servlet.http. 在javax.servlet包中定义了所有的Servlet类都必须实现或扩展的的通用接口和类.在javax.servlet.http包中定义了采用HTTP通信协议的HttpServlet类.
https://blog.csdn.net/honghailiang888/article/details/50585475
https://www.cnblogs.com/leiqiannian/p/7797188.html
Servlet是sun公司提供的一门用于开发动态web资源的技术。
Sun公司在其API中提供了一个servlet接口,用户若想开发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
1、编写一个Java类,实现servlet接口。(Tomcat以编写好)
2、把开发好的Java类部署到web服务器中。
按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为Servlet
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
服务器
硬件角度上说就是一台高性能的Computer。我们通常指的服务器其实应该是装有能够处理具体请求事务的服务器软件的Computer。比如最常见的www服务器、mail服务器、计费服务器、ftp服务器等等。很多时候人们常把诸如Tomcat、IIS、Weblogic 也称之为web服务器,其实这些只是用于开发、集成、部署和管理Web应用、网络应用和数据库应用的应用服务器软件。
什么是容器?
Servlet没有main()方法。Servlet受控于另一个Java应用,这个Java应用称为容器。Tomcat就是这样一个容器。如果web服务器应用得到一个指向servlet的请求(而不是其他请求,如请求一个普通的静态HTML),此时服务器不是把这个请求交给servlet本身,而是交给部署该servlet的容器,要由容器调用servlet的方法,如doPost()或doGet()。
doGet()和doPost()的区别
https://blog.csdn.net/baidu_25310663/article/details/50675384
405错误:
https://blog.csdn.net/qq_35804654/article/details/77272304
doGet可以通过URL访问,doPost不能
从字面上可以看出,get(获取)重点在从服务器上获取资源,post(发送)是向服务器发送数据;
不同点一:
通过get方式提交的数据有大小的限制,通常在1024字节左右。也就是说如果提交的数据很大,用get方法就可需要小心;而post方式没有数据大小的限制,理论上传送多少数据都可以。
不同点二:
通过get传递数据,实际上是将传递的数据按照”key,value”的方式跟在URL的后面来达到传送的目的的;而post方式提交数据时是采用的HTTP post机制,是将表单中的字段与值放置在HTTP HEADER内一起传送到ACTION所指的URL中,用户是看不见的。
长连接和短连接
短连接
连接->传输数据->关闭连接
HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束后就中断连接。短连接是指SOCKET连接后发送后接收完数据后马上断开连接。
长连接
连接->传输数据->保持连接->传输数据->....->关闭连接
长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。
@WebServlet(urlPatterns="/user")
@WebServlet作用:告诉Web容器有关于这个Servlet的一些信息。
只要在Servlet上设置@WebServlet标注,容器就会自动读取当中的信息。上面的@WebServlet告诉容器,如果请求的URL是“user”,则由UserServlet的实例提供服务。
在Java EE相关应用程序中使用标注时,可以记得的是,没有设置的属性通常会有默认值。例如,若没有设置@WebServlet的name属性,默认值会是Servlet的类完整名称。
当应用程序启动后,事实上并没有创建所有的Servlet实例。容器会在首次请求需要某个Servlet服务时,才将对应的Servlet类实例化、进行初始化操作,然后再处理请求。这意味着第一次请求该Servlet的客户端,必须等待Servlet类实例化、进行初始动作所必须花费的时间,才真正得到请求的处理。
端口号
主机拥有一个IP地址,为了区分不同的网络服务,引入端口号,通过“IP地址+端口号”来区 分不同的服务。
在网络技术中,端口(Port)包括逻辑端口和物理端口两种类型。物理端口指的是物理存在的端口,如ADSL Modem、集线器、交换机、路由器上用 于连接其他网络设备的接口,如RJ-45端口、SC端口等等。逻辑端口是指逻辑意义上用于区分服务的端口,如TCP/IP协议中的服务端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等。由于物理端口和逻辑端口数量较多,为了对端口进行区分,将每个端口进行了编号,这就是端口号。
端口有什么用呢?我们知道,一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区 分不同的服务的。
请求和响应:
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。
request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了。
HTTPServletRequest(接口)
参考网页:http://www.cnblogs.com/xdp-gacl/p/3798347.html
公共接口类HttpServletRequest继承自ServletRequest。客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。对象包含了客户端请求信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操作系统都包含在其内。
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
Request常用方法
request.getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型 。
request.getParameter表示接收参数,参数为页面提交的参数,包括:表单提交的参数、URL重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter),而且接收参数返回的不是Object,而是String类型。
setAttribute的参数是String 和 Object ,
放一些基本数据类型时需要先封装
1.放的时候:Double res = new Double(result);//包装
request.setAttribute("result", res);//再设置进去
2.取的时候:Double res = (Double)request.getAttribute("result");
double result = res.doublue();
另外,需要注意的是使用request.setAttribute时不能使redirect而是forward。即是将请求转发而不是重定向.
Servlet |
Http Servlet Request(携带信息的对象) |
响
请 应
求
HTML页面 |
HTTPServletResponse(接口)
生成的对象是服务器到页面的使者
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。(同时创建)
response对象也定义了处理HTTP头模块的接口。通过这个对象,开发者们可以添加新的cookies,时间戳,HTTP状态码等等。
java中的getAttribute和getParameter
https://blog.csdn.net/yiwangxiblog/article/details/55814544
页面跳转:
https://blog.csdn.net/qq_34111779/article/details/78164027
例如:
请求转发:
request.getRequestDispatcher("/student_list.jsp").forward(request,response);
重定向:
response.sendRedirect(request.getContextPath + "/student_list.jsp")
Forward是在服务器端的跳转,就是客户端一个请求给服务器,服务器直接将请求相关参数的信息原封不动的传递到该服务器的其他jsp或Servlet去处理。而sendRedirect()是客户端的跳转,服务器会返回客户端一个响应报头和新的URL地址,原来的参数信息如果服务器没有特殊处理就不存在了,浏览器会访问新的URL所指向的Servlet或jsp,这可能不是原来服务器上的webService了。
请求转发(能携带数据,将request、response中的数据传到下一个服务器)
请求转发,即request.getR equestDispatcher().forward(),是一种服务器的行为,客户端只有一次请求,服务器端转发后会将请求对象保存,地址栏中的URL地址不会改变,得到响应后服务器端再将响应发给客户端;
转发过程:客户端首先发送一个请求到服务器(即登录操作),服务器匹配Servlet(即验证用户信息),并指定执行。当这个Servlet执行完后,它要调用getRequestDispacther()方法,把请求转发给指定的Servlet_list.jsp,整个流程都是在服务端完成的,而且是在同一个请求里面完成的,因此Servlet和jsp共享同一个request,在Servlet里面放的所有东西,在student_list.jsp中都能取出来。因此,student_list.jsp能把结果getAttribute()出来,getAttribute()出来后执行完把结果返回给客户端,整个过程是一个请求,一个响应。
重定向(不能携带数据)
请求重定向,即response.sendRedirect(),是一种客户端行为,从本质上讲等同于两次请求,前一次请求对象不会保存,地址栏的URL地址会改变。
重定向过程:客户端发送一个请求到服务器端,服务器匹配Servlet,这都和请求转发一样。Servlet处理完之后调用了sendRedirect()这个方法,这个方法是response方法。所以,当这个Servlet处理完后,看到response.sendRedirect()方法,立即向客户端返回个响应,响应行告诉客户端你必须再重新发送一个请求,去访问student_list.jsp,紧接着客户端收到这个请求后,立刻发出一个新的请求,去请求student_list.jsp,在这两个请求互不干扰、相互独立,在前面request里面setAttribute()的任何东西,在后面的request里面都获得不了。因此,在sendRedirect()里面是两个请求,两个响应。
短连接
连接->传输数据->关闭连接
HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束后就中断连接。短连接是指SOCKET连接后发送后接收完数据后马上断开连接。
特点:
1. 需要的时候才建立连接;
2. 每次只发送一项业务。
短连接登陆原理:
HTTP长连接和短连接原理浅析:
https://blog.csdn.net/sheng_bin/article/details/53291410
Session机制
Session详解
https://www.cnblogs.com/lonelydreamer/p/6169469.html
Session:
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。
当一个session第一次被启用时,一个唯一的标识被存储于本地的cookie中。
session只存储在服务器端的,不会在网络中进行传输,所以较cookie来说,session相对安全一些。但是session是依赖cookie的,当用户访问某一站点时,服务器会为这个用户产生唯一的session_id,并把这个session_id以cookie的形式发送到客户端,以后的客户端的所有请求都会自动携带这个cookie(前提是浏览器支持并且没有禁用cookie)。
存储需要在整个用户会话过程中保持其状态的信息,例如登录信息或用户浏览 Web应用程序时需要的其它信息。
Session 的作用就是它在 Web服务器上保持用户的状态信息供在任何时间从任何页访问。因为浏览器不需要存储任何这种信息(这种信息存在服务器上),所以可以使用任何浏览器,即使是像 Pad 或手机这样的浏览器设备。(是在服务器端跟浏览器无关)
Session作用:
用来解决Http协议不能维持状态的问题。
Session特点:
https://blog.csdn.net/ai_houzi/article/details/48846255
- session在用户第一次请求服务器时被创建
- session只存储在服务器端的(和浏览器没有任何关系),不会在网络中进行传输
- session是依赖cookie的
- 存储需要在整个用户会话过程中保持其状态的信息
- Session也是一种key-value的属性对
- 服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。
Cookie(储存在用户本地终端上的数据)
指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。
- 目前公认的是,通过 Cookie 和 Session 技术来实现记录访问者的一些基本信息
- 服务器中的session产生的session_id及其他必要信息保存到客户端的cookie中
- 用户再次发送请求时会将本地的cookie值放在HTTP请求头中,
- Cookie具有不可跨域名性,Cookie在客户端是由浏览器来管理的。
参考网页:https://zhidao.baidu.com/question/336754505.html
银行信息系统
Login页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<hr>
<form action="user" method="post">
UserName<input type="text" name="username">
PassWord<input type="password" name="pwd">
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
</body>
</html>
用户信息验证:
服务程序,用于验证用户信息,并利用请求转发和重定向进行页面跳转
若信息正确则跳转到个人信息主页面,否则重定向到登录页面
package com.nwnu;
import java.io.IOException;
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;
@WebServlet(urlPatterns="/user")//无论信息是否正确都会跳转到http://localhost:8080/HelloWorld/user只不过信息不正确时立马重定向到login页面
public class UserServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");//获取属性
String pwd = req.getParameter("pwd");
if("zhangSan".equals(username) && "1234".equals(pwd)) {
HttpSession session = req.getSession();
session.setAttribute("user","zhangSan");
//请求转发
req.getRequestDispatcher("main.html").forward(req, resp);
}else {
//重定向
resp.sendRedirect("login.html");
}
}
}
主页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
main
<a href="bank">secret</a>// http://点击由http://localhost:8080/HelloWorld/user 跳到 localhost:8080/HelloWorld/bank
</body>
</html>
银行信息服务:
package com.nwnu;
import java.io.IOException;
import java.io.PrintWriter;
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;
@WebServlet(urlPatterns="/bank")//链接到新的页面的URL必须加反斜杠,若存在多级目录可用../进行调试
public class BankServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Object username = session.getAttribute("user");
if(username != null) {
PrintWriter out = resp.getWriter();
out.println("yin hang ka xin xi");
}else {
resp.sendRedirect("login.html");
}
}
}
多个链接请求一个servlet
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="DemoServlet?op=forword">forward</a>
<a href="DemoServlet?op=redirect">direct</a>
//http://localhost:8080/Demo/DemoServlet?op=redirect
</body>
</html>
package com.zparked.controler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/DemoServlet")
public class DemoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String op = request.getParameter("op");
switch (op) {
case "forword":
System.out.println("forword");
request.getRequestDispatcher("http://baidu.com").forward(request, response);//跳转失败,找不到:/Demo/http://baidu.com
break;
case "redirect":
System.out.println("redirect");
response.sendRedirect("http://baidu.com");
break;
default:
break;
}
}
}
手动部署项目
Tomcat只能运行class文件
Jsp执行原理:
Jsp必须运行在Tomcat中,jsp先转化成servlet再运行在Tomcat中,最终运行在JRE中。
Servlet执行原理:
Servlet运行在Tomcat中Tomcat运行在JVM中
- 把web项目expore出来
- 把war文件放到C:\Program Files\apache-tomcat-9.0.5\webapps路径下
- 运行startup.bat(保持开启) 将.war文件进行解压。
- 在浏览器中运行
JSP
JSP页面是如何被执行的?JSP执行效率比Servlet低吗?
答:当客户端向一个JSP页面发出请求时,Web Container将JSP转换成Servlet的源代码(只是第一次请求时),然后编译转化后的Servlet并加载到内存中执行,执行的结果Response到客户端。
JSP只在第一次执行的时候会转化为Servlet,以后的每次执行Web容器都是直接执行编译后的Servlet,所有JSP和Servlet只有第一次执行的时候不一样,JSP慢一点,以后的执行都是相同的。
JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计。它是在传统的网页HTML文件中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件
- JSP可以直接写Java代码(脚本)(现在都用JSTL代替脚本语言)
- JSP内可以用<%! %>或<% %>定义变量,变量在整个jsp页面中有效
- Jsp中可以使用out或<%= %>往页面中输出信息(多用EL表达式)
- 请求jsp页面时session被自动创建
示例代码:
<body>
<h1>aaaaaaaaaa</h1>
<%
int a = 123;
String b = "abc";
System.out.print(a+""+b);
out.write(a+""+b);
%>
<%=a+" " +b %>
</body>
<% %>与<%! %>的区别:
<%! %>标记符:
1.在<%! %>之间声明的变量和方法在整个jsp页面内都有效,也就是说说可以理解为<%! %>之间声明的是全局的变量和方法,可以方法可以被公有使用,变量则可以被所有方法调用改变。
2.当有运行多个线程时,任何一个线程对jsp页面成员变量操作的结果,都会影响其他线程。
<% %>标记符:
在<% %>之间声明的变量则为“局部变量”,当运行多个线程时,不同线程中的java程序片的局部变量无不干扰,也就是说一个用户改变java程序片中的局部变量的值不会影响下一个用户java程序片中的局部变量。
JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
答:JSP是Servlet的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类Servlet"。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是java和HTML可以组合成一个扩展名为.jsp的文件。JSP偏重于视图,Servlet偏重于业务逻辑。
Jsp指令
https://www.runoob.com/jsp/jsp-directives.html
Page指令
Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令。
指令 | 描述 |
<%@ page ... %> | 定义网页依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include ... %> | 包含其他文件 |
<%@ taglib ... %> | 引入标签库的定义 |
Taglib指令
JSP API允许用户自定义标签,一个自定义标签库就是自定义标签的集合。
Taglib指令引入一个自定义标签集合的定义,包括库路径、自定义标签。
Taglib指令的语法:
<%@ taglib uri="uri" prefix="prefixOfTag" %>
uri属性确定标签库的位置,prefix属性指定标签库的前缀。
Jsp九大内置对象
https://www.runoob.com/jsp/jsp-implicit-objects.html
对象 | 描述 |
request | HttpServletRequest 接口的实例 |
response | HttpServletResponse 接口的实例 |
out | JspWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
常用:
request
response
session
out
page
pageContext
response.getWriter().write()与out.print()的区别
1、首先介绍write()和print()方法的区别:
(1)、write():仅支持输出字符类型数据,字符、字符数组、字符串等
(2)、print():可以将各种类型(包括Object)的数据通过默认编码转换成bytes字节形式,这些字节都通过write(int c)方法被输出
2、介绍response.getWriter()和out的区别:
(1)、out和response.getWriter的类不一样,一个是JspWriter,另一个是java.io.PrintWriter。
(2)、执行原理不同:JspWriter相当于一个带缓存功能的printWriter,它不是直接将数据输出到页面,而是将数据刷新到response的缓冲区后再输出,
response.getWriter直接输出数据(response.print()),所以(out.print)只能在其后输出。
(3)、out为jsp的内置对象,刷新jsp页面,自动初始化获得out对象,所以使用out对象是需要刷新页面的,
而response.getWriter()响应信息通过out对象输出到网页上,当响应结束时它自动被关闭,与jsp页面无关,无需刷新页面
形象的比喻:当我们调用response.getWriter()这个对象同时获得了网页的画笔,这时你就可以通过这个画笔在网页上画任何你想要显示的东西。
(4)、out的print()方法和println()方法在缓冲区溢出并且没有自动刷新时候会产生ioexception,
而response.getWrite()方法的print和println中都是抑制ioexception异常的,不会有ioexception
out.println(""); 方法并不能使页面布局换行,只能使html代码换行,要实现页面布局换行可以:out.println("</br>");
后台向用户传送数据
用户从一个页面请求数据:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<a href="DataControler">request</a>
</body>
</html>
服务器处理请求并请求转发
package com.zparked.controler;
import java.io.IOException;
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;
@WebServlet("/DataControler")
public class DataControler extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data1 = "Hello";
String data2 = "world";
request.setAttribute("d1", data1);
HttpSession session = request.getSession();
session.setAttribute("d2", data2);
request.getRequestDispatcher("res.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
向用户返回数据
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%
String data1 = (String)request.getAttribute("d1");
String data2 = (String)session.getAttribute("d2");
%>
<%=data1 %>
<%=data2 %>
</body>
</html>
序列化
https://blog.csdn.net/jinyuancai/article/details/50848256
序列化(Serialize):用ObjectOutputStream类将一个Java对象写入IO流中
反序列化(Deserialize):用ObjectInputStream类从IO流中恢复该Java对象
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原。
序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
请注意,一个类的对象要想序列化成功,必须满足两个条件:
- 这个要被序列化的类必须实现 java.io.Serializable 接口
事实上,java.io.Serializable 接口没有任何java代码内容,它是一个
特殊的接口,JVM通过它来确认这个类的对象可以被序列化
2、要求此类中的属性同样是实现了Serializable接口的 注意:这两个条件任意没有实现的话,都会报java.io.NotSerializableException异常
3、提供一个版本号:private statis final long serialVersionUID
在这解析下使用这个版本号:
serialVersionUID用来表明类的不同版本间的兼容性
如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。
若类的源代码作了修改,serialVersionUID 可能发生变化。故建议,显示声明。
显示定义serialVersionUID的用途:
希望类的不同版本对序列化兼容,不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID
不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID
4、使用static或transient修饰的属性,不可实现序列化
将对象写到文件中
public class Dept implements Serializable{
private Integer deptno;
private String dname;
private String loc;
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public static void main(String[] args) throws IOException {
Dept dept = new Dept();
dept.setDeptno(10);
dept.setDname("zhangsan");
dept.setLoc("NewYork");
File file = new File("D:/abc.obj");//并没有创建文件
//装饰设计模式
OutputStream out = new FileOutputStream(file);//若没有文件该语句会自动创建文件
ObjectOutputStream oos = new ObjectOutputStream(out);//(java对象流
oos.writeObject(dept);//动态地为一个对象增加新的功能
oos.close();
}
装饰设计模式
https://www.cnblogs.com/zhangtianq/p/6091047.html
职责:动态的为一个对象增加新的功能
装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
验证码
https://www.cnblogs.com/boy1025/p/4250710.html
路径问题
1、页面中请求
href = "<%=request.getContextPath() %>/servlet/bank
2、请求转发
request.getRequestDispatcher("/main.jsp").forward(request, response);
request.getRequestDispatcher("../main.jsp").forward(request, response);
3、重定向
String contextPath = request.getContextPath();
response.sendRedirect(contextPath+"/login.jsp");
四层结构:
https://www.cnblogs.com/lesleysbw/p/6272716.html
MVC和三层结构:
https://www.cnblogs.com/whgk/p/6435300.html
http://www.360doc.com/content/16/0616/15/7014874_568276861.shtml
Dao设计模式
https://www.cnblogs.com/shici/p/7734047.html
JavaWeb面试题
http://www.cnblogs.com/darren0415/p/6040894.html
奇葩的NULL
https://www.aliyun.com/jiaocheng/170736.html
空指针异常的一般问题:
1.定义了一个对象引用,但是没有new 直接拿过来使用
2.没有考虑是否为空,直接获取或者返回;
PS:上述两种情况都因为一个引用指向null,然后又被使用导致空指针异常。
3.某行或某段代码需要从其他方法中获取结果,但是未获取成功导致应该有值的对象变量成为null,比如执行某 个SQL语句之后应该返回一些执行结果但是由于代码或者语句的错误导致没有查到相关的数据,引发了该问题。
EL表达式
https://www.cnblogs.com/xdp-gacl/p/3938361.html
EL主要作用:(有效的解决了空指针异常的问题)
${对象的引用 }不管对象的引用为不为空或有没有该引用都不会报错,只是什么都不显示罢了
1、获取数据
EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象、获取数据。(某个web域 中的对象,访问javabean的属性、访问list集合、访问map集合、访问数组)
2、执行运算
利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算。${user==null}
3、获取web开发常用对象
EL 表达式定义了一些隐式对象,利用这些隐式对象,web开发人员可以很轻松获得对web常用对象的引用,从而获得这些对象中的数据。
EL(Expression Language) 是为了使JSP写起来更加简单。
EL存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称为username的变量。
因为我们并没有指定哪一个范围的username,所以它会依序从Page、Request、Session、Application范围查找。
EL的内置对象
首先我们要知道 EL 的内置对象有哪些----pageScope、requestScope、sessionScope、applicationScope
1)从四个域中通过key找到简单数据并显示出来。表达式代码:
${name} <!-- 类比于<%=pageContext.getAttribute("name") %> -->
四个域的寻找顺序是 page,request,session,application。用EL表达式还有个好处,若找不到键值为name的属性值,不会显示null,会显示空字符串。
对象名 | 用法 | 等价JSP代码或作用 |
param | ${param.name} | request.getParameter(name) |
paramValues | ${paramValues.name} | request.getParameterValues(name)//返回一个字符串数组 |
header | ${header.name} | request.getHeader(name) |
headerValues | ${headerValues.name} | request.getHeaderValues(name) |
cookie | ${cookie.name.value} | request.getCookie() |
initParam | ${initParam.name} | ServletContext.getInitparameter(name) |
pageContext | ${pageContext.request.contextPath} | 获取WEB应用名 |
pageContext | ${pageContext.request.sessionid} | 获取sessionId |
pageContext | ${pageContext.request.remoteAddr} | 获取主机名 |
el表达式可以获取bean的属性
<!-- 在jsp页面中,使用el表达式可以获取bean的属性 -->
19 <%
20 Person p = new Person();
21 p.setAge(12);
22 request.setAttribute("person",p);
23 %>
24 使用el表达式可以获取bean的属性:${person.age}
JSTL
JSTL(JavaServer Pages Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。
在应用程序服务器之间提供了一致的接口,最大程度地提高了WEB应用在各应用服务器之间的移植。
1、什么是JSTL?
JSTL是apache对EL表达式的扩展(也就是说JSTL依赖EL),JSTL是标签语言!JSTL标签使用以来非常方便,它与JSP动作标签一样,只不过它不是JSP内置的标签,需要我们自己导包,以及指定标签库而已!
JSTL优点
a、在应用程序服务器之间提供了一致的接口,最大程度的提高了web应用在各应用服务器之间的移植。
b、简化了JSP和web应用程序的开发。
c、以一种统一的方式减少了JSP中scriptlet(脚本片段)代码数据,可以达到没有任何scriptlet代码的代码。在我们公司的项目中是不允许任何scriptlet出现在JSP中。
d、允许JSP设计工具与web应用程序开发的进一步集成。相信不久就会有支持JSTL的IDE开发工具出现。
使用taglib指令导入标签库:
除了JSP动作标签外,使用其他第三方的标签库都需要:
- 导包;
- 在使用标签的JSP页面中使用taglib指令导入标签库;
下面是导入JSTL的core标签库:
<%@ taglib prefix="c"uri="http://java.sun.com/jstl/core" %>
- prefix="c":指定标签库的前缀,这个前缀可以随便给值,但大家都会在使用core标签库时指定前缀为c;
- uri="http://java.sun.com/jstl/core":指定标签库的uri,它不一定是真实存在的网址,但它可以让JSP找到标签库的描述文件;
提高了WEB应用在各应用服务器之间的移植。
WEB应用:指的是你自己弄好的web工程,比如ssh2web;
WEB应用服务器:指的是运行JavaEE程序的容器,比如tomcat、Jboss、weblogic....
“在应用程序服务器之间提供了一致的接口,最大程度地提高了WEB应用在各应用服务器之间的移植”
意思是,你自己的jsp中一旦引用了标准的JSTL,那么这个工程发布到tomcat、Jboss或weblogic等服务器中,你的jsp都可以正常运行。
标准的JSTL就是JAVA EE规范中规定的,Servlet也是JavaEE规范的一种,严格来说,所有的应用服务器都应该完全支持JavaEE规范,包括标准的JSTL规范。
if标签:
if标签的test属性必须是一个boolean类型的值,如果test的值为true,那么执行if标签的内容,否则不执行。
- <c:set var="a" value="hello"/>
- <c:if test="${not empty a }">
- <c:out value="${a }"/>
- </c:if>
forEach标签:
forEach当前就是循环标签了,forEach标签有多种两种使用方式:
- 使用循环变量,指定开始和结束值,类似for(int i = 1; i <= 10; i++) {};
- 循环遍历集合,类似for(Object o : 集合);
循环变量:
- <c:set var="sum" value="0" />
- <c:forEach var="i" begin="1" end="10">
- <c:set var="sum" value="${sum + i}" />
- </c:forEach>
- <c:out value="sum = ${sum }"/>
- <c:set var="sum" value="0" />
- <c:forEach var="i" begin="1" end="10" step ="2">
- <c:set var="sum" value="${sum + i}" />
- </c:forEach>
- <c:out value="sum = ${sum }"/>
遍历集合或数组方式:
- <%
- String[] names = {"zhangSan", "liSi", "wangWu", "zhaoLiu"};
- pageContext.setAttribute("ns", names);
- %>
- <c:forEach var="item" items="${ns }">
- <c:out value="name: ${item }"/><br/>
- </c:forEach>
遍历List:
- <%
- List<String> names = new ArrayList<String>();
- names.add("zhangSan");
- names.add("liSi");
- names.add("wangWu");
- names.add("zhaoLiu");
- pageContext.setAttribute("ns", names);
- %>
- <c:forEach var="item" items="${ns }">
- ${item }<br/>
- </c:forEach>
遍历Map:
- <%
- Map<String,String> stu = new LinkedHashMap<String,String>();
- stu.put("number", "N_1001");
- stu.put("name", "zhangSan");
- stu.put("age", "23");
- stu.put("sex", "male");
- pageContext.setAttribute("stu", stu);
- %>
- <c:forEach var="item" items="${stu }">
- <c:out value="${item.key }: ${item.value }"/><br/>
- </c:forEach>
forEach标签还有一个属性:varStatus,这个属性用来指定接收“循环状态”的变量名,例如:<forEach varStatus=”vs” …/>,这时就可以使用vs这个变量来获取循环的状态了。
- count:int类型,当前以遍历元素的个数;
- index:int类型,当前元素的下标;
- first:boolean类型,是否为第一个元素;
- last:boolean类型,是否为最后一个元素;
- current:Object类型,表示当前项目。
- <c:forEach var="item" items="${ns }" varStatus="vs">
- <c:if test="${vs.first }">第一行:</c:if>
- <c:if test="${vs.last }">最后一行:</c:if>
- <c:out value="第${vs.count }行: "/>
- <c:out value="[${vs.index }]: "/>
- <c:out value="name: ${vs.current }"/><br/>
- </c:forEach>
JSP和Servlet的中文乱码处理
https://blog.csdn.net/longyuhome/article/details/7856270
Filter
Filter简介
过滤器是"链"在容器的处理过程中的。
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
二、Filter是如何实现拦截的?
Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
- 调用目标资源之前,让一段代码执行。
- 是否调用目标资源(即是否让用户访问web资源)。
- 调用目标资源之后,让一段代码执行。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对 象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方 法,即web资源就会被访问,否则web资源不会被访问。
三、过滤链的好处
过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前,这样才能确保在使用请求中的数据前设置正确的编码。
过滤器适用于那些地方?
1, 为一个web应用程序的新功能建立模型(可被添加到web应用程序中或者从web应用程序中删除而不需要重写基层应用程序代码);
2, 向过去的代码添加新功能。
与servlet的区别
Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应。 主要用于对HttpServletRequest 进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。 (检查和修改request和response的头和数据)
方法
创建Filter 必须实现javax.servlet.Filter 接口,在该接口中定义了三个方法。
•public void init(FilterConfig config)
web容器调用本方法,说明过滤器正被加载到web容器中去。容器只有在实例化过滤器时才会调用该方法一次。容器为这个方法传递一个FilterConfig对象,其中包含与Filter相关的配置信息。
• void destroy(): 用于Filter 销毁前,完成某些资源的回收。
• void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 实现过滤功能,该方法就是对每个请求及响应增加的额外处理。
参考网页:
https://blog.csdn.net/my98800/article/details/53940838
https://blog.csdn.net/lulidaitian/article/details/60766830
Servlet3.0新特性
https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/#major3
文件上传
https://www.cnblogs.com/xdp-gacl/p/4224960.html