servlet笔记

servlet笔记

看的老杜的视频

servlet是javaee的规范之一 规范就是接口

servlet是javaweb的三大组件之一。 分别是servlet 程序 Filter过滤器 LIstener监听器

servlet是运行在服务器上的java小程序 他可以接受客户端发送的请求 并响应数据数据给客户端

浏览器—webapp webapp就是某个服务器的文件 在web文件中有我们编写的java html等各种程序 在webapp中开发的各种规范就是servlet
只有规范统一 我们在一个服务器中写的webapp就可以应用于其他服务器

jdbc我们是负责调用 而我们写的appweb则是实现者 等待服务器调用

浏览器—(http)—web服务器----(servlet)----服务器端小java程序----(jdbc)-----数据库
向上被调用 向下调用
servlet都是javaee规范 serv表示服务器端 let表示小程序

tomcat从浏览器中读取到一个路径 然后在web.xml中查询这个路径所对应的java小程序 然后通过反射机制创建对象 最后调用service方法

模拟总结:servlet是一套接口 里面有一个service方法 规定java程序必须实现该方法 在web.xml中绑定查询路劲和小java程序
tomcat从浏览器中读取到一个路径 然后在web.xml中查询这个路径所对应的java小程序 然后通过反射机制创建对象 最后调用service方法
因为每个java程序都实现了sevrvice接口 所有就会实现该java类

注意表单提交的时候action和web里面的pattern保持一致

一个学了servlet GenericServlet httpservlet
servletconfig servletcontext
Servletrequest Servletresponse
httprequest httpresponse

firstweb 固定的格式
WEB-INF(文件夹) 包含 : classes(文件夹:java程序的calss文件) lib(文件夹:放jar包) web.xml(主要配置请求路径和servlet类名之间的绑定关系)

servlet包括5个方法 init service destory getServletInfo ServletConfig getServletConfig

web.xml规范

<?xml version="1.0" encoding="UTF-8"?>

随便写但必须与下面保持一致 要绑定的java程序的名字 访问的虚拟路径 必须以/开头

默认情况下 servlet对象在web服务器启动阶段不会被实例化 【若希望在web服务器启动阶段实例化servlet对象 需要进行特殊的设置】
调用顺序init service destory

servlet对象的生命周期
1.用户输入URL
2.web容器截web.xml中找请求路径
4.若没有找到对应的servlet对象(该类还没有被实例化)
通过web.xml中的相关配置信息 得到路径
通过反射机制完成servlet对象的实例化
web容器调用init犯法完成初始化
web容器调用service方法
5.若找到对应的servlet对象(已经被实例化)
直接调用service方法提供服务
6.web容器关闭的时候 web容器会把servlet对象销毁 在销毁之前 会调用destory方法

servlet对象先实例化 然后用init初始化 然后调用service方法(用户请求一次 调用一次) destory只会调用一次(在调用的时候 servl还没有被销毁 而是即将被销毁)
servlet对象是单例 但不符合单例模式 只能被称为伪单例
真单例的构造方法是私有化的 tomcat服务器是支持多线程的 所有servlet对象狮子啊单例多线程环境下的运行

如果想在服务器加载之前实例化和初始化 在servlet添加1 这个数字越小级别越高

init是在初始化时刻执行一些操作
service请求的处理以及完成响应
destory 结束时需要操作的代码

servletconfig接口
servletconfig是一个servlet对象的配置信息
servletconfig对象封装了一个servlet对象的配置信息
servlet对象的配置信息到web.xml
一个servlet对象对应到一个servletconfig对象

servletconfig接口是在init方法中的 如果想要在sevice方法中调用 就必须声明一个全局变量 然后在init中初始化 最后在service中使用
private ServletConfig config;          this.config=config(写在init方法中 ) 


servletconfig接口常用方法(里面也会有各种初始信息,也就是在web.xml中有所有servlet对象的数据 每个servlet对象都需要初始数据 这个数据可以通过servletconfig调用)
String getInitParameter(String name)  通过name返回value  初始化参数 也就是再web.xml中写入每个servlet的初始化参数  
    <init-param>
      <param-name>driver<>
      <param-value>com.myssql.jdbc.driver<>
    </init-param>  写在对应的web.xml中的每一个servlet标签里面

Enumeration getInitParameterNames() 获取所有初始化参数的name
Enumeration<String> names=config.geyInitParameterNames()  
String getServletName()   返回servletname

servletcontext接口
多个servlet共享一个servletcontext
config.getServletContext 通过config返回context

一个servlet对应一个servletconfig  所有的servlet共享一个servletContext对象
一个webapp只有一个web.xml文件和servletContext对象   web.xml在文件服务器启动阶段被解析 ServletContext在启动姐u但被实例化 关闭阶段被销毁
ServletContext对应的是web.xml文件是web.xml的代表 在同一个webapp中所有的servlet对象共享一个四周环境对象
所有的用户想共享一个数据可以把这个数据放到servletcontext对象中

