软件体系结构
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的时候,在控制台可以看到相应信息;
项目文件存放位置;
工作空间项目和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):通过指定名称获取参数值;
String[] getParameterValues(String name):当多个参数名称相同时,可以使用方法来获取;例如多选框
Map getParameterMap():获取所有参数封装到Map中,其中key为参数名,value为参数值,因为一个参数名称可能有多个值,所以参数值是String[],而不是String。
Enumeration getParameterNames():获取所有参数的名字;
域对象功能
请求转发和包含
//获取转发器 RequestDispatcher rd = request.getRequestDispatcher("/BServlet"); //转发 rd.forward(request, response);
其他方法
- 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”);
<!--tomcat 改配置文件加 URIEncoding= "UTF-8" --> <Connector URIEncoding= "UTF-8" connectionTimeout= "20000" port= "8888" protocol= "HTTP/1.1" redirectPort= "8443" />
post
两种方式
request.setCharacterEncoding(“utf-8”);
arameter(“name”);
//先获得字节数组通过 服务器编码 ;在利用utf-8 编码装换成我们需要的字符;
name = new String(name.getBytes(“iso-8859-1”), “utf-8”);
<!--tomcat 改配置文件加 URIEncoding= "UTF-8" --> <Connector URIEncoding= "UTF-8" connectionTimeout= "20000" port= "8888" protocol= "HTTP/1.1" redirectPort= "8443" />
post
两种方式
request.setCharacterEncoding(“utf-8”);
request.setContentType("text/html; charset=utf-8 ");