JavaWeb知识汇总
- 一、Servlet
- 二、HTTP
- 1. HTTP协议简介
- 2.HTTPS
- 三、Request
- 四、Response
- 五、ServletContext
- 六、ServletConfig(了解)
- 七、Cookie和Session
- 1.会话技术
- 2.Cookie
- 3.Session
- 八、JSP
- 九、 EL &JSTL
- 1. EL表达式
- 2. JSTL
- 十、Filter
- 十一、Listener
- 十二、 MVC和三层架构
- 十三、Ajax
- 十四、JSON
- 1.jackson
- 2.Jsonlib
使用PC浏览,体验更加!!!!
一、Servlet
- 概念:servlet是一个在Web服务器中运行的小型Java程序。主要功能在于交互
式地浏览和修改数据,⽣成动态Web内容。
A servlet is a small Java program that runs within a Web server
- Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。
- 未来我们可以自定义一个类,实现Servlet接口,复写方法。
- 快速入门:
- 创建JavaEE项目
- 定义一个类,实现Servlet接口
public class ServletDemo1 implements Servlet - 实现接口中的抽象方法
- 配置Servlet
在web.xml中配置:
<!--配置Servlet -->
<servlet>
<servlet-name>demo1</servlet-name>
<!--全类名-->
<servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<!--资源路径-->
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
- 执行原理:
1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径。
2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。
3. 如果有,则在找到对应的<servlet-class>全类名。
4. tomcat会将对应的Servlet字节码文件加载进内存,并且创建其对象。
5. 调用其方法。
- Servlet生命周期
1. 当客户端⾸次发送第⼀次请求后,由容器(web服务器(tomcat))去解析请求。
2. 根据请求找到对应的servlet,判断该类的对象是否存在。
3. 不存在则创建servlet实例,调取init()⽅法 进⾏初始化操作。
4. 初始化完成后调取service()⽅法,由service()判断客户端的请求⽅式。
5. 如果是get,则执⾏doGet()。
6. 如果是post则执⾏doPost()。
7. 处理⽅法完成后,作出相应结果给客户端.单次请求处理完毕。
8. 当服务器关闭时调取destroy()⽅法进⾏销毁
对于同一个Servlet,当⽤户发送第2~n次请求时,不再执⾏init(),⽽直接执⾏service()⽅法,调取doGet()/doPost()⽅法。
- Servlet中的生命周期方法
1. 被创建:执行init()方法,只执行一次
Servlet什么时候被创建?
默认情况下,第一次被访问时,Servlet被创建。
通过web.xml文件,可以配置Servlet的创建时机。
在<servlet>标签下配置
1. 第一次被访问时,创建
<load-on-startup>的值为负数。
2. 在服务器启动时,创建
<load-on-startup>的值为0或正整数,
正数情况下,数值越⼩,加载该Servlet的优先级越⾼。
Servlet的init()方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
多个用户同时访问时,可能存在线程安全问题。
解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值
2. 提供服务:执行service()方法,执行多次
每次访问Servlet时,service()方法都会被调用一次。
3. 被销毁:执行destroy()方法,只执行一次
Servlet被销毁时执行。服务器关闭时,Servlet被销毁
只有服务器正常关闭时,才会执行destroy()方法。
destroy()方法在Servlet被销毁之前执行,一般用于释放资源
* Servlet3.0:
好处:
支持注解配置。可以不需要web.xml了。
步骤:
1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
2. 定义一个类,实现Servlet接口
3. 复写方法
4. 在类上使用@WebServlet注解,进行配置
* @WebServlet("资源路径")
示例:
@WebServlet(urlPatterns = {"/test"},
initParams ={
@WebInitParam(name = "code",value = "utf-8")
},loadOnStartup = 1)
public class TestServlet extends HttpServlet {}
关于@WebServlet的注解类如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
String name() default "";//相当于<Servlet-name>
String[] value() default {};//代表urlPatterns()属性配置
String[] urlPatterns() default {};//相当于<url-pattern>
int loadOnStartup() default -1;//相当于<load-on-startup>
WebInitParam[] initParams() default {};
boolean asyncSupported() default false;
String smallIcon() default "";
String largeIcon() default "";
String description() default "";
String displayName() default "";
}
- Servlet体系结构
Servlet -- 接口
|
GenericServlet -- 抽象类
|
HttpServlet -- 抽象类
* GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
* 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
* HttpServlet:对service()方法做了详细的实现,不再需要我们写代码判断用户的请求方式,对http协议的一种封装,简化操作
1. 定义类继承HttpServlet
2. 复写doGet/doPost方法
- Servlet相关配置
1. urlpartten:Servlet访问路径(资源路径)
1. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
2. 路径定义规则:
1. /xxx:路径匹配
2. /xxx/xxx:多层路径,目录结构
3. *.do:扩展名匹配
ps: /user/.do、/.do、test*.do都是非法的,启动时候会报错
二、HTTP
1. HTTP协议简介
- 概念:超⽂本传输协议(英⽂:HyperText Transfer Protocol,缩写:HTTP)是⼀种⽤于分布式、协作式和超媒体信息系统的应⽤层协议。HTTP是万维⽹的数据通信的基础。定义了客户端和服务器端通信时,交互报文的格式
- 特点:
1. 基于TCP/IP的高级协议
2. 默认端口号:80
3. 基于请求/响应模型的:一次请求对应一次响应
4. 在HTTP/1.0中默认使⽤短连接。也就是说,客户端和服务器每进⾏⼀次HTTP操作,就建⽴⼀次连接,任务结束就中断连接。
5. 无状态协议:HTTP协议自身不对请求和响应之间的通信状态进行保存。每次请求之间相互独立,不能交互数据。
6. HTTP/1.1起,默认使⽤⻓连接,⽤以保持连接特性。使⽤⻓连接的HTTP协议,会在响应头加⼊这⾏
代码:
Connection:keep-alive
- 在使⽤⻓连接的情况下,当⼀个⽹⻚打开完成后,客户端和服务器之间⽤于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使⽤这⼀条已经建⽴的连接。Keep-Alive不会永久保持连接,它有⼀个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现⻓连接需要客户端和服务端都⽀持⻓连接。
- 请求消息(报文)格式: 客户端发送给服务器端的数据
1. 请求行
请求方式 请求url 请求协议/版本
GET http://localhost:8080/thumbupTest/index.jsp HTTP/1.1
请求方式:
HTTP协议有7中请求方式,常用的有2种
GET:
1. 请求参数在请求行中,在url后。
2. 请求的url长度有限制的
3. 不太安全
POST:
1. 请求参数在请求体中
2. 请求的url长度没有限制的
3. 相对安全
2. 请求头:客户端浏览器告诉服务器一些信息
请求头名称: 请求头值
常见的请求头:
1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
2. Referer:http://localhost/login.html
告诉服务器,我(当前请求)从哪里来?
作用:
1. 防盗链:
通过条件判断指定从某条URL跳转过来到当前页面才正常显示
2. 统计工作:
可以统计从某个URL跳转到当前页面的用户数
3. 请求空行
空行,就是用于分割POST请求的请求头,和请求体的。
4. 请求体(正文):
封装POST请求消息的请求参数的
格式: username=zhangsan
* 字符串格式(请求头):
POST /login.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
- 响应消息(报文)格式: 服务器端发送给客户端的数据
数据格式:
1. 响应行
1. 组成:协议/版本 响应状态码 状态码描述
示例: HTTP/1.1 200 OK
2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
1. 状态码都是3位数字
2. 分类:
1. 1xx:服务器接收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
2. 2xx:成功。代表:200
3. 3xx:重定向。代表:302(重定向),304(访问缓存)
4. 4xx:客户端错误。
* 代表:
* 404(请求路径没有对应的资源)
* 405:请求方式没有对应的doXxx方法
5. 5xx:服务器端错误。代表:500(服务器内部出现异常)
2. 响应头:
1. 格式:头名称: 值
2. 常见的响应头:
1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
* 值:
* in-line:默认值,在当前页面内打开
* attachment;filename=xxx:以附件形式打开响应体。文件下载需设置此响应头
3. 响应空行
4. 响应体:传输的数据
5.
* 响应字符串格式
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 101
Date: Wed, 06 Jun 2018 07:08:42 GMT
<html>
<head>
<title>$Title$</title>
</head>
<body>
hello , response
</body>
</html>
- 常见状态码
状态码 | 状态码描述 | 含义 |
100 | Continue | 只有⼀部分请求被服务器接收,但只要没被服务器拒绝,客户端就会延续这个请求 |
101 | Switching Protocols | 服务器交换机协议 |
200 | OK | 请求被确认 |
201 | Created | 请求时完整的,新的资源被创建 |
202 | Accepted | 请求被接受,但未处理完 |
300 | Multiple Choices | ⼀个超链接表,⽤户可以选择⼀个超链接并访问,最⼤⽀持5个超链接 |
301 | Moved Permanently | 被请求的⻚⾯已经移动到了新的URL下 |
302 | Found | 被请求的⻚⾯暂时性地移动到了新的URL下 |
303 | See Other | 被请求的⻚⾯可以在⼀个不同的URL下找到 |
400 | Bad Request | 服务器⽆法识别请求 |
403 | Forbidden | 禁⽌访问所请求的⻚⾯ |
404 | Not Found | 服务器⽆法找到所请求的⻚⾯ |
405 | Method Not Allowed | 请求中所指定的⽅法不被允许 |
500 | Internal Server Error | 请求不完整,服务器遇⻅了出乎意料的状况 |
501 | Not Implemented | 请求不完整,服务器不提供所需要的功能 |
502 | Bad Gateway | 请求不完整,服务器从上游服务器接受了⼀个⽆效的响应 |
503 | Service Unavailable | 请求不完整,服务器暂时重启或关闭 |
504 | Gateway Timeout | ⽹关超时 |
505 | HTTP Version Not Supported | 服务器不⽀持所指定的HTTP版本 |
2.HTTPS
HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),
是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 。
HTTPS 在HTTP 的基础下加入SSL,HTTPS 的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP与 TCP 之间)。
这个系统提供了身份验证与加密通讯方法。
它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面。
- 详情请看 HTTPS
三、Request
- Request对象和Response对象的原理
1.客户端发送请求后,Tomcat服务器会根据请求URL中的资源路径(Servlet访问路径),创建对应的Servlet对象。
2. Tomcat服务器,会创建request和response对象,并将请求消息(请求报文)数据封装到request对象中。
3. Tomcat将request和response两个对象传递给service()方法,并且调用service()方法。
4. 后续,程序员可以通过request对象获取请求消息数据,通过response对象设置响应消息(响应报文)数据。
5. 服务器给浏览器作出响应之前会从response对象中获取程序员设置的响应消息数据。
- Request对象继承体系结构
ServletRequest -- 接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)
public class RequestFacade implements HttpServletRequest
- Request功能
1. 获取请求消息(报文)数据
1. 获取请求行数据
* GET http://localhost:8080/day14/demo1?name=zhangsan HTTP/1.1
* 方法:
1. 获取请求方式 :GET
* String getMethod()
2. (*)获取虚拟目录:/day14
* String getContextPath()
3. 获取Servlet路径: /demo1
* String getServletPath()
4. 获取get方式请求参数:name=zhangsan
* String getQueryString()
5. (*)获取请求URI:/day14/demo1
* String getRequestURI(): /day14/demo1
* StringBuffer getRequestURL() :http://localhost/day14/demo1
* URL:统一资源定位符 : http://localhost/day14/demo1 例如:中华人民共和国
* URI:统一资源标识符 : /day14/demo1 例如:共和国
6. 获取协议及版本:HTTP/1.1
* String getProtocol()
7. 获取客户机的IP地址:
* String getRemoteAddr() // 0:0:0:0:0:0:0:1
2. 获取请求头数据
* 方法:
* (*)String getHeader(String name):通过请求头的名称获取请求头的值
* Enumeration<String> getHeaderNames():获取所有的请求头名称
3. 获取请求体(正文)数据:
* 请求体:只有POST请求方式,才有请求体,在请求体(正文)中封装了POST请求的请求参数
* 步骤:
1. 获取流对象
* BufferedReader getReader():获取字符输入流,只能操作字符数据
* ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
2. 再从流对象中拿数据
2. 其他功能:
1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
1. String getParameter(String name):根据参数名称获取参数值 username=zs&password=123
2. String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game
3. Enumeration<String> getParameterNames():获取所有请求的参数名称
4. Map<String,String[]> getParameterMap():获取所有参数的map集合
* 中文乱码问题:
* get方式:tomcat 8 已经将get方式乱码问题解决了
* Tomcat 8以前:
⽅式1:
//针对于get提交时中⽂乱码
String s=new String(请求参数.getBytes("ISO-8859-1"),"UTF-8");
示例:
String s=new String(request.getParameter("key").getBytes("ISO-8859-1"),"GBK");
⽅式2:修改tomcat中配置⽂件:
//使⽤于get提交在Tomcat⽬录结构\conf\server.xml中设置字符集 URLEncoding
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" />
* post方式:会乱码
* 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");
2. 请求转发:一种在服务器内部的资源跳转方式
1. 步骤:
1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
2. 特点:
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求,可以使用request对象来共享数据
3. 共享数据:
* 域对象:一个有作用范围的对象,可以在范围内共享数据
* request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
* 方法:
1. void setAttribute(String name,Object obj):存储数据
2. Object getAttitude(String name):通过键获取值
3. void removeAttribute(String name):通过键移除键值对
4. 获取ServletContext:
* ServletContext getServletContext()
- GET和POST的区别
1、GET请求:请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数⽤&连接。
URL的编码格式采⽤的是ASCII编码,而不是uniclde,
即是说所有的非ASCII字符都要编码之后再传输。
POST请求:请求的数据放在请求消息(报文)的请求体(正文)中。
因此,GET请求的数据会暴露在地址栏中,⽽POST请求则不会。
2、传输数据的大小
在HTTP规范中,没有对URL的⻓度和传输的数据⼤⼩进⾏限制。
但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的⻓度有限制。
因此,在使⽤GET请求时,传输数据会受到URL⻓度的限制。
对于POST,由于不是URL传值,理论上是不会受限制的,
但是实际上各个服务器会规定对POST提交数据⼤⼩进⾏限制,
Apache、IIS都有各⾃的配置。
3、安全性
POST的安全性比GET的相对较⾼。
四、Response
- 功能: 设置响应消息
1. 设置响应行
1. 格式:HTTP/1.1 200 ok
2. 设置状态码:setStatus(int sc)
2. 设置响应头:setHeader(String name, String value)
添加响应头:void addHeader(String name, String value) //两者作用一致
3. 设置响应体:
* 使用步骤:
1. 获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream()
2. 使用输出流,将数据输出到客户端浏览器
- 案例
1. 完成重定向
* 重定向:资源跳转的方式
* 代码实现:
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/day15/responseDemo2");
//简单的重定向方法
response.sendRedirect("/day15/responseDemo2");
* forward 和 redirect 区别
* 重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据
* 转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据
2. 服务器输出字符数据到浏览器
* 步骤:
1. 获取字符输出流
2. 输出数据
* 注意:
* 乱码问题:
1. PrintWriter pw = response.getWriter();
获取的流的默认编码是ISO-8859-1
2. 设置该流的默认编码
response.setHeader("content-type","text/htm;charset=utf-8")
告诉浏览器响应体所使用的编码
//简单的形式,设置编码,是在获取流之前设置
response.setContentType("text/html;charset=utf-8");
3. 服务器输出字节数据到浏览器
* 步骤:
1. 获取字节输出流 ServletOutputStream getOutputStream()
2. 输出数据
- 路径写法
1. 路径分类
1. 相对路径:通过相对路径不可以确定唯一资源
* 如:./index.html 或者 servletDemo1
* 不以/开头、以.开头路径
* 规则:找到当前资源和目标资源之间的相对位置关系
* ./:当前目录
* ../:后退一级目录
2. 绝对路径:通过绝对路径可以确定唯一资源
* 如:http://localhost/day15/responseDemo2 /day15/responseDemo2
* 以/开头的路径
* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
* 建议虚拟目录动态获取:request.getContextPath()
*如 <a> , <form> 标签重定向到某个页面
* 给服务器使用:不需要加虚拟目录,使用相对路径即可
* 转发路径
五、ServletContext
- 概念:ServletContext是javax.servlet包内定义的接口,Web容器会为每个Web程序构造一个实现该接口的对象实例,代表整个web应用,Servlet可以和web容器(服务器)进行交互
- 获取:
- 通过request对象获取
request.getServletContext(); - 通过HttpServlet获取
this.getServletContext();
- 功能:
- 获取MIME类型:
- MIME类型:在互联网通信过程中定义的一种文件数据类型
- 格式: 大类型/小类型 text/html image/jpeg
- 获取:String getMimeType(String file)
- 域对象:共享数据
- void setAttribute(String name,Object value)
- Object getAttribute(String name)
- void removeAttribute(String name)
// ServletContext对象范围:所有用户所有请求的数据
- 获取文件的真实(服务器)路径
- 方法:String getRealPath(String path)
String b = context.getRealPath("/b.txt");//web目录下资源访问
System.out.println(b);
String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
System.out.println(c );
String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
System.out.println(a);
六、ServletConfig(了解)
- 概述
ServletConfig是用来获得Servlet相关的配置的对象
- 获取
通过当前Servlet实例来获取
ServletConfig config = this.getServletConfig();
- 功能
- 获取ServletContext对象
* ServletContext getServletContext(); - 获取当前Servlet的初始化参数
* String getInitParameter(String name) - 获取当前Servlet的所有初始化参数的名称
* Enumeration getInitParameterNames() - 获取当前Servlet实例的名称
* String getServletName()
- Servlet初始化参数
- 针对某个Servlet的初始化参数
实现⽅式:
(1) web.xml中先定义初始化参数
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
(2) 注解方式实现 initParams
@WebServlet(urlPatterns = {"/test"},
initParams ={
@WebInitParam(name = "code",value = "utf-8")
})
public class TestServlet extends HttpServlet {}
*获取:
String encode = this.getServletConfig().getInitParameter("encoding");
2.对于当前web程序中所有的Servlet都有效的初始化参数
(1)定义
<context-param>
<param-name>forAll</param-name>
<param-value>utf-8</param-value>
</context-param>
(2)获取
this.getServletConfig().getServletContext().getInitParameter("forAll");
七、Cookie和Session
1.会话技术
- 会话:会话跟踪是Web程序中常⽤的技术,⽤来跟踪⽤户的整个会话。保持对⽤户会话期间的数据管理。常⽤的会话跟踪技术是Cookie与Session。一次会话中包含多次请求和响应。
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
- 功能:在一次会话的范围内的多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
2.Cookie
- 概念
Cookie是客户端(⼀般指浏览器)请求服务器后,服务器发给客户端的⼀个辨认标识,保存在客户端,当客户端再次向服务器发送请求时,会携带着这个辨认标识,服务器就可以通过这个标识来识别客户端的身份或状态等。 - Cookie的设置和获取
- 使用步骤:
1. 创建Cookie对象,绑定数据
* new Cookie(String name, String value)
2. 发送Cookie对象
* response.addCookie(Cookie cookie)
3. 获取Cookie,拿到数据
* Cookie[] request.getCookies()
*
* 示例:
* Cookie[] cs = request.getCookies();
* // 通过遍历获取各个cookie的值
for (Cookie c : cs) {
String name = c.getName(); //获取cookie的名称
String value = c.getValue();//获取cookie的值
}
- 实现原理
- 基于响应头set-cookie和请求头cookie实现。
- 客户端请求服务器中发送cookie的Servlet,服务器设置set-cookie: msg = hello头发送到客户端浏览器。
- 浏览器将msg = hello保存到本地cookie中,后续的请求都会通过请求头Cookie携带此客户端的cookie数据,服务器可以获取cookie进行相应的操作
- 细节
- 一次可不可以发送多个cookie?
* 可以
* 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。- cookie在浏览器中保存多长时间?
1. 默认情况下,当浏览器关闭后,Cookie数据被销毁
2. 持久化存储:
* setMaxAge(int seconds)
(1)正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
(2)负数:默认值
(3)零:删除cookie信息- cookie能不能存中文?
* 在tomcat 8 之前 cookie中不能直接存储中文数据。
* 需要将中文数据转码—一般采用URL编码(%E3)
* 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析- cookie共享问题?
1. 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
* 默认情况下cookie不能共享。
* setPath(String path):设置cookie的获取范围。默认情况下,被设置为当前的虚拟目录
* 如果要共享,则可以将path设置为"/"
~
2. 不同的tomcat服务器间cookie共享问题?
* setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
* setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享。- Cookie的特点和作用
* 特点
1. cookie存储数据在客户端浏览器
2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制,不同浏览器对于cookie的数量限制不同。
* 作用:
1. cookie一般用于存出少量的不太敏感的数据
2. 在不登录的情况下,完成服务器对客户端的身份识别
3.Session
- 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
- 快速入门:
- 获取HttpSession对象:
HttpSession session = request.getSession(); - 使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
- 原理
- Session的实现是依赖于Cookie的。
- 第一次获取Session,没有Cookie,服务器会在内存中创建一个新的Session对象,假设其对应的Id属性值为 ID = 742938a4289。
- 服务器会自动设置响应头set-cookie:JSESSIONID= 742938a4289响应消息给浏览器。
- 浏览器解析set-cookie响应头,将JSESSIONID=742938a4289存入Cookie请求头。
- 后续服务器再次创建Session对象时会根据请求头Cookie中的JSESSIONID先在内存中寻找对应的session实例,然后返回其引用。
- 细节:
1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
* 默认情况下。不是。
* 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让 cookie持久化保存。
Cookie c = new Cookie(“JSESSIONID”,session.getId());
c.setMaxAge(60*60); //单位:秒
response.addCookie(c );
2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
* 不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
* session的钝化:
* 在服务器正常关闭之前,将session对象序列化到硬盘上
* session的活化:
* 在服务器启动后,将session文件转化为内存中的session对象即可。
- session什么时候被销毁?
1. 本地服务器正常关闭后不会被销毁,idea上配置的tomcat服务器关闭后会被销毁
2. session对象调用invalidate() 。
3. session默认失效时间 30分钟
* Session的超时时间为maxInactiveInterval属性,可以通过对应的 getMaxInactiveInterval()获取,通过 setMaxInactiveInterval(longinterval)修改
* 还可以在config目录下的web.xml中选择性配置修改
<session-config>
<session-timeout>30</session-timeout>
</session-config>
4.浏览器中含有JSESSIONID的cookie被销毁时,服务器会重新创建一个新的session对象,原有的session对象会在失效时间过后被销毁。
- session的特点
- session用于存储一次会话的多次请求的数据,存在服务器端。
- 为了获得更⾼的存取速度,服务器⼀般把Session放在内存⾥。
- session可以存储任意类型,任意大小的数据
什么时候创建Session?
1.Session在⽤户第⼀次访问page指令中的session属性值不为false的JSP页面时被创建。
2.若servelt是第浏览器客户端访问的第一个WEB应用的资源,则只有调用了request.getSession()或request.getSession(true)才会创建session对象。其中request.getSession(boolean),
boolean为false时,若没有和当前JSP页面关联的session对象则返回null,若有,则返回true。
Boolean为true时,一定返回一个session对象,若没有和当前JSP页面关联的session对象,则服务器创建一个新的session对象,若有,直接返回。
request.getSession()等同于request.getSession(true)。
- session与Cookie的区别:
1. session存储数据在服务器端,Cookie在客户端。
2. session没有数据大小限制,Cookie有,一般为4KB。
3. session数据安全,Cookie相对于不安全。
4. Session是由应⽤服务器维持的⼀个服务器端的存储空间,⽤户在连接服务器时,会由服务器⽣成⼀个唯⼀的SessionID,⽤该SessionID 为标识符来存取服务器端的Session存储空间。⽽SessionID这⼀数据则是保存到客户端,⽤Cookie保存的,⽤户提交⻚⾯时,会将这⼀SessionID提交到服务器端,来存取Session数据。这⼀过程,是不⽤开发⼈员⼲预的。所以⼀旦客户端禁⽤Cookie,那么Session也会失效。
八、JSP
1. 概念:
* Java Server Pages: java服务器端页面
* 可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
* 用于简化书写!!!
2. 原理
* JSP本质上就是一个Servlet,当浏览器访问http://localhost:8080/day9_1/index.jsp。服务器发现后缀为.jsp,它会根据路径找到index.jsp⽂件,会将index.jsp翻译成index_jsp.java⽂件,对这个java⽂件进⾏编译,产⽣⼀个index_jsp.class⽂件,将class⽂件加载运⾏。将JSP翻译成java⽂件,它是将JSP中的所有的HTML代码通过流进⾏输出,也就是说最终翻译成class,被虚拟机加载,它本质是servlet,它就会往回响应,响应回去就是把JSP中的HTML代码以流的⽅式写回浏览器。所以在JSP中展示出了HTML代码。
3. JSP指令
- 作用:用于配置JSP页面,导入资源文件
- 格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %>
- 分类:
1. page :
- contentType: 配置JSP页面的 contentType属性:等同于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
- import:导包
- errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
- isErrorPage:标识当前也是是否是错误页面。
- true:是,可以使用内置对象exception <% String message = exception.getMessage(); %>
- false:否。默认值。不可以使用内置对象exception
page 指令相关属性:
- include : JSP可以通过include指令来包含其他⽂件。被包含的⽂件可以是JSP⽂件、HTML⽂件或⽂本⽂件。包含的⽂件就好像是该JSP⽂件的⼀部分,会被同时编译执⾏。
<%@ include file=“⽂件相对 url 地址” %> - taglib : 导入资源(引入jsp标签库)
- <%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
- prefix:前缀,自定义的
- 注释:
1. html注释:
<!-- -->:只能注释html代码片段
2. jsp注释:推荐使用
<%-- --%>:可以注释所有
4. JSP的脚本: JSP定义Java代码的方式
1. <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
2. <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。
3. <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
5. JSP的内置对象:
* 在jsp页面中不需要获取和创建,可以直接使用的对象
* jsp一共有9个内置对象。
变量名 | 真实类型 | 作用 |
pageContext | PageContext | 当前页面共享数据,还可以获取其他八个内置对象 |
request | HttpServletRequest | 一次请求访问的多个资源(转发)间共享数据。 |
session | HttpSession | 一次会话的多个请求间共享数据 |
application | ServletContext | 所有用户间共享数据 |
response | HttpServletResponse | response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。只在JSP⻚⾯内有效。 |
page | Object | 当前页面(Servlet)的对象,类似于this |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | 主要作⽤是取得服务器的配置信息。通过 pageConext对象的 getServletConfig() ⽅法可以获取⼀个config对象。当⼀个Servlet 初始化时,容器把某些信息通过config对象传递给这个Servlet。 开发者可以在web.xml ⽂件中为应⽤程序环境中的Servlet程序和JSP⻚⾯提供初始化参数。 |
exception | Throwable | exception 对象的作⽤是显示异常信息,只有在包含 isErrorPage=“true” 的⻚⾯中才可以被使⽤,通常用于打印错误信息输出到日志文件,exception.getMessage() |
- out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
* response.getWriter()和out.write()的区别:
* 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
* response.getWriter()数据输出永远在out.write()之前。
九、 EL &JSTL
1. EL表达式
- 概念:Expression Language 表达式语言
- 作用:替换和简化jsp页面中java代码的编写
- 语法:${表达式}
- 注意:
- jsp默认支持el表达式的。如果要忽略el表达式
- 设置jsp中page指令中:isELIgnored=“true” 忽略当前jsp页面中所有的el表达式
- ${表达式} :忽略当前这个el表达式
- 使用:
- 运算:
- 运算符:
- 算数运算符: + - * /(div) %(mod)
${30 + 40}
${20 div 5} - 比较运算符: > < >= <= == !=
- 逻辑运算符: &&(and) ||(or) !(not)
- 空运算符: empty
- 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
- ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
- ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
- 获取值
- el表达式只能从域对象中获取值
- 语法:
- ${域名称.键名}:从指定域中获取指定键的值
- 域名称:
- pageScope --> pageContext
- requestScope --> request
- sessionScope --> session
- applicationScope --> application(ServletContext)
- 举例:在request域中存储了name=张三
- 获取:${requestScope.name}
- ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
- 获取对象、List集合、Map集合的值
- 对象:${域名称.键名.属性名}
- 本质上会去调用对象的getter方法
- List集合:${域名称.键名[索引]}
- 索引越界会返回空字符
- Map集合:
- ${域名称.键名.key名称}
- ${域名称.键名[“key名称”]}
- 隐式对象:
* el表达式中有11个隐式对象
* pageScope
* requestScope
* sessionScope
* applicationScope
* pageContext:
* 获取jsp其他八个内置对象
* ${pageContext.request.contextPath}:动态获取虚拟目录
2. JSTL
(1) 什么是JSTL
JSP标准标签库(JSTL)是⼀个JSP标签集合,它封装了JSP应⽤的通⽤核⼼功能。
JSTL⽀持通⽤的、结构化的任务,⽐如迭代,条件判断,XML⽂档操作,国际化标签,SQL标签。 除了这些,它还提供了⼀个框架来使⽤集成JSTL的⾃定义标签。
根据JSTL标签所提供的功能,可以将其分为5个类别。核⼼标签 格式化标签 sql标签 xml标签 jstl函数(后⾯详细解释)
(2) JSTL的作⽤和语法格式
作⽤:用于简化和替换jsp页面上的java代码
语法格式:
- 下载 jakarta-taglibs-standard-1.1.2.zip 包并解压,将 jakarta-taglibs-standard-1.1.2/lib/ 下的两
个 jar ⽂件:standard.jar 和 jstl.jar ⽂件拷⻉到 /WEB-INF/lib/ 下。 - 在JSP⻚⾯中引⼊<%@ taglib prefix=”⻚⾯使⽤的名称” uri=”功能范围的路径”%>
- 常用的JSTL标签
- 核⼼标签
核⼼标签是最常⽤的 JSTL标签。引⽤核⼼标签库的语法如下:
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
- if:相当于java代码的if语句
- 属性:
- test 必须属性,接受boolean表达式
- 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
- 一般情况下,test属性值会结合el表达式一起使用
- 注意:
- c:if标签没有else情况,想要else情况,则可以再定义一个c:if标签
- choose:相当于java代码的switch语句
- 使用choose标签声明 相当于switch声明
- 使用when标签做判断 相当于case
- 使用otherwise标签做其他情况的声明 相当于default
- foreach:相当于java代码的for语句
代码案例:
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>if标签</title>
</head>
<body>
<%--
c:if标签
1. 属性:
* test 必须属性,接受boolean表达式
* 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
* 一般情况下,test属性值会结合el表达式一起使用
2. 注意:c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
--%>
<c:if test="true">
<h1>我是真...</h1>
</c:if>
<br>
<%
//判断request域中的一个list集合是否为空,如果不为null则显示遍历集合
List list = new ArrayList();
list.add("aaaa");
request.setAttribute("list",list);
request.setAttribute("number",4);
%>
<c:if test="${not empty list}">
遍历集合...
</c:if>
<br>
<c:if test="${number % 2 != 0}">
${number}为奇数
</c:if>
<c:if test="${number % 2 == 0}">
${number}为偶数
</c:if>
</body>
</html>
代码案例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>choose标签</title>
</head>
<body>
<%--
完成数字编号对应星期几案例
1.域中存储一数字
2.使用choose标签取出数字 相当于switch声明
3.使用when标签做数字判断 相当于case
4.otherwise标签做其他情况的声明 相当于default
--%>
<%
request.setAttribute("number",51);
%>
<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>
代码案例:
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<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:容器对象
var:容器中元素的临时变量
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环次数,从1开始
--%>
<c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
${i} <h3>${s.index}<h3> <h4> ${s.count} </h4><br>
</c:forEach>
<hr>
<%
List 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>
- 格式化标签
1、fmt:formatDate 作⽤:将⽇期类型格式化为指定模式的字符串
属性
value:将要被格式化的数据
pattern:格式化的模式,与SimpleDateFormat的参数设置⼀样
var:格式化后的字符串所要存放的变量,若不指定var,则会将格式化的结果直接显示在⻚⾯
scope:变量存放的域属性空间,默认page
type:其取值为date、time、both,表示给出的value是⽇期、时间、还是两者都包含,默认是date
代码案例:
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
pageContext.setAttribute("mytime",new Date());
%>
date=<fmt:formatDate value="${mytime}" pattern="yyyy-MM-dd"></fmt:formatDate>
</body>
</html>
十、Filter
- 概念:
- 生活中的过滤器:净水器,空气净化器,土匪、
- web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
- 过滤器的作用:
- 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…
- 快速入门:
- 步骤:
- 定义一个类,实现接口Filter
- 复写方法
- 配置拦截路径
- web.xml
- 注解
- 代码:
@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo1被执行了....");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
- 过滤器细节:
- web.xml配置
demo1
cn.itcast.web.filter.FilterDemo1
demo1
/* - 过滤器执行流程
- 执行过滤器
- 执行放行后的资源
- 回来执行过滤器放行代码下边的代码
- 过滤器生命周期方法
- init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
- doFilter:每一次请求被拦截资源时,会执行。执行多次
- destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
- 过滤器配置详解
- 拦截路径配置:
- 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
- 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
- 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
- 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
- 拦截方式配置:资源被访问的方式
- 注解配置:
- 设置dispatcherTypes属性
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
//浏览器直接请求index.jsp资源时,该过滤器会被执行
//@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
//只有转发访问index.jsp时,该过滤器才会被执行
//@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
//浏览器直接请求index.jsp或者转发访问index.jsp。该过滤器才会被执行
//@WebFilter(value="/*",dispatcherTypes ={ DispatcherType.FORWARD,DispatcherType.REQUEST})
- web.xml配置
设置<dispatcher></dispatcher>标签即可
如:
<filter-mapping>
<filter-name>demo1</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
- 过滤器链(配置多个过滤器)
- 执行顺序:如果有两个过滤器:过滤器1和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
- 过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
- 如: AFilter 和 BFilter,AFilter就先执行了。
- web.xml配置:
<filter-mapping>谁定义在上边,谁先执行
- 使⽤场景
1.如何防⽌⽤户未登录就执⾏后续操作
String name=(String)session.getAttribute(“key”);
if(name==null){
//跳转到登录⻚⾯
}
2.设置编码⽅式–统⼀设置编码
3.加密解密(密码的加密和解密)
4.⾮法⽂字筛选
5.下载资源的限制
过滤器的特点:在servlet之前和之后都会被执⾏
十一、Listener
1.什么是监听器
监听器就是监听某个域对象的的状态变化的组件
监听器的相关概念:
事件源:被监听的对象(三个域对象 request、session、servletContext)
监听器:监听事件源对象事件源对象的状态的变化都会触发监听器
注册监听器:将监听器与事件源、事件进⾏绑定。事件源上发生某个事件后,执行监听器代码
响应⾏为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)
- ServletContextListener:监听ServletContext对象的创建和销毁
- 方法:
- void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
- void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法
- 步骤:
- 定义一个类,实现ServletContextListener接口
- 复写方法
- 配置
1. web.xml
<listener>
<!-- 监听器所在的路径 -->
<listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class>
</listener>
2. 注解:
* @WebListener
2.监听器分类
3.监听三⼤域对象的创建与销毁的监听器
- ServletContextListener
监听ServletContext域的创建与销毁的监听器
Servlet域的⽣命周期
何时创建:服务器启动创建
何时销毁:服务器关闭销毁
ServletContextListener监听器的主要作⽤
初始化的⼯作:初始化对象、初始化数据(加载数据库驱动、连接池的初始化)
加载⼀些初始化的配置⽂件(spring的配置⽂件)
任务调度(定时器—Timer/TimerTask) - HttpSessionListener
监听Httpsession域的创建和销毁的监听器
HttpSession对象的⽣命周期
何时创建:第⼀次调⽤request.getSession时创建
何时销毁:服务器关闭销毁、session过期(默认30分钟,修改默认的30分钟是在
Tomcat的web.xml,修改当前项⽬的过期时间是在⾃⼰项⽬的web.xml中)、⼿动销毁
HttpSessionListener监听器的主要作⽤:
由于每次访问⽹站都会默认创建session对象(jsp⻚⾯中page指令中的session属性默认为
true,即被访问时创建session),可以⽤于计数⽹站访问过的⼈ - ServletRequestListener
监听ServletRequest域创建与销毁的监听器
ServletRequest的⽣命周期
创建:每⼀次请求都会创建request
销毁:请求结束
⽤法同上,⽤处不是很⼤,此处省略。
十二、 MVC和三层架构
1.MVC设计模式
- jsp演变历史
- 早期只有servlet,只能使用response输出标签数据,非常麻烦
- 后来又jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表,造成难于维护,难于分工协作
- 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性
- MVC:
- M:Model,模型。JavaBean
- 完成具体的业务操作,如:查询数据库,封装对象
- V:View,视图。JSP
- 展示数据
- C:Controller,控制器。Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
- 优缺点:
1. 优点:
1. 耦合性低,方便维护,可以利于分工协作
2. 重用性高
2. 缺点:
1. 使得项目架构变得复杂,对开发人员要求高
JavaBeans :是Java中⼀种特殊的类(换⾔之:JavaBean就是⼀个Java类).
⼀个Java类 ,满⾜以下要求,则可称为⼀个JavaBean
a. public修饰的类,提供public ⽆参构造⽅法
b. 所有属性 都是private
C. 提供getter和setter⽅法
从使⽤层⾯来看,JavaBean分为2⼤类:
a. 封装业务逻辑的JavaBean(eg:LoginDao.java 封装了登录逻辑)
b. 封装数据的JavaBean(实体类:eg:Student.java Vadio.java 。往往对应于数据库中的⼀张
表,即数据库中有个Student表,项⽬中就有个Student.java类)通常:表名=类名,列名=属性名
JavaBean是⼀个可以重复使⽤的组件,通过编写⼀个组件来实现某种通⽤功能,“⼀次编写、任何地⽅执⾏、任何地⽅重⽤”。
2.三层架构
三层架构 通常意义上的三层架构就是将整个业务应⽤划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的⽬的即为了“⾼内聚,低耦合”的思想。
1、表现层(UI):通俗讲就是展现给⽤户的界⾯,即⽤户在使⽤⼀个系统的时候他的所⻅所得。
jsp/html
2、业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。
servlet,service
3、数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找
等。dao
表现层实现的代表作品是Struts,springmvc框架,
业务层实现的代表作品是Spring,
持久层实现的代表作品是Hibernate,mybatis。
层就相当于⼀个⿊盒⼦,我们不⽤知道它内部怎么实现,只需要知道如何去调⽤它就⾏了。每层只与上下相邻的两层打交道。当⼀层内部由于技术变迁发⽣变化时,只要接⼝不变,其他层不⽤做任何改变。分层之后灵活性提⾼,也便于团队分⼯开发。
3.三层架构和MVC的区别与联系
MVC可以是三层中的⼀个表现层框架,属于表现层。三层和mvc可以共存。
三层是基于业务逻辑来分的,⽽MVC是基于⻚⾯来分的。
MVC主要⽤于表现层,3层主要⽤于体系架构,3层⼀般是表现层、中间层、数据层,其中表现层⼜可以分成M、V、C,(Model View Controller)模型-视图-控制器
MVC是表现模式(Presentation Pattern)
三层架构是典型的架构模式(Architecture Pattern)
三层架构的分层模式是典型的上下关系,上层依赖于下层。但MVC作为表现模式是不存在上下关系的,⽽是相互协作关系。即使将MVC当作架构模式,也不是分层模式。MVC和三层架构基本没有可⽐性,是应⽤于不同领域的技术。
十三、Ajax
1. 概念: ASynchronous JavaScript And XML 异步的JavaScript 和 XML
Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。
功能:提升用户的体验
异步和同步:客户端和服务器端相互通信的基础上
* 同步: 客户端必须等待服务器端的响应。在等待的期间客户端不能做其他操作。
* 异步:客户端不需要等待服务器端的响应。在服务器处理请求的过程中,客户端可以进行其他的操作。
* 浏览器的普通交互⽅式(同步)
2.工作原理:
1.客户端浏览器发送JS请求Ajax引擎。
2.Ajax将JS请求转换成HTTP请求。
3.服务器对接收到的数据进行处理。
4.服务器返回XML、JSON或文本文档类型的数据给Ajax引擎。
5.AJax引擎接收服务器返回的数据进行渲染。
3. 实现方式:
(1)原生的JS实现方式(了解)
AJAX 的核⼼是 XMLHttpRequest 对象。
不同的浏览器创建 XMLHttpRequest 对象的⽅法是有差异的。
IE 6及以下浏览器使⽤ ActiveXObject,⽽其他的浏览器使⽤名为 XMLHttpRequest 的 JavaScript 内建对象
//1.创建核心对象
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//2. 建立连接
/*
参数:
1. 请求方式:GET、POST
* get方式,请求参数在URL后边拼接。send方法为空参
* post方式,请求参数在send方法中定义
2. 请求的URL:
3. 同步或异步请求:true(异步)或 false(同步)
*/
xmlhttp.open("GET","ajaxServlet?username=tom",true);
//3.发送请求
xmlhttp.send();
//4.接受并处理来自服务器的响应结果
//获取方式 :xmlhttp.responseText
//什么时候获取?当服务器响应成功后再获取
//当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。
xmlhttp.onreadystatechange=function()
{
//判断readyState就绪状态是否为4,判断status响应状态码是否为200
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//获取服务器的响应结果
var responseText = xmlhttp.responseText;
alert(responseText);
}
}
- XMLHttpRequest常⽤属性
- onreadystatechange 属性
onreadystatechange 属性存有处理服务器响应的函数。
xmlHttp.onreadystatechange = function() { }
- readyState 属性
readyState 属性存有服务器响应的状态信息。每当 readyState 改变时,onreadystatechange 函数就会
被执⾏。
readyState 属性可能的值: - responseText 属性
可以通过 responseText 属性来取回由服务器返回的数据。
AJAX状态码说明
1xx:请求收到,继续处理
2xx:操作成功收到,分析、接受
3xx:完成此请求必须进⼀步处理
4xx:请求包含⼀个错误语法或不能完成
5xx:服务器执⾏⼀个 完全有效请求 失败
再具体就如下:
100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本
200——交易成功
201——提示知道新⽂件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204——请求收到,但返回信息为空
205——服务器完成了请求,⽤户代理必须复位当前已经浏览过的⽂件
206——服务器已经完成了部分⽤户的GET请求
300——请求的资源可在多处得到
301——删除请求数据
302——在其他地址发现了请求数据
303——建议客户访问其他URL或访问⽅式
304——客户端已经执⾏了GET,但⽂件未变化
305——请求的资源必须从服务器指定的地址得到
306——前⼀版本HTTP中使⽤的代码,现⾏版本中不再使⽤
307——申明请求的资源临时性删除
400——错误请求,如语法错误
401——请求授权失败
402——保留有效ChargeTo头响应
403——请求不允许
404——没有发现⽂件、查询或URl
405——⽤户在Request-Line字段定义的⽅法不允许
406——根据⽤户发送的Accept拖,请求资源不可访问
407——类似401,⽤户必须⾸先在代理服务器上得到授权
408——客户端没有在⽤户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且⽆进⼀步的参考地址
411——服务器拒绝⽤户定义的Content-Length属性请求
412——⼀个或多个请求头字段在当前请求中错误
413——请求的资源⼤于服务器允许的⼤⼩
414——请求的资源URL⻓于服务器允许的⻓度
415——请求资源不⽀持请求项⽬格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含IfRange请求头字段
417——服务器不满⾜请求Expect头字段指定的期望值,如果是代理服务器,可能是下⼀级服务器不能
满⾜请求
500——服务器产⽣内部错误
501——服务器不⽀持请求的函数
502——服务器暂时不可⽤,有时是为了防⽌发⽣系统过载
503——服务器过载或暂停维修
504——关⼝过载,服务器使⽤另⼀个关⼝或服务来响应⽤户,等待时间设定值较⻓
505——服务器不⽀持或拒绝⽀请求头中指定的HTTP版本
(2).JQeury实现方式
1. $.ajax()
* 语法:$.ajax({键值对});
//使用$.ajax()发送异步请求
$.ajax({
url:"ajaxServlet1111" , // 请求路径
type:"POST" , //请求方式
//data: "username=jack&age=23",//请求参数
data:{"username":"jack","age":23},
success:function (data) {
alert(data);
},//响应成功后的回调函数
error:function () {
alert("出错啦...")
},//表示如果请求响应出现错误,会执行的回调函数
dataType:"text"//设置接受到的响应数据的格式(预期服务器返回的数据类型)
});
2. $.get():发送get请求
* 语法:$.get(url, [data], [callback], [type])
* 参数:
* url:请求路径
* data:请求参数
* callback:回调函数
* type:响应结果的类型(预期服务器返回的数据类型)
3. $.post():发送post请求
* 语法:$.post(url, [data], [callback], [type])
* 参数:
* url:请求路径
* data:请求参数
* callback:回调函数
* type:响应结果的类型
十四、JSON
1. 概念: JavaScript Object Notation (JavaScript对象表示法)
JSON (JavaScript Object Notation) 是⼀种轻量级的数据交换格式。 易于⼈阅读和编写。同时也易于机器解析和⽣成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition -December 1999的⼀个⼦集。 JSON采⽤完全独⽴于语⾔的⽂本格式,但是也使⽤了类似于C语⾔家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语⾔。
* json现在多用于存储和交换文本信息的语法
* 进行数据的传输
* JSON 比 XML 更小、更快,更易解析。
1.jackson
- 语法:
- 基本规则
- 数据在名称/值对中:json数据是由键值对构成的
- 键用引号(单双都行)引起来,也可以不使用引号
- 值得取值类型:
- 数字(整数或浮点数)
- 字符串(在双引号中)
- 逻辑值(true 或 false)
- 数组(在方括号中) {“persons”:[{},{}]}
- 对象(在花括号中) {“address”:{“province”:“陕西”…}}
- null
- 数据由逗号分隔:多个键值对由逗号分隔
- 花括号保存对象:使用{}定义json 格式
- 方括号保存数组:[]
- 获取数据:
- json对象.键名
- json对象[“键名”]
- 数组对象[索引]
- 遍历
//1.定义基本格式
var person = {"name": "张三", age: 23, 'gender': true};
var ps = [{"name": "张三", "age": 23, "gender": true},
{"name": "李四", "age": 24, "gender": true},
{"name": "王五", "age": 25, "gender": false}];
//获取person对象中所有的键和值
//for in 循环
/* for(var key in person){
//这样的方式获取不行。因为相当于 person."name"
//alert(key + ":" + person.key);
alert(key+":"+person[key]);
}*/
//获取ps中的所有值
for (var i = 0; i < ps.length; i++) {
var p = ps[i];
for(var key in p){
alert(key+":"+p[key]);
}
}
- JSON数据和Java对象的相互转换
- JSON解析器:
- 常见的解析器:Jsonlib,Gson,fastjson,jackson
- JSON转为Java对象(jackson)
- 导入jackson的相关jar包
- 创建Jackson核心对象 ObjectMapper
- 调用ObjectMapper的相关方法进行转换
- readValue(json字符串数据,Class)
- Java对象转换JSON
- 使用步骤:
- 导入jackson的相关jar包
- 创建Jackson核心对象 ObjectMapper
- 调用ObjectMapper的相关方法进行转换
- 转换方法:
- writeValue(参数1,obj):
参数1:
File:将obj对象转换为JSON字符串,并保存到指定的文件中
Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中 - writeValueAsString(obj):将对象转为json字符串
- 注解:
- @JsonIgnore:被此注解标注的属性将不再被转为JSON格式
- @JsonFormat:属性值的格式化
- @JsonFormat(pattern = “yyyy-MM-dd”) 如日期对象格式化,pattern用法与SimpleDateFormat类似
- 复杂java对象转换
- List:数组 存储的为对象则为对象数组 [{“key”:“value”},{“key”:“value”},{“key”:“value”}]
- Map:与对象格式一致
案例:
Person类:
public class Person {
private String name;
private int age ;
private String gender;
//@JsonIgnore // 忽略该属性
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
测试类
public class JacksonTest {
//Java对象转为JSON字符串
@Test
public void test1() throws Exception {
//1.创建Person对象
Person p = new Person();
p.setName("张三");
p.setAge(23);
p.setGender("男");
//2.创建Jackson的核心对象 ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//3.转换
/*
转换方法:
writeValue(参数1,obj):
参数1:
File:将obj对象转换为JSON字符串,并保存到指定的文件中
Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
writeValueAsString(obj):将对象转为json字符串
*/
String json = mapper.writeValueAsString(p);
//{"name":"张三","age":23,"gender":"男"}
//System.out.println(json);//{"name":"张三","age":23,"gender":"男"}
//writeValue,将数据写到d://a.txt文件中
//mapper.writeValue(new File("d://a.txt"),p);
//writeValue.将数据关联到Writer中
mapper.writeValue(new FileWriter("d://b.txt"),p);
}
@Test
public void test2() throws Exception {
//1.创建Person对象
Person p = new Person();
p.setName("张三");
p.setAge(23);
p.setGender("男");
p.setBirthday(new Date());
//2.转换 Object -> JSON
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(p);
System.out.println(json);//{"name":"张三","age":23,"gender":"男","birthday":1530958029263}
//{"name":"张三","age":23,"gender":"男","birthday":"2018-07-07"}
}
// List集合 - > JSON Set集合类似
@Test
public void test3() throws Exception {
//1.创建Person对象
Person p = new Person();
p.setName("张三");
p.setAge(23);
p.setGender("男");
p.setBirthday(new Date());
Person p1 = new Person();
p1.setName("张三");
p1.setAge(23);
p1.setGender("男");
p1.setBirthday(new Date());
Person p2 = new Person();
p2.setName("张三");
p2.setAge(23);
p2.setGender("男");
p2.setBirthday(new Date());
//创建List集合
List<Person> ps = new ArrayList<Person>();
ps.add(p);
ps.add(p1);
ps.add(p2);
//2.转换
ObjectMapper mapper = new ObjectMapper();
// List -> JSON
String json = mapper.writeValueAsString(ps);
// [{},{},{}]
//[{"name":"张三","age":23,"gender":"男","birthday":"2018-07-07"},{"name":"张三","age":23,"gender":"男","birthday":"2018-07-07"},{"name":"张三","age":23,"gender":"男","birthday":"2018-07-07"}]
System.out.println(json);
// JSON -> List
List<Person> list = mapper.readValue(json, new TypeReference<List<Person>>() {
}); // class java.util.ArrayList
for (Person pp : list) {
System.out.println(pp);
}
}
//Map集合 -> JSON
@Test
public void test4() throws Exception {
//1.创建map对象
Map<String,Object> map = new HashMap<String,Object>();
map.put("name","张三");
map.put("age",23);
map.put("gender","男");
//2.转换 map -> JSON
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(map);
//{"name":"张三","age":23,"gender":"男"}
System.out.println(json);//{"gender":"男","name":"张三","age":23}
// JSON -> Map
//方式一: //class java.util.LinkedHashMap
Map<String,Object> hm = mapper.readValue(json, Map.class);
//方式二: //class java.util.LinkedHashMap
//Map<String, Object> lhm= mapper.readValue(json, new TypeReference<Map<String, Object>>() {
});
Set<String> set = hm.keySet();
for (String str : set) {
System.out.println(str + ":" + hm.get(str));
}
}
//演示 JSON字符串转为Java对象
@Test
public void test5() throws Exception {
//1.初始化JSON字符串
String json = "{\"gender\":\"男\",\"name\":\"张三\",\"age\":23}";
//2.创建ObjectMapper对象
ObjectMapper mapper = new ObjectMapper();
//3.转换为Java对象 Person对象
Person person = mapper.readValue(json, Person.class);
System.out.println(person);
}
/**
* 将数组转换成json字符串
* [{"name":"张三","age":23,"gender":"男"},{"name":"李四","age":24,"gender":"女"},{"name":"王五","age":25,"gender":"男"}]
* @throws Exception
*/
@Test
public void test6() throws Exception {
Person p1 = new Person("张三", 23, "男");
Person p2 = new Person("李四", 24, "女");
Person p3 = new Person("王五", 25, "男");
Person[] persons = {p1, p2, p3};
ObjectMapper mapper = new ObjectMapper();
// Array -> JSON
String json= mapper.writeValueAsString(persons);
System.out.println(json);
// JSON ->Array
Person[] persons = mapper.readValue(json, Person[].class); // [Lcn.itcast.domain.Person;@43195e57
String content = "";
for (Person person : persons) {
content+=person + " ";
}
System.out.println(content);
}
}
2.Jsonlib
- JSON转为Java对象
1. 导入Jsonlib的相关jar包
java对象和json之间的转换
《1》单个对象或map集合
java->json:
Users user2=new Users();
user2.setUsername(“李四”);
user2.setPassword(“abc”);
user2.setAge(20);
JSONObject obj=JSONObject.fromObject(user);//obj就是json格式的
json->java:
String str="{‘username’:‘李四’,‘password’:‘admin’,‘age’:19}";
JSONObject jsnotallow=JSONObject.fromObject(str);
Users user=(Users)JSONObject.toBean(json,Users.class);
《2》对象集合和json的转换
java集合->json数组:
List list=new ArrayList();
list.add(“dd”);
list.add(“aa”);
JSONArray obj=JSONArray.fromObject(list);//set也是这么转
json数组->java集合:
⽅式1:
String str2="[{‘age’:20,‘password’:‘abc’,‘username’:‘李四’},
{‘age’:10,‘password’:‘adb’,‘username’:‘张三’}]";
JSONArray json2=JSONArray.fromObject(str2);
Object[] obj=(Object[])JSONArray.toArray(json2,Users.class);
⽅式2:
String str3="[{‘age’:20,‘password’:‘abc’,‘username’:‘李四’},
{‘age’:10,‘password’:‘adb’,‘username’:‘展示⼲’}]";
JSONArray json3=JSONArray.fromObject(str3);
//默认转换成ArrayList
List list=(List) JSONArray.toCollection(json3,Users.class);
感谢您能阅读至此!!respect!!!!