ServletContext中的方法
web.xml文件中配置上下文参数 这些信息被自动封装到servletcontext对象中
<context-param>
  <param-name><param-name>
  <param-value></param-value>
</context-param>

void setAttribute(String name,Object object)向servletcontext中添加数据  后面那个object可以是字符串也可以是一个类
 object getAttribute(String name)从servletcontext范围中获取数据
 void removeAttributer(String name)移除servletcontext范围中的数据

String getInitParameter(String name)  通过name返回value

Enumeration getInitParameterNames()获取上下文初始化参数的name
Enumeration<String> names=a.geyInitParameterNames()
循环用while while(names.hasMoreElements()){ String name=names.nextElement() String value=a.getInitParameter(name)}

String getRealPath(String path) 获取文件的绝对路径

一般把servletContext变量命名为application

总结:
servletconfig就是再web.xml中的每一个servlet标签中(这个标签中包含url和实体类)中写入数据(这个数据一般用来初始化这个类) 只能在该servlet中调用这个数据
servletcontext就是在整个wev.xml中写入数据 所有的servlet都可以调用 可以通过web.xml中添加数据 也可以在java程序中添加(这个情况下添加只能在该次会话中使用)

添加欢迎页面在web.xml中写

welcome.html

主要该html文件要在web目录下 欢迎页面可以设置多个 越上面的级别越高 如果不以/开头则该文件必须与WEB-INF一个级别
欢迎页面不一定是html 也可以是servlet对象

常见错误代码
404 NOT FOUND 资源未找到 请求路径写错了
500 Server Inner Error 服务器内部出现问题 一般java程序出现异常
正常响应是200

错误信息的页面可以重新设置

<error-page>
    <error-code>404</error-code>
    <location>/error/error.html</location>
</error-page>

我们可以自己写一个适配器(也就是实现一个接口 对常用的方法抽象化 增添里面原来没有的方法 供子类使用)
这个适配器也是一个servlet对象 以后继承这个就可以 在其他java程序中 可以多使用这种适配器 是代码优雅
为什么要有抽象这种方法 就是利于这种适配器 这样可以不用 每一个子类都继承一个父类的所有方法 而是挑有用的去抽象继承
抽象类必须有抽象方法 而他的子类必须重写抽象方法 同时也可以使用父类的其他方法 所有在一个大的类中 我们主要在一两个方法中使用的时候 就可以把他抽象化 然后通过子类继承 重写抽象方法来实现

在写适配器的时候 如果init被重写 则下面可能会出问题 所有我们用final修饰不 想他在子类中被修改
但这样我们就无法在运行初期执行代码(只执行一次) 所以在适配器中在写个void init()无参数的方法 在init中直接调用 在子类中重写无参的init方法 就可以达成目标

GenericSeverlet实现原理如上 实现了sevlet 和config接口
GenericSeverlet是对servlet的优化

http协议
请求协议包括:请求行 消息报头 空白行 请求体
请求行包括:请求方式 URI 协议版本号
空白行专门用来分离消息报头和请求体的

响应协议包括 状态行 响应报头 空白行 响应体

状态码 200正常 404资源未找到 500服务器内部错误

只有当表单form 并且将form标签的method属性设置为post的时候才是post请求
其余都是基于get方式

get是在请求行上提交数据 也就是说在地址栏会有显示
格式:urk?name=value&name=value
在请求行上提交数据 所以数据长度有限制
只能提交字符串数据
最终的结果最后会被浏览器缓存收纳

post 在请求体中提交数据 相对安全
格式 name=value$name=value
在请求体中提交数据 所以数据长度没有限制
可以提交任何类型的数据 包括视频等等
最后的结果 不会被浏览器缓存收纳

1.有敏感数据使用post
2.传送数据不是普通字符串 用post
3.传送数据非常多 用post

get请求多数情况下是从服务器中读取资源 这个读取的资源在短时间之内是不会发生变化的所以 get请求的数据被浏览器缓存起来了
post请求是为了修改服务器的资源 每一次的修改结果是不同的 最终结果没有必要被缓存起来

浏览器将资源缓存之后,缓存的资源和某个特定的路径绑定在一起,只要浏览器再发送这个相同的路径 这个时候就会去缓存中获取资源
不在访问服务器 提高效率 减少用户的压力

有时候不希望走缓存 而是每一次都访问服务器 可以在请求路径后面添加时间戳

前端的页面发送的请求方式应该和服务器需要的请求方式一致

http的请求信息全部信息被封装到httpservletrequest中
在这个接口中有个方法叫做String getMetod() 可以获取请求方式
首先把service里的两个参数强制转换成带有htpp的接口 然后实例化在使用
httpservletrequest a=(httpservletrequest) request

