软件体系结构
c/s 架构
client (客户端) 服务器 架构
需要编写服务器端程序,以及客户端程序,例如我们安装的就是QQ的客户端程序;
缺点:软件更新时需要同时更新客户端和服务器端两端,比较麻烦;
优点:安全性比较好。
b/s架构
browser(浏览器) 服务器架构
只用编写服务端程序,但安全性较差;
-
URL
-
格式:协议://服务器IP:端⼝/路径1/路径N ? key1=value1 & key2=value2
- 协议:不同的协议有不同的解析⽅式,http 超文本传输协议, https 对http的加密,更安全,但解析时间会延长;
- 路径:资源路径,例如 index.html ;
-
http 常见的请求方法:
- http1.0 定义了3种
- GET: 向服务器获取资源,⽐如常⻅的查询请求
- 请求参数会在浏览器的地址栏中显示,所以不安全;
- 请求参数长度限制长度在1K之内;
- GET请求没有请求体,无法通过request.setCharacterEncoding()来设置参数的编码;
- POST: 向服务器提交数据⽽发送的请求
- 请求参数在请求头中,不会显示浏览器的地址栏,相对安全;
- 请求参数长度没有限制;
- Head: 和get类似,返回的响应中没有具体的内容,⽤于获取报头
- http1.1 定义了6种方法
- PUT:⼀般是⽤于更新请求,⽐如更新个⼈信息、商品信息全量更新
- PATCH:PUT ⽅法的补充,更新指定资源的部分数据
- DELETE:⽤于删除指定的资源
- OPTIONS: 获取服务器⽀持的HTTP请求⽅法,服务器性能、跨域检查等
- CONNECT: ⽅法的作⽤就是把服务器作为跳板,让服务器代替⽤户去访问其它⽹⻚,之后把 数据原原本本的返回给⽤户,⽹⻚开发基本不⽤这个⽅法,如果是http代理就会使⽤这个让服务器代理⽤户去访问其他⽹⻚,类似中介
- TRACE:回显服务器收到的请求,主要⽤于测试或诊断
http 常见状态码
-
1xx :收到请求,需要请求者继续执⾏操作,⽐较少⽤
-
2XX: 请求成功,常⽤的 200
-
3XX: 重定向,浏览器在拿到服务器返回的这个状态码后会⾃动跳转到⼀个新的URL地址,这 个地址可以从响应的Location⾸部中获取;
- 301:永久性跳转,⽐如域名过期,换个域名 302:临时性跳转
-
4XX: 客服端出错,请求包含语法错误或者⽆法完成请求 ,
- 400: 请求出错,⽐如语法协议 403: 没权限访问 404: 找不到这个路径对应
的接⼝或者⽂件 405: 不允许此⽅法进⾏提交,Method not allowed,⽐如接⼝⼀定要
POST⽅式,⽽你是⽤了GET
-
5XX: 服务端出错,服务器在处理请求的过程中发⽣了错误
- 500: 服务器内部报错了,完成不了这次请求 503: 服务器宕机
-
Servlet
Servlet 是 javaweb 三大组件(Servlet , Filter , Lisenter)之一 ;
作用:处理请求
- 接收请求数据
- 处理请求
- 完场响应
servlet 实现
三种方式:
- 实现javax.servlet.Servlet接口;
- 继承javax.servlet.GenericServlet类;
- 继承javax.servlet.http.HttpServlet类;
Servlet -->GenericServlet–>HttpServlet 继承关系; HttpServlet 常用
Servlet中的方法大多数不由我们来调用,而是由Tomcat来调用。并且Servlet的对象也不由我们来创建,由Tomcat来创建!
创建servlet
package servletDemo01; import javax.servlet.*; import java.io.IOException; public class ServletImpl implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("servlet !!!"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
配置 web.xml 文件,绑定url
<servlet> <servlet-name>ServletImpl</servlet-name> <servlet-class>servletDemo01.ServletImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletImpl</servlet-name> <url-pattern>/ServletImpl</url-pattern> </servlet-mapping>
- servlet,servlet-mapping 的servlet-name : 必须一样,先是url访问tomcat ,通过name找到绑定的servlet-class,运行class文件,运行servlet ,处理请求;
- 配置文件可以用 注解 @WebServlet(" / asd") 代替;放在我们的实现类上面,servlet-name 不重要,所以注解中提供了默认名称 “” 空字符串;我们只用配置url ;
- url 通配符:
- 表示所有; @WebServlet(".do") 表示以do 结尾的路径都可;
Servlet 生命周期
init( ); 出生 ;第一次访问时创建servlet,也可以在服务器启动时创建,此时需要额外配置 web.xml 文件,生命 周期中只会被调用一次;
这里的 xml 额外配置:
xml 文件 : servlet 标签中 添加0 ,非负整数即可; 数字越小表示,在服务器启动时,Servlet越先创建;
注解方式:@WebServlet(value = “/*”,loadOnStartup = 1) loadOnStartup 设置参数即可;
service( ); 处理请求
destroy( ) 销毁 服务器关闭时销毁;
- Servlet 线程安全吗? 不安全
- 当servlet 被创建后,不会立即销毁,当多个线程访问时,会进入到同一个servlet中,此时就容易造成线程不安全的相关问题
- 一个Servlet能绑定多个 url 吗?
- 可以,注解 @WebServlet({“”,“”}) 中可以是数组形式;
Servlet 相关接口
ServletRequest
HttpServletRequest 在ServletRequest 的基础上 增加了 http方法
方法:
- String getParameter(String paramName):获取指定请求参数的值;
- String getMethod():获取请求方法,例如GET或POST;
- String getHeader(String name):获取指定请求头的值;
- void setCharacterEncoding(String encoding):设置请求体的编码!因为GET请求没有请求体,所以这个方法只只对POST请求有效。当调用request.setCharacterEncoding(“utf-8”)之后,再通过getParameter()方法获取参数值时,那么参数值都已经通过了转码,即转换成了UTF-8编码。所以,这个方法必须在调用getParameter()方法之前调用!
ServletResponse
HttpServletResponse 在ServletResponse 的基础上 增加了 http方法
方法:
- PrintWriter getWriter():获取字符响应流,使用该流可以向客户端输出响应信息。
- ServletOutputStream getOutputStream():获取字节响应流,当需要向客户端响应字节数据时,需要使用这个流,例如要向客户端响应图片;
- void setCharacterEncoding(String encoding):用来设置字符响应流的编码,例如在调用setCharacterEncoding(“utf-8”);之后,再response.getWriter()获取字符响应流对象,这时的响应流的编码为utf-8,使用response.getWriter()输出的中文都会转换成utf-8编码后发送给客户端;
- void setHeader(String name, String value):向客户端添加响应头信息,例如setHeader(“Refresh”, “3;url=http://www.baidu.com”),表示3秒后自动刷新到http://www.baidu.com;
- void setContentType(String contentType):该方法是setHeader(“content-type”, “xxx”)的简便方法,即用来添加名为content-type响应头的方法。content-type响应头用来设置响应数据的MIME类型,例如要向客户端响应jpg的图片,那么可以setContentType(“image/jepg”),如果响应数据为文本类型,那么还要台同时设置编码,例如setContentType(“text/html;chartset=utf-8”)表示响应数据类型为文本类型中的html类型,并且该方法会调用setCharacterEncoding(“utf-8”)方法;
- void sendError(int code, String errorMsg):向客户端发送状态码,以及错误消息。例如给客户端发送404:response(404, “您要查找的资源不存在!”)。
ServletConfig
init()方法的参数,它表示Servlet配置对象,它对应Servlet的配置信息,那对应web.xml文件中的
<servlet>
元素。ServletConfig对象是由服务器创建的,然后传递给Servlet的init()方法,你可以在init()方法中使用它!相关方法:
- String getServletName():获取Servlet在web.xml文件中的配置名称,即指定的名称;
- ServletContext getServletContext():用来获取ServletContext Application域对象
- ServletContext在服务器启动时创建,服务器关闭时销毁;
- 获取方式:1. ServletConfig 获取 ; 2. GenericServlet类中有getServletContext();可直接调用;
- String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;
- Enumeration getInitParameterNames():用来获取在web.xml中配置的所有初始化参数名称;
servlet 四大域
Application 域 全局域,整个web项目有用;
session 域 会话域
request 域 请求域
page 域 页面域
四大域对象:
- ServletContext;
- HttpSession;
- ServletRequest;
- PageContext;
域对象的一些方法
- getAttribute(String name) 获取对应的数据
- getAttributeNames()获取所有的key
- removeAttribute(String name) 移除对应的数据
- SetAttribute(String name, Object object) 设置数据
IDEA与tomcat相关配置
IDEA会为每一个tomcat部署的项目单独创建一份配置文件,配置文件在哪里呢?我们启动tomcat的时候,在控制台可以看到相应信息;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RBcI9Dip-1667116846706)(C:\Users\22496\Desktop\images\idea 与 tomcat 部署.png)]
项目文件存放位置;
工作空间项目和tomcat部署的web项目
- tomcat真正访问的是“tomcat部署的web项目” 即 IDEA下的out 目录中的内容 ,“tomcat部署的web项目"对应着"工作空间项目” 的web目录下的所有资源
- WEB-INF目录下的资源不能被浏览器直接访问。
request
在客户端发出每个请求时,服务器都会创建一个request对象,并把请求数据封装到request中,然后在调用Servlet.service()方法时传递给service()方法,这说明在service()方法中可以通过request对象来获取请求数据。
请求头
String getHeader(String name):获取指定名称的请求头;
Enumeration getHeaderNames():获取所有请求头名称;
int getIntHeader(String name):获取值为int类型的请求头。
请求参数
String getParameter(String name):通过指定名称获取参数值;
前端传递请求参数名,没有传递值 username=&email=111,获取到"";
前端没有传递请求参数名,结果为null
String[] getParameterValues(String name):当多个参数名称相同时,可以使用方法来获取;例如多选框
Map getParameterMap():获取所有参数封装到Map中,其中key为参数名,value为参数值,因为一个参数名称可能有多个值,所以参数值是String[],而不是String。
Enumeration getParameterNames():获取所有参数的名字;
域对象功能
请求转发和包含
//获取转发器
RequestDispatcher rd = request.getRequestDispatcher(“/BServlet”);
//转发
rd.forward(request, response);
```java + 其他方法 - int getContentLength():获取请求体的字节数,GET请求没有请求体,没有请求体返回-1; - String getContentType():获取请求类型,如果请求是GET,那么这个方法返回null;如果是POST请求,那么默认为application/x-www-form-urlencoded,表示请求体内容使用了URL编码; - String getMethod():返回请求方法,例如:GET - Locale getLocale():返回当前客户端浏览器的Locale。java.util.Locale表示国家和言语,这个东西在国际化中很有用; - String getCharacterEncoding():获取请求编码,如果没有setCharacterEncoding(),那么返回null,表示使用ISO-8859-1编码; - void setCharacterEncoding(String code):设置请求编码,只对请求体有效!注意,对于GET而言,没有请求体!!!所以此方法只能对POST请求中的参数有效! - String getContextPath():返回上下文路径,例如:/hello - String getQueryString():返回请求URL中的参数,例如:name=zhangSan - String getRequestURI():返回请求URI路径,例如:/hello/oneServlet - StringBuffer getRequestURL():返回请求URL路径,例如:http://localhost/hello/oneServlet,即返回除了参数以外的路径信息; - String getServletPath():返回Servlet路径,例如:/oneServlet - String getRemoteAddr():返回当前客户端的IP地址; - String getRemoteHost():返回当前客户端的主机名,但这个方法的实现还是获取IP地址; - String getScheme():返回请求协议,例如:http; - String getServerName():返回主机名,例如:localhost - int getServerPort():返回服务器端口号,例如:8080
response
在客户端发出每个请求时,服务器都会创建一个response对象,并传入给Servlet.service()方法。response对象是用来对客户端进行响应的,这说明在service()方法中使用response对象可以完成对客户端的响应工作。
设置响应头信息;
response.setHeader(“content-type”, “text/html;charset=utf-8”):设置content-type响应头,该头的作用是告诉浏览器响应内容为html类型,编码为utf-8。而且同时会设置response的字符流编码为utf-8,即response.setCharaceterEncoding(“utf-8”);
response.setHeader(“Refresh”,“5; URL=http://www.baidu.com”):5秒后自动跳转到百度主页。
发送状态码;
response.setContentType(“text/html;charset=utf-8”):等同与调用response.setHeader(“content-type”, “text/html;charset=utf-8”);
response.setCharacterEncoding(“utf-8”):设置字符响应流的字符编码为utf-8;
response.setStatus(200):设置状态码;
response.sendError(404, “您要查找的资源不存在”):当发送错误状态码时,Tomcat会跳转到固定的错误页面去,但可以显示错误信息。
设置响应正文;
通过获取字符流 或者 字节流 输出响应内容;
PrintWriter out = response.getWriter():获取字符流;
response.getWriter()是PrintWriter类型,所以它有缓冲区,缓冲区的默认大小为8KB。
调用response.flushBuffer()方法来手动刷新缓冲区;
ServletOutputStream out = response.getOutputStream():获取字节流;
当我们响应数据之前,需要设置文本类型及编码;setContentType();
注意!!! 在一个请求中,不能同时使用这两个流!不然会抛出IllegalStateException异常。
重定向;
//重定向
response.sendRedirect(“http://www.baidu.cn”);
重定向是两次请求;
重定向的URL可以是其他应用,不局限于当前应用;
重定向的响应头为302,并且必须要有Location响应头;
重定向就不要再使用response.getWriter()或response.getOutputStream()输出数据,不然可能会出现异常;
转发与重定向的区别:
- 请求转发是一个请求,而重定向是两个请求;
- 请求转发后浏览器地址栏不会有变化,而重定向会有变化,因为重定向是两个请求;
- 请求转发的目标只能是本应用中的资源,重定向的目标可以是其他应用;
- 请求转发对AServlet和BServlet的请求方法是相同的,即要么都是GET,要么都是POST,因为请求转发是一个请求;
- 重定向的第二个请求一定是GET;
- 请求转发是在服务端内部执行的,而重定向是在客户端执行的.
Servlet 编码问题
我们常说的文本都存在编码问题;在计算机底层以及io传输的过程中,都是以字节的形式存在的;在获取字节流后,利用相应的编码表转成相应的字符;常见的编码有 Ascall 码,utf-8,GBK,ISO-8859-1 (西欧编码)等
ascall 码表里包含了所有的英文字母,而其他所有的编码都是在ascall 码的基础上扩展的,所以英文在任何编码里都不会乱码;而像其他语言就会因为编码的问题而乱码; 例如 同样的一个中文字,它在a编码里对应1120;而在b编码表里对应1563;那么当它在a编码环境中会显示正确,而在b编码环境中就会显示异常;
所以解决乱码问题就是统一编码规则即可;
在web 项目中
- html页面一般是UTF-8编码,
- 浏览器(chrom)的默认编码是UTF-8;
- tomcat服务器处理请求的默认编码是ISO-8859-1 ;
- IDEA 编辑器的编码全都设置为UTF-8;
get请求没有请求体,不能直接通过请求对象设置编码;
在tomcat 7 以及以前的版本,它没有默认处理get 请求的编码;在8版本及以后的版本,tomcat默认处理get请求的编码,将其指定为utf-8,此时我们拿到的就是正确的没有乱码的结果;
tomcat 7之前既然没有默认指定get编码,那么怎么手动改编码呢?
//通过代码改编码
String name = request.getParameter(“name”);
//先获得字节数组通过 服务器编码 ;在利用utf-8 编码装换成我们需要的字符;
name = new String(name.getBytes(“iso-8859-1”), “utf-8”);
```xml + ```xml <!--tomcat 改配置文件加 URIEncoding= "UTF-8" --> <Connector URIEncoding= "UTF-8" connectionTimeout= "20000" port= "8888" protocol= "HTTP/1.1" redirectPort= "8443" />
+ post + 两种方式 + 设置请求编码 :request.setCharacterEncoding(“utf-8”); + 设置响应编码:response.setContentType("text/html; charset=utf-8 "); + 响应编码 只设置 setCharacterEncoding(“utf-8”); 只设置了响应流的编码,没有指定浏览器编码; + 当我们使用setContentType("text/html; charset=utf-8 "); 时,它的响应流编码默认跟浏览器编码一致,所以只设置响应浏览器编码即可;
解决编码问题的相关代码 要写在操作数据之前的;即先编码,后使用;
jsp
jsp概述
jsp 既可以写html ,又可以写java代码;
<% %> java代码入口,相当于main函数; 多个<% %>可以通用
<%= %> 表达式的值输出到页面
<%! %> 定义属性和方法,相当于java类
<%
int a = 10;
if(a==10){
out.print("<p>"+a+"</p>");
}
%>
<%-- 内容输出到页面,相当于out.print--%>
<%= a %>
<%-- 定义属性和方法,相当于类--%>
<%!
private String str;
private void fun(){
System.out.println(str);
}
%>
<%
this.str="123";
fun();
%>
jsp九大内置对象
- pageContext page域对象
- request 请求对象(请求域)
- session session域对象
- application 全局域对象
- response 响应对象
- out 输出流对象
- config 配置
- page 相当于this
- exception 异常
html转jsp
创建与html同名jsp文件,
把html页面的所有内容拷贝到jsp, 从<%@ page%> 之后
把相对路径转换为绝对路径, 项目设置发布项目名: / 绝对路径: 全部以 /开头
如果设置发布项目名: /xx 绝对路径: /xx开头, /xx动态获取: <%=request.getContextPath()%>
EL表达式
<%= %> 往页面输出内容: 如果内容为null(空对象), 也会在页面显示
EL 表达式
${域中的属性名(k值)}
${对象.属性名..}
获取对象属性
- 查找所有的域
- 从小范围的域–》大范围的域,即page域(若没找到)到application域
- 若所有的域都没找到,返回null值,在页面不显示
JSTL标签
作用: 替换java脚本, 配合EL标签式,
执行在服务器端执行, 把jstl执行之后的结果响应给客户端浏览器,
JSTL标签在Html标签之前执行
使用步骤
导入jstl依赖:
在使用jstl标签的jsp页面, 使用 taglib指令,导入标签库
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
prefix: 前缀, 任意取名, 规范名: core标签库: c 比如: `<c:div>` 使用前缀区分html标签 core所有的标签名: `<c:标签名>` uri: 对应jstl标签的url, 固定写法, 导入jstl标签库, 选择的是 jsp/jstl的标签库
使用:
<!-- if(){} -->
<c: if test="${a==null}">
<h1>
a是null
</h1>
</c:>
<!-- if else if else -->
<!-- choose标签里不能加注释-->
<c:choose>
<c:when test="">
</c:when>
<c:when test="">
</c:when>
<c:otherwise test="">
</c:otherwise>
</c:choose>
<!-- 循环 -->
<!-- 普通循环-->
<c:forEach var="i" begin="0" end="4" step="1">
</c:forEach>
<!--增强for-->
<c:forEach var = "admin" items ="${adminList}">
</c:forEach>
for循环: 有一个varStatus=“变量” , 得到for循环的循环状态对象,该对象有以下属性:
- count:int类型,当前以遍历元素的个数; 第几次循环,从1开始
- index:int类型,当前元素的下标; 从0开始
- first:boolean类型,是否为第一个元素;
- last:boolean类型,是否为最后一个元素;
Cookie
Cookie就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。相当于一个身份的标识;
Cookie由服务器创建,在第一次请求的时候,响应(发)给客户端;在以后的每次客户端发请求时,都会带上Cookie,服务器也会返回Cookie;用于身份识别;
Cookie在不同的浏览器之间是不共享的;
Cookie k-v键值对 ,相同的k可以覆盖原有的值;
tomcat 7 及之前,Cookie不支持中文;解决:URL编码;
String str ="中国"; //URL编码 String str1 = URLEncoder.encode(str, "UTF-8"); System.out.println(str1); //%E4%B8%AD%E5%9B%BD //URL解码 String str2 = URLDecoder.decode(str1, "UTF-8"); System.out.println(str2); //中国
tomcat 8以及以后,Cookie支持中文;
Cookie操作
//服务器创建Cookie
Cookie cook1 = new Cookie("name","张三");
Cookie cook2 = new Cookie("age","28");
//传Cookie,响应返回Cookie
response.addCookie(cookie1);
response.addCookie(cookie2);
//拿Cookie
Cookie[] cs = request.getCookies();//获取请求中的Cookie
//Cookie 类的相关方法
cook.getName();
cook.getValue();
//设置Cookie存活时间
//参数单位为秒;
//默认值 -1, 是会话级别存活,即浏览器关闭窗口;
// 参数 0 为立即删除
cook.setMaxAge(int count);
//设置Cookie 访问路径
//如果servlet 请求路径包含Cookie路径,会在请求中带上这些Cookie;
//这里的包含是指
// 例如 访问路径为 localhost:8080/a/b/c ; 它包含的路径有:/a; /a/b; /a/b/c;
cook.setPath();
//修改value值
cook.setValue();
//若path不同,即使key相同,也是不同的Cookie
Session
javax.servlet.http.HttpSession
接口表示一个会话,我们可以把一个会话内需要共享的数据保存到HttSession对象中!获取Session :
- HttpSession request.getSesssion():如果当前会话已经有了session对象那么直接返回,如果当前会话还不存在会话,那么创建session并返回;
- HttpSession request.getSession(boolean):当参数为true时,与requeset.getSession()相同。如果参数为false,那么如果当前会话中存在session则返回,不存在返回null;
//设置session失效;一般作退出使用 void invalidate(); //设置最大存活时间 void setMaxInactiveInterval(int interval); //获取sessionid String getId(); //域对象的相关方法;get,set,remove;
session原理:
- 服务器在创建session时,会给每一个客户端生成一个sessionid用来做身份识别;这个sessionid被放在Cookie中(也就是一个k-v键值对),随着服务器的响应,客户端接收Cookie,得到sessionid;在下一次请求中,通过sessionid,去服务器对应的session块中交换数据;
- 在服务器中,tomcat维护了一个session池,里面存放了各个客户端的seeion,它们会通过sessionid来区分;每一个session的默认存活时间为30分钟,即离上一次访问session的时长;
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cmijyoD4-1667116846709)(C:\Users\22496\Desktop\实训三\javaweb\javaWeb新版\文档\assets\wps8-1665588799705.jpg)]
当浏览器关闭,Cookie(客户端)销毁,session(服务器)就不会被访问,经过设定的存活时间,就会被服务器清理;
Filter
拦截请求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DCzcEfHY-1667116846710)(C:\Users\22496\Desktop\images\Filter.png)]
实现:
- 编写一个类实现javax.servlet.Filter接口
- 在web.xml文件或者使用注解, 对过滤器进行配置, 配置过滤器拦截那些请求的url
拦截后放行:
filterChain.doFilter(servletRequest,servletResponse);
过滤器的执行顺序:
web.xml配置文件: 过滤器的配置文件决定过滤器执行顺序
由过滤器的<filter-mapper>
顺序决定的, 谁的<filter-mapper>
在前,谁先执行
<filter>
<filter-name>AFilter</filter-name>
<filter-class>Filter.CheckLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/AFilter</url-pattern>
</filter-mapping>
在web3.0提供注解@WebFilter的配置方式:
使用注解的方式, 过滤器执行的顺序, 由过滤器名字决定, 多个过滤器, 推荐使用web.xml配置
@WebFilter(filterName = "CheckLoginFilter",value = "/user/*")
文件上传
文件上传时
对于小文件,我们一般将它存在服务器上;
前端:
- 使用表单元素:
<input type="file"/>
- 提交方式: POST,请求体上传;
- from 表单的 enctype 的值"multipart/form-data"
后端:
- 当from表单的 enctype 的值"multipart/form-data",request.getParamter()这个方法失效
- 通过请求对象的ServletInputStream得到数据, 借助第三方的jar, apache提供的 commons-fileupload.jar,commons-io.jar ;
使用Commons-fileupload步骤
- 导入依赖
- 创建DiskFileItemFactory, 工厂类, FileItem: 对应表单的表单项(input,select,teaxarea)
- 创建一个解析Request对象解析器 ServletFileUpload
- 解析Request对象 ServletFileUpload的
List<FileItem> parseRequest(request)
- 遍历第4步的 得到
List<FileItem>
得到一个一个FileItem,根据FileItem类型(普通表单项,非普通表单项(文件表单))
@WebServlet( "/uploadServlet")
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求参数
//String username = request.getParameter("username"); //失效
//System.out.println(username); //null
//ServletInputStream inputStream = request.getInputStream();
//借助于 commons-fileupload
//1.创建DiskFileItemFactory对象
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//2.创建一个解析Request对象解析器 ServletFileUpload
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
try {
//3.解析Request对象
List<FileItem> fileItems = servletFileUpload.parseRequest(request);
//4.遍历fileItems
for (FileItem fileItem : fileItems) {
//5.判断fileItem是否是一个普通表单项
// true 普通表单项 false: 非普通表单项 文件表单项
if(fileItem.isFormField()){ //true 普通表单项
//表单项的name getFieldName() // getName() 上传的文件名
String fieldName = fileItem.getFieldName();
//表单项的value getString(String charset)
String value = fileItem.getString("UTF-8");
System.out.println(fieldName+":"+value);
}else{ //非普通表单项 文件表单项
//上传的文件保存到服务器的硬盘上
String savePath = "D:/upload/";
//得到上传的文件名 getName()
String uploadFilename = fileItem.getName();
//注意问题: 服务器保存的文件名不能直接使用用户上传的文件名
//保证每一个文件名唯一的 时间戳(毫秒)+用户名+...
// UUID(随机生成32位16进账字符串)
//保存 FileItem的write(File file)
//使用UUID
// 创建一个文件名 文件名称 + 后缀名(上传文件的后缀名)
String saveFile = FileUploadUtil.randomFilename()+FileUploadUtil.getFileSuffix(uploadFilename);
fileItem.write(new File(savePath,saveFile));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Ajax
什么是Ajax
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。目前流行json数据;
AJAX还有一个最大的特点就是,当服务器响应时,不用刷新整个浏览器页面,而是可以局部刷新。这一特点给用户的感受是在不知不觉中完成请求和响应过程。
同步交互和异步交互的区别:
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
Ajax核心对象
其实AJAX就是在Javascript中多添加了一个对象:XMLHttpRequest对象。通过这个对象完成异步交互;
多个异步请求并不是同时被服务器处理,而是在XMLHttpRequest 对象的作用下,组成了一个阻塞队列,服务器依次处理这些请求,这里有一个排队的机制在里面;
jQuery 中的Ajax
$.ajax()可以通过发送HTTP请求加载远程数据,是jQuery最底层的AJAX的实现,具有较高灵活性:
$.ajax({ //请求路径 url:getPath()+"/AServlet", //请求方法 type:"GET", // 请求参数 data:"name=张三", // 返回数据类型 dataType:"text", // 请求成功的回调函数 // 参数date 为 返回参数; success:function(data){ alert(data); } });
JQuery封装的发送HTTP GET请求从服务器加载数据的AJAX方法:
// get $.get(url,data,success(resp,status,xhr),dataType) // post $.post(url,data,success(resp,status,xhr),dataType);
Json
什么是json
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式 (字符串类型)。
JSON是用字符串来表示Javascript对象,例如可以在Servlet中发送一个JSON格式的字符串给客户端Javascript,Javascript可以执行这个字符串,得到一个Javascript对象。
json 语法:
- 花括号保存对象
- 方括号保存数组
- k-v结构
- key要在双引号中,不能使用单引号
- 字符串必须使用双引号表示,不能使用单引号
- value值可以为null
var person = ' {"name":"zhangSan",
"age":"18",
"sex":"male"} ';
{
"employees": [
{ "firstName":"Bill" , "lastName":"Gates" },
{ "firstName":"George" , "lastName":"Bush" },
{ "firstName":"Thomas" , "lastName":"Carter" }
]
}
json 序列化
javascript:
//json -> javascript
JSON.parse(text[, reviver])
//javascript --> json
JSON.stringify(value[, replacer [, space]])
java:
采用第三方 jar包 fastjson.jar
fastjson优点:速度快、使用广泛、使用简单、功能完备、测试完备(之前爆了很多漏洞),现在使用fastjson
至少升级到1.2.60
版本
fastjson 三大对象
- JSON
- 主要用于转换json;
- JSONObject
- JSONArray
如果想得到指定格式的日期字符串,我们可以使用
@JSONField(format = "yyyy-MM-dd")
注解进行日期格式化//日期格式化 @JSONField(format = "yyyy-MM-dd") //不可序列化,即json中会隐去该字段 @JSONField(serialize=true) private Date birthday;
T parseObject(String text, Class<T> clazz) //把json转换为一个java对象
JSONObject parseObject(String text) // 把json转换为一个JSONObject对象
List<T> parseArray(String text, Class<T> clazz) //把json转换为一个List集合
JSONArray parseArray(String text) //把json转换为一个JSONArray对象
String toJSONString(Object object) //把一个java对象转换为json格式的字符串
Person person = new Person("liSi", 18, "female");
//把java对象转换为json字符串
String json = JSON.toJSONString(person);
System.out.println(json);
(text[, reviver])
//javascript --> json
JSON.stringify(value[, replacer [, space]])
java:
采用第三方 jar包 fastjson.jar
fastjson优点:**速度快、使用广泛、使用简单、功能完备**、测试完备(之前爆了很多漏洞),现在使用`fastjson`至少升级到`1.2.60`版本
>fastjson 三大对象
>
>+ JSON
> + 主要用于转换json;
>+ JSONObject
>+ JSONArray
>
>
>
>如果想得到指定格式的日期字符串,我们可以使用`@JSONField(format = "yyyy-MM-dd")`注解进行日期格式化
>
>```java
>//日期格式化
>@JSONField(format = "yyyy-MM-dd")
>//不可序列化,即json中会隐去该字段
>@JSONField(serialize=true)
>private Date birthday;
>
>```
>
>
```java
T parseObject(String text, Class<T> clazz) //把json转换为一个java对象
JSONObject parseObject(String text) // 把json转换为一个JSONObject对象
List<T> parseArray(String text, Class<T> clazz) //把json转换为一个List集合
JSONArray parseArray(String text) //把json转换为一个JSONArray对象
String toJSONString(Object object) //把一个java对象转换为json格式的字符串
Person person = new Person("liSi", 18, "female");
//把java对象转换为json字符串
String json = JSON.toJSONString(person);
System.out.println(json);