学习笔记27-request\response

servlet的继承结构
servlet(接口) 直接实现此接口必须重写5个抽象方法,但是我们经常用的就只有service,比较麻烦
GenericServlet(抽象类)实现Servlet接口 该抽象类解决了此问题,它对Servlet其他几个方法进行了默认为空处理,继承它只需实现一个service方法即可(其它方法如果需要,可以进行覆写)
HttpServlet(抽象类)继承了GenericServlet
GenericServlet虽然解决了多个抽象方法重写的问题,但是我们的子类是处理网络请求的,需要判断请求的类型,然后再做具体的操作,这部分代码我们自己实现比较麻烦,而HttpServlet对此进行了处理,我们只需关注实际业务即可
servlet的URLPattern 不仅可以定义一个,也可以定义多个 @WebServlet({"/aaa","/bbb"."/ccc"}) 也可以是多重路径"/aaa/bbb" 也可以用通配符"/" "/aaa/" “*.do”

Http hyper text transfer protocol 超文本传输协议
传输协议:定义了客户端和服务器端通信时,发送数据的格式

Http协议的特点
1.基于TCP/IP协议的高级协议
2.它的默认端口号是80
3.它是基于请求/响应模型的 即一次请求对应一次响应
4.它是无状态的,每次请求之间相互独立,不能交互数据

http的历史版本 访问一个页面并不是简单的一次访问一次响应,每个资源都是一次访问,如一个图片,一个视频,每个css资源,js资源
1.0 每一个资源的请求完毕后,断开连接,一个页面进行了多次连接,断开,浪费资源,效率较低
1.1 复用连接,每一次请求完毕后连接先不关闭,如果仍有资源需要请求就复用该连接,直到没有再过一段时间关闭

请求消息的数据格式(请求行和请求头之间连着呢,只换了行)
1.请求行
2.请求头
3.请求空行(就是一个空的行,用来分割请求行和请求体)
4.请求体

具体如下:
POST /aaa HTTP/1.1 --请求行(请求方式,请求的url路径,协议名称及版本号)
Host: localhost:8080 --请求头(都是键值对的形式,前面是键,后面是值,中间冒号隔开)
Connection: keep-alive
Content-Length: 13
Cache-Control: max-age=0
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
Referer: http://localhost:8080/login.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: Idea-22621246=49cca6a6-7eda-4816-b05e-f231ec3362d5; JSESSIONID=4900680E78DE8376DB470A0AEDA4C3AD
–请求空行
username=lisi --请求体

get方式是没有请求体的,参数直接放在请求行中(URL路径后面)

get和post请求方式的区别
1.请求参数get是放在请求行中的(即url后面),而post方式是放在请求体里的
2.get方式参数是有大小限制的,而post方式没有
3.get方式不太安全,post方式相对安全