如果一个类实现的接口是httpservlet 因为该类中没有service方法 所以会走httpsevlet中的service方法
当浏览器发送的请求和该类要求的发送方式不一致 会自动走另外一个发送方式的方法
也就是说我在类中只要写doget方法 如果浏览器传的是post会自动走httpservlet中dopost方法

httpservlet是针对浏览器发送请求这一要求对servlet的再一次优化

servlet GenericSeverlet httpservlet
以后只要继承httpservlrt就行 是get 就用doget 是post就用dopost
理解:servlet是最原始的也是最全面的有5个方法 init中有config service中有ServletRequest和ServletResponse
GenerServlet 继承自servlet 但是更优化了init方法不允许直接调用 并且把srvice作为抽象方法 init中的config接口 也通过方法实现 可以直接调用 这样子类就只要写一个service方法 且可以直接调用原来init中的config接口
HttpServlet 继承于GenerServlet 更加的优化 并且提供检测浏览器的请求方式 在子类中只要重写你想要的请求方式 把他对应的方法当作main即可 因为tomcat启动的时候会调用servlet方法 因为该类中没有会到父类中找 找到之后 继续执行是post就执行dopost
实际上dopost和doget都是封装在service方法里面的 浏览器的请求是哪个就调用哪个
就是保证前后端的请求方式相同 不同要报错

httpservletrequest接口
一次请求对应一个httpservletrequest
封装了http请求协议的全部内容
表单提交的数据会被封装到request对象中 request对象中有Map集合存储这些数据
map集合的kye是name value是一个一维数组

常见方法
String getParameter(String name) 通过key获取这个一维数组的首元素(通常情况下这个一维数组只有;一个元素所有使用较多)
MAp getParametermap() 获取整个map集合
Enumberation getParametNames() 获取整个map集合的所有key
String[] getParametValues(String name) 通过map集合key获取value

String getRemoteAddr()获取客户端IP地址
String getContextPath() 获取上下文路径 (这个webapp的根路径 也就是这个webapp的项目名)
String getMethod()获取浏览器的请求方式
String getRequestURI() 获取请求的URI 在webapp中这个java程序所在的位置/web_1/test
StringBuffer getRequestURL() 获取请求的URL 在浏览器栏中的地址localhost:8080/web_1/test
String getServletPath()获取请求的servlet path java程序的自身位置/test 也就是web.xml中patterb标签中的位置

(servletcontext也有下面方法)void setAttribute(String name,Object object)向request中添加数据 后面那个object可以是字符串也可以是一个类
object getAttribute(String name)从request范围中获取数据
void removeAttributer(String name)移除request范围中的数据

request.getSession() 返回一个session对象 参数可以为true 获取当前session若没有则新建session 若为false 获取当前session 若没有则返回null

RequestDispatcher getRequestDispatcher(String path)
request只能完成在同一次请求中传输数据
要想使几个servlet对象在同一个请求中 就要使用转发技术 也就是可以共用一个request
就是执行完a 跳转到b
转发:1.获取请求转发器 2.。调用请求转发器的forward方法
RequestDispatcher dispatcher=request.getRequestDispatcher(“另一个需要转发的地址例如testweb”)
dispatcher.forward(request,resonse)

也可以上面两个连起来写request.getRequestDispatcher("webtest").foward(request,response)

重定向 redirect 实质上是 跳转到了指定的地址 两次请求 不是同一个request
response.sendRedirect("/webtest/b") response.sendRedirect(request.getContextPath+"/b")
重定向的原理 response.sendRedirect("/webtest/a")
浏览器执行到上述代码会将请求路径发送给浏览器 浏览器又会想服务器发送一次全新的请求 所有地址栏上显示的是该路径

  转发和重定向的相同点和不同点
      相同点:都可以完成资源的跳转
      不同点:转发是request对象触发的    重定向是respnse对象触发的
              转发是一次请求地址栏不会发生变化 也就是还在原页面 重定向是两次请求 地址栏上的地址会发生变化 也就是发生了页面改变
              转发是在本项目内部完成资源跳转 重定向可以完成跨app跳转资源
              重定向的路径需要加webapp的根路径 
  
  若想完成跨app跳转必须用重定向 
  重定向可以解决浏览器刷新问题
  若想在上一个组员中向request范围中存储了数据 希望在下一个资源从request范围中取出就用转发

  重定向可以解决刷新问题 
  也就是重定向跳转到一个页面 无论该页面怎么属性都和 之前的页面以及程序无关 所有刷新是可以的
  如果采用转发跳转 则还是之前的页面 刷新之后 之前的页面的程序还会在执行一次

void setCharacterEncoding(String env)

Servletrequest 和servletContext 都可以共享数据
ServletContext范围更大 整个浏览器运行过程都可以存取接受数据
Servletrequest范围小 只可以用于一次请求 如果想两个程序共享数据要用转发技术

httpServletresponse方法
PrintWriter out = response.getWriter();
response.setHeader(“content-type”, “text/html;charset=UTF-8”);
out.write(data);

怎么解决线程安全问题
1.不使用实例变量 尽量使用局部变量
2.若必须使用实例变量 可以考虑将该对象编程多例对象 一个线程一个java对象 实例变量的内存也不会共享
3.若必须使用单例,那就只能使用synchronized线程同步机制 线程一旦排队执行 则吞吐量降低 降低用户体验

servlet只能是单例的

cookie
常见功能:保留购物车的状态在客户端上
十天免登录
cookie被当作类来处理 用new创建cookie对象
Cookie cookie=new cookie(“username”,“张三”)
cookie分为两部分 name和value 都是字符串String类型
服务器可以一次向浏览器发送多个cookie 默认情况下 浏览器将cookie保存在缓存中 只要浏览器不关闭cookie永远存在
cookie和访问路径有关
/web/test/test_1 cookie会和test绑定在一起 只要发送test请求cookie就一定会提交给服务器

setPath 设置cookie的关联路径 cookie1.setPath("")
cookie.setPath(“web_1/king”) 只有同时发送web_1/king cookie浏览器才会提交

cookie可以设置有效时长 只要这个有效时长大于0 该cookie就会被保存到客户端硬盘中
setMaxAge() 单位是秒

response.addCookie(cookie) 将cookie对象发送给浏览器
request.getCookies() 返回cookie数组 用增强for循环遍历 和getname getvalue可以获取值

1.创建cookie对象
2.设置有效时间
3.设置关联路径
4.发送cookie给浏览器

十天内免登录流程
1.先用一个类判断是否有cookie 没有cookie直接跳转到登录页面
2.登录的时候 可以选择是否十天登录 若选了创建cookie对象并保存
3.如果有cookie 获取cookie里的值
4.用获取的值和数据库进行比较 正确跳转到欢迎页面 错误跳转到登录界面

httpsession
session表示会话 cookie可以将会话状态把保存到客户端 httpsession可以把会话状态保存在服务器
request.getSession 来获取session

httpSession对象是一个会话级别的对象 一次会话对应一个httpsession
在会话进行过程中 web服务器一致为当前这个用户维护着一个会话对象 httpsession

用getsession的时候会首先看一下有没有对应的cooki若存在就不会生成且一直使用 直到浏览器关闭 cookie失效

打开浏览器在浏览器上发送首次请求
服务器会创建一个httpsession对象 代表一次会话 同时生成对应的cookie对象 cookie对象的name是JSESSIONID value是32位字符串
服务器将cookie的value和httpsession对象绑定到session列表中
服务器将cookie发送给浏览器客户端
浏览器客户端将cookie保存到缓存中 只要浏览器不关闭 cookie不会消失
当服务器再次发送请求的时候 会自动提交缓存中的cookie 当服务器接收到cookie 验证cookie中的name是JSESSIONID 然后获取该cookie中的value
通过cookie中的value取session列表中检索对应的httpsession

浏览器关闭之后服务器不会销毁session对象
当很长一段时间 没有用户再访问session对象 此时服务器自动回收session对象
这个时间可以设置 在web.xml里面设置
120<><> 默认是30分钟
一次会话:
一般来说是 用户打开浏览器到关闭浏览器 表示一次会话结束
本质上是:从session对象的创建到最终session对象的销毁

httpsession中常用的方法
void setAttribute(String name,Object value) 存储数据
Object getAttribute(String name) 根据name读取值
void removeAttribute(String name)根据name删除数据
void invalidate() 销毁session

关于路径问题
class里面是包名+类名 web.loginservlet web是包名
pattern里面是自定义的路径 /loginservlet
action里面是项目名+自定义的路径 /web_login/loginservlet 是访问路径 表单里的action会直接提交这个路径
a标签 href="/项目名/资源路径"

转发 request.getRequestDispatcher(“资源路径”).forward( )
重定向 response.sendRedirect(“项目名/资源路径”)
这个资源路径是在pattern里面设计的

servletcontext httpsession httpservletequest范围比较
httpservletrequest 是请求范围
httpsession是会话范围
servletcontext是应用范围

请求范围:就是在一个页面中实现数据共享 页面跳转不能实现共享
会话范围:同一个用户的多个页面可以实现数据共享
应用范围:只要是在这个程序中的数据都可以共享

servletcontext可以完成跨会话共享数据
session可以完成跨请求传递数据 但是这些请求必须在同一个会话当中
request完成跨servlet共享数据 但这些servlet必须在同一个请求当中

从小到大使用 优先使用小范围

session就是一个用户使用一个 一个用户代表一次会话
context多个用户使用一个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值