常见的请求头:(请求头就是客户端浏览器告诉服务器一些信息)
User-Agent 浏览器信息 agent代理人,代理商 通过该请求头就可以获得用户的浏览器信息,从而解决浏览器的兼容问题
Accept 可以接收的数据类型 */*所有类型
Accept-language 可以接收的语言
Accept-encoding 可以接收的压缩格式
Connection :keep-alive 连接状态,一直活着的,可复用
Upgrade-insecure-requests:1 可处理https协议的意思
Referer(引用页) 告诉服务器当前的请求从哪里来 作用:1.防盗链(防止盗取超链接) 2.数据统计

请求体:用来封装POST请求的请求参数的


request和response对象都是由服务器创建的,request是用来获取用户请求信息的,response是用来设置给浏览器的响应信息的

ServletRequest接口 子接口是HttpServletRequest 这都是javaee API HttpServletRequest的实现类是由各web服务器厂商编写的,tomcat的实现类是 org.apache.catalina.connector.RequestssFacade

在IDEA中我们可以直接创建一个Servlet文件,不用自己手动创建类再实现接口,再重写方法,比较简单

request的功能

1.获取请求行信息
GET /day01/demo1?username=zhangsan http/1.1
(1)获取请求方式 getMethod()
(2)getContextPath()获取虚拟路径
(3)getServletPath()获取servlet路径
(4)getURL()获取请求的URL 即http://localhost:8080/day01/demo1 getURI()获取请求的URI 即day01/demo1
(5)getProtocol()获取网络协议及版本号
(6)getQuaryString()获取请求的参数信息
(7)getRemoteAddr()获取访问的ip地址
项目的虚拟路径一定要写,否则获取的虚拟路径是不正确的
URL统一资源定位符 URI是统一资源标识符 URI的范围更大

2.获取请求头信息
getHeader()获取某个具体的请求头 getHeaderNames()获取所有头的一个枚举迭代器 向页面响应内容需要靠response来设置,response.getWriter().write(“内容”) 在打印之前需要设置一下内容的格式
response.setContextType(“text/html;charset=utf-8”)

3.获取请求体信息
只有post方式才有请求体,请求体被封装在了request对象中,我们可以通过流获取到.先获取一个流,在从流中读取请求体的信息.
getReader() 获取一个BufferedReader 字符流
getInPutStream() 获取的是一个ServletInPutStream 字节流

其他功能
1.获取参数的通用方法
getParameter(str name) 通过参数名获取参数值
getParameterValues(str name)通过参数名获取所有的参数值 如hobby 爱好可以有对个 hobby=swimming&hobby=read
getParameterNames()获取所有的参数名 Enumeration
getParameterMap()获取所有参数的map集合 Map<String,String[]>
注意:获取参数的通用方法和获取流后获取所有的参数内容不能同时使用,否则会出现空指针异常 一种方式取完了,另一种方式就取不到了
在debug模式下更新了class文件后不重启服务器也会生效,在普通模式下不能 前提是update选项选择了resources和classes

doGet()和doPost()方法如果处理相同的逻辑,不用两个都写,一个写了另一个直接调用该方法就行了

在页面中输入中文,servlet中打印获取的内容出现乱码的原因
编码:将字符变成字节 解码:将字节变成字符
1.get方式,我们的注册表单编码方式是utf-8 ,输入参数后都是以utf-8编码方式进行编码并传输至服务器的,服务器以ISO-8859-1方式解码,就出现了乱码
解决方式 得到的内容先按照iso8859-1编码,在按照Utf-8解码就OK new String( name.getbytes(“iso-8859-1”),“utf-8”) 现在tomcat8已经解决了此问题,不用我们自己解决了.

2.post方式和get方式出现乱码的原因是一样的都是客户端和服务器端的编解码方式不一致,但解决方法却不一样,原因是get方法的参数是在URL后面跟着呢,URL的编解码用的是URLEncoder和URLDecoder,出现中文默认按iso-8859-1解码,并且通过request.setCharacterEncoding(“UTF-8”) 也解决不了 只能修改配置文件 或者在传递参数前进行汉字的URLEncoder.encode(汉字,编码格式)

response.setContentType(“tetx/html;charset=utf-8”) 这是为了控制浏览器用UTF-8的字符集 因为它默认用的是gbk的

请求转发是一种服务器内部的资源跳转方式
特点:
1.浏览器地址栏不会发生改变
2.只有一次请求
3.只能转发到项目内部的资源

域对象:一个有作用范围的对象,就是域对象,可以在作用范围内共享数据
request对象的作用范围就是一次请求,一般用于请求转发的多个资源之间的数据通信

web项目的jar包要放在WEB-INF文件夹的lib文件中,放在项目下只能java代码用,web项目运行会报缺少jar包

JDBCTemplate的query方法(参数是sql,BeanPropertyRowMapper,参数)返回的是一个数组,如果没有值,返回的是一个空集合 所以在判断的时候要判断是否为null及size()是否为0, 以防出现空指针异常

在实际开发中,数据库的每张表都对应一个javaBean 数据库查询的数据往往会封装到相应的对象中

DAO data access object 数据访问对象 DAO是面向对象编程中专门访问数据库的接口,用它的实现类进行数据库的访问

代码的编写,注意分层,DAO层操作数据 domain实体类 utils工具类 测试类test 注意一步一测试,不要从头写到尾然后报一堆的错误

login.HTML中的form表单的action属性值需要写路径 1.可以写URL路径 2.本项目的话可以写绝对路径(以/开始) /项目虚拟目录/资源文件或servlet路径 3.也可以写相对路径(最前面不加/) 资源文件或servlet路径

我们在进行登录案例的时候,发现查询数据库的内容封装成对象可以利用JDBCTemplate,但是前台提交的内容封装成登录对象却需要手动获取及设置,一旦参数较多是时分的麻烦,参数可以批量获取封装到一个Map集合中
然后直接将此集合映射为一个对象.BeanUtils就提供了这样的功能,这是一个apache开源的工具类,需要导入jar包后使用

BeanUtils是用于封装javaBean的
javaBean是标准的java类
要求:
1.是public修饰的类
2.有空参构造方法
3.成员变量私有
4.提供公共的getter setter方法
作用:封装数据

成员变量和属性是不一样的 成员变量不一定是属性,属性是getter和setter方法截取get或set后首字母变小写的产物,这是针对BeanUtils说的
BeanUtils.getProperty(obj,property,value) BeanUtils.setProperty(obj,property,value) 这里面的property就必须是属性而不能是简单的成员变量
所以get和set方法属性尽量和成员变量保持一致


请求消息:客户端发送给服务器的数据
响应消息:服务器发送给客户端的数据
格式:
请求行 响应行 http/1.1 200 OK 200是状态码 OK是状态码描述
请求头 响应头 ContextType:text/html charset=utf-8
请求空行 响应空行
请求体 响应体 就是html文档的信息,响应的就是一个页面的二进制数据(含有页面的所有内容,图片等等)

状态码:就是服务器给客户端返回的本次请求和响应的一个状态
分类:
1xx: 代表服务器接收到了请求消息,但没有接收完毕,过一段时间就会发送此状态码
2xx: 代表成功 例如200
3xx: 302重定向 304访问缓存
4xx; 代表客户端错误 404请求的路径没有对应的资源(路径错误或服务器没开启等) 405请求的方式没有对应的doxxx方法
5xx: 代表服务器错误 500服务器内部错误

chrome浏览器默认的编码是GBK IE的编码可选UTF-8和GBK,IE11默认的编码是UTF-8 而tomcat服务器默认的编码是iso-8858-1 所以响应出去汉字,不做任何字符集设置会出现乱码
response.setContentType(“text/html;charset=utf-8”) 可以同时设置服务器和浏览器的编码方式 但是response.setCharacterEncoding(“utf-8”)只能设置服务器

重要的几个响应头:
Content-Type 服务器告诉浏览器本次响应的数据格式以及编码格式
content-disposition 服务器告诉浏览器响应体打开的形式 默认值是in-line(在当前页面打开) 还有一个选项是 attachment(以附件的形式打开) 中间会有一个属性 filename=xxx

response对象的功能
1.设置响应行 response.setStatus() 设置状态码
2.设置响应头 response.setHeader(name,value)
3.设置响应体 通过流来输出响应体 1.字符流输出流printWriter response.getWriter().write() 2.字节输出流 ServletOutPutStream response.getOutPutStream().write()

重定向和请求转发的区别
重定向
1.地址栏会发生改变
2.可以访问其他项目和其他服务器的资源
3.多次请求和多次响应 request域对象不起作用了
请求转发
1.地址栏不会发生改变
2.只能访问项目内的资源
3.一次请求 request域对象起作用

绝对路径(a标签,form表单,重定向) 和相对路径(请求转发)
通过绝对路径可以找到唯一的资源,通过相对路径不能找到唯一的资源(会随着代码所处的项目而发生变化),想利用相对路径就必须知道目标资源和当前资源之间的相对位置关系
以/开头的就是绝对路径 以.开头的就是相对路径 不写任何东西默认就是./ ./就代表当前目录 …/就代表后退一级目录

推荐使用绝对路径,因为绝对路径比较简单,相对路径比较麻烦,容易错误

在绝对路径中要判断请求是从哪里发过来的,如果是浏览器就必须加虚拟目录,如果是服务器内部就不需要加虚拟目录了.因为虚拟目录可能会改变,如果路径中写死了,就需要修改代码,比较麻烦.
所以虚拟路径要动态的获取,request.getContextPath(),这样虚拟目录改变也不会影响代码的执行

用response得到的流是ISO-8859-1编码 因为response对象是tomcat里的类的对象,它默认使用tomcat的字符集 如果new的话用的是java默认的字符集是GBK 设置编码是在获取流之前

验证码本质就是一张图片,作用是为了防止恶意注册

BufferedImage 对象可以创建一个内存中的图片对象 ImageIO对象可以将图片对象输出 我们将其输出到response.getOutPutStream()这个流,这样就可以在页面进行展示了
图片的0,0点就是它的左上角

image等其它资源,如果每次访问的src都一样的话,服务器会304至访问缓存,所以验证码就不会改变,所以我们要在路径后面加一个参数?+date 每次都用最新的时间,这样就都不一样了

servletContext代表的是整个web应用,可以和程序的容器(服务器)来通信
作用:1.获取文件的mime类型(根据文件的后缀名来获取的) 2.域对象,共享数据(作用范围是本项目内,生命周期很长,服务器开了就被创建了,服务器关闭才销毁) 3.可以获得项目的真实路径

可以通过request来获取 request.getServletContext() 也可以通过当前的servlet对象来获取,因为在HttpServlet中有getServletContext()的方法

mime类型:在互联网通信过程中定义的一种文件数据类型 格式 大的类型/小的类型 如text/html image/jpg

类加载器只能获取src目录直属下的文件的绝对路径,如果不是src直属文件或文件不存在则返回null
ServletContext可以获取项目的绝对路径,用getRealPath("/不含虚拟目录的文件绝对路径")可以获取文件的绝对路径,但前提是不含虚拟目录的文件绝对路径正确,此方法只起到一个拼接作用,不判断正确与否

服务器每次给浏览器响应数据要告诉浏览器响应的格式及编码,如响应图片 图片名称的解析不同浏览器厂家的解析方式不一样,中文时需要使用DownLoadUtils(自己写的,网上找)

猜你喜欢

转载自blog.csdn.net/wwzzh1989/article/details/89310232