搞懂Servlet
1.什么是Servlet
Servlet是运行在服务器上的一个小程序,用来接受客户端发送过来的请求,并响应给客户端。
2.Servlet的作用功能
- 接受客户端发送过来的请求,并响应给客户端
Servlet是一个服务器中的一个Java小程序,用来处理浏览器的请求和相应。浏览器发送请求之后,Servlet拦截下来,通过类库解析http协议,在服务器运行程序,然后将得到的结果响应给客户端。但是Servlet和html的组织方式不友好,需要Java程序员既要懂后端开发,也要懂前端开发。这时候就出现了Jsp页面,将Java程序嵌入到html中,当客户端请求jsp资源的时候,jsp类库会把jsp资源解析成Servlet的Java源代码。所有Jsp本质上是一个Servlet程序。
3.Hello World入门
3.1实现Servlet
- 编写一个类实现Servlet,实现里面的方法,有五个方法需要被实现,其中service是专门用来处理请求和相应的
- 编写响应代码,输出hello servlet
- 这个时候需要告诉客户端,怎么来访问HelloServlet程序,在web.xml中进行配置
public class HelloServlet 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("hello servlet");
}
//信息
@Override
public String getServletInfo() {
return null;
}
//销毁
@Override
public void destroy() {
}
}
配置web.xml
<servlet>
<servlet-name>HelloServlet</servlet-name>
<!--全类名-->
<servlet-class>com.xiaolong.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<!--访问地址,其中/表示http:localhost:8080/项目名/-->
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
访问:http:localhost:8080/项目名/helloServlet
访问流程:
通过ip地址和端口定位到tomcat服务器,然后通过项目名定位到服务器中运行的哪个程序,最后在web.xml中找到helloServlet对应的全类名,运行HelloServlet这个程序。
3.2实现HttpServlet
HttpServlet实现了Servlet的所有方法,并且添加了HTTP协议处理方法,比Servlet接口功能更强大。
- 编程类继承HttpServlet
- 根据业务重写doGet或doPost方法
- web.xml中配置访问地址
在实际开发过程中,我们只需要根据实际的业务重写doGet或者doPost方法即可
public class HelloHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
配置web.xml
<servlet>
<servlet-name>HelloHttpServlet</servlet-name>
<servlet-class>com.xiaolong.servlet.HelloHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloHttpServlet</servlet-name>
<url-pattern>/helloHttpServlet</url-pattern>
</servlet-mapping>
3.3IDEA创建
在IDEA中可以一键创建
4.Servlet的什么周期
- 加载Servlet,创建Servlet实例
- 初始化,Servlet被实例化后,会调用init方法进行初始化
- 调用service处理业务,每次访问Servlet都会调用service来处理业务
- 调用destory,在web工程停止的时候会调用destory来进行销毁
注意:第1和第2只有在第一次访问Servlet的时候才会被调用
访问细节:
- Servlet是单例的,Servlet对象一旦创建了就会一直存在内存中,直到服务器挂关闭
- 每次请求,Servlet都会创建新的HttpServletRequest和HttpServletResponse对象,把两个对象作为参数传递给service方法,然后再根据请求方式调用doPost或者doGet方法
5.ServletConfig对象
作用:
- 获取servlet配置中的初始化参数
- 获取servlet的别名
- 获取ServletContext对象
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
//获取别名
String servletName = servletConfig.getServletName();
System.out.println(servletName);
//获取初始化参数
String username = servletConfig.getInitParameter("username");
System.out.println(username);
System.out.println(servletConfig.getServletContext());
}
<servlet>
<servlet-name>HelloHttpServlet</servlet-name>
<servlet-class>com.xiaolong.servlet.HelloHttpServlet</servlet-class>
<!--初始化参数-->
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloHttpServlet</servlet-name>
<url-pattern>/helloHttpServlet</url-pattern>
</servlet-mapping>
6.ServletContext对象
6.1什么是ServletContext对象
- ServletContext是一个接口,表示Servlet上下文对象
- ServletContext对象是一个域对象
- ServletContext在web工程启动的时候创建,在web工程停止的时候销毁,且一个web工程只有一个ServletContext对象实例
什么是域对象
域对象, 是可以像 Map 一样存取数据的对象, 叫域对象。这里的域指的是存取数据的操作范围, 整个 web 工程
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
6.2ServletContext对象的作用
- 获取web.xml中的上下文参数,ServletConfig获取的是单个Servlet的参数
- 像Map一样存取数据
- 获取资源路径
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletConfig().getServletContext();
//获取上下文参数
String password = context.getInitParameter("password");
//像map一样存取数据
context.setAttribute("name","root");
String name = (String)context.getAttribute("name");
System.out.println(name);
//获取当前工程路径
String contextPath = context.getContextPath();
//获取工程部署路径
String realPath = context.getRealPath("/");
//获取工程下的资源路径
String realPath1 = context.getRealPath("/css");
}
<!--上下文参数,属于整个web工程-->
<context-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</context-param>
注意:
我们以前读取⽂件的时候,如果程序和⽂件在同⼀包名,可以直接通过⽂件名称获取得到的!原因很简单, 以前我们写的程序都是通过JVM来运⾏的,⽽现在,我们是通过Tomcat来运⾏的,根据web的⽬录规范, Servlet编译后的class⽂件是存放在WEB-INF\classes⽂件夹中的。所以需要先获取到路径,然后再读
7.HttpServletRequest对象
7.1HttpServletRequest的作用功能
每次有请求进入Tomcat服务器,Tomcat就会把请求的HTTP协议内容解析好封装在HttpServletRequest对象中,然后将HttpServletRequest对象传递给doGet和doPost待用,我们可以利用HttpServletRequest对象,获取到所有请求的信息。
7.2 HttpServletRequest的常用方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
System.out.println("username:"+req.getParameter("username"));
//获取URL
System.out.println("url:"+req.getRequestURL());
//获取访问的ip
System.out.println("ip:"+req.getRemoteHost());
//获取请求方法
System.out.println("method:"+req.getMethod());
//设置域数据和获取域数据
req.setAttribute("eamil","123@163.com");
System.out.println(req.getAttribute("email"));
}
测试表单
<body>
<form action="/ServletReview/helloHttpServlet" method="get">
username:<input type="text" name="username"><br/>
password<input type="password" name="password"><br/>
<input type="submit">
</form>
</body>
7.3HttpServletRequest的应用
防盗链
作用:
防止别人复制我的资源的访问地址,也就是如果想要访问我的资源,必须在我的主页中来获取
//防盗链
//获取请求的来源
String referer = req.getHeader("Referer");
//如果不是从我的index的请求,则返回到我的首页
if (referer == null || referer.contains("localhost:8080/ServletReview/index.jsp")){
resp.sendRedirect("/ServletReview/index.jsp");
}
中文乱码
doPost的解决办法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//防止中文乱码
req.setCharacterEncoding("UTF-8");
}
doGet的解决办法
post的请求数据是封装在请求对象中的,而get的请求数据是从消息行中过去的,所以通过请求对象的设置编码没有效果,只能
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
//先以iso-8859-1编码,再UTF-8解码
username = new String(username.getBytes("iso-8859-1"),"UTF-8");
}
请求的转发
什么是请求转发
请求转发就是,服务器收到请求后,从一个资源跳动另外一个资源的操作叫做请求转发,其中浏览器中的地址没有发生变化,他们一起是一次请求。
请求转发的特点:
- 是一次请求
- 浏览器地址栏没有发生变化
- 共享Request域中的数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取对象转发到index.jsp页面
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/index.jsp");
//实现转发,并将req和resp对象传入,因为是共有数据呀
requestDispatcher.forward(req,resp);
}
8.Response对象
8.1HttpServletResponse对象的作用
需要设置返回给客户端的数据都是通过HttpServletResponse对象来设置的,HttpServletResponse封装了响应消息。
8.2HttpServletResponse的常用方法
字节流:getOutPutStream()
字符流:getWriter()
注意:两个流只能同时使用其他的一个
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码问题
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("回传数据");
}
8.3HttpServletResponse的应用
请求重定向
点击一个超链接,通知浏览器跳转到另外的一个页面的就交重定向跳转。一般可能是这个页面废弃了,通知你去另外一个页面。
response.sendRedirect("/ServletReview/index.jsp");
特点:
- 浏览器地址栏会发生变化
- 是两次请求
- 因为是两次请求,所有是两个不同的Request对象,所以不共享数据
- 跳转链接,需要写项目名
请求重定向和请求转发对比
两个都是跳转页面,
区别:
- 请求转发是发生的服务器上,请求重定向是发生在浏览器上。
- 转发是服务器跳转,所以只能访问当前工程的应用资源;重定向是浏览器跳转,请求地址发生变化,可以访问其他工程应用的资源
- 转发的/:因为只能在当前工程,所以是带工程名字的。重定向的/:后面需要加上工程名,因为不一定是在本工程下。
9.会话技术
什么是会话
会话是浏览器和服务器之间的多次请求和相应。从浏览器访问服务器开始,到访问服务器结束流浪器关闭为止的这段时间产生的多次请求和响应,称为浏览器和服务器之间的一次会话
为什么实用会话技术
目的是为了保存用户的一些数据,方便以后用户再次访问的时候使用。
因为之前的Request只能保存一次请求的数据,所有不用使用,ServletContext是整个web应用共享用的,将数据保存到这里,将无法区分具体信息的归属。所以这里将使用Cookie和session形式来存储会话的数据。
分类
将会话技术分为两大类
-
客户端会话技术:Cookie
-
服务器会话技术:Session
9.1 Cookie
Cookie的功能
客户端和服务器之间是通过Http协议来传输数据,因为HTTP协议是无状态的协议 ,数据提交完之后,客户端和服务器之间的连接就会关闭,再次交互还需要重新建立新的连接。
为了更方便建立连接,再第一次连接之后,服务器记录一些用户的一些数据,发送给客户端,当客户端下次访问同一个网站的时候,服务器就会主动去查询这个数据,确认用户信息。
这些数据就称为cookie。
Cookie的简单使用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建cookie对象
Cookie cookie = new Cookie("username", "root");
//设置cookie存留时间
cookie.setMaxAge(100);
//通过客户端保存cookie,原理是在响应头增加一个Set-Cookie字段
resp.addCookie(cookie);
//获取客户端提交的cookie数组
Cookie[] cookies = req.getCookies();
}
cookie的特点
- 不可跨域名性,例如访问百度的时候,客户端只会把百度服务器传递的cookie传给服务器,而不会把b站传递的cookie发给百度的服务器;
这种隐私安全机制是通过下面的方法实现的
cookied.setDomain()
cookie的安全属性
HTTP是不安全的,如果不喜欢cookie在非安全协议中传输,可以设置cookie的secure的属性为true,这样流浪器只会在HTTPS和SSL等安全协议中传输cookie
9.2 Session
什么是session
session是另外一种记录浏览器状态的机制,当客户端访问服务器的时候,服务把用户的信息,以某种形式记录在服务器中,这种被称为session。
session可以存储对象,而cookie只能存储字符串
API
/获取Session被创建时间
long getCreationTime()
//获取Session的id
String getId()
//返回Session最后活跃的时间
long getLastAccessedTime()
//获取ServletContext对象
ServletContext getServletContext()
//设置Session超时时间
void setMaxInactiveInterval(int var1)
//获取Session超时时间
int getMaxInactiveInterval()
//获取Session属性
Object getAttribute(String var1)
//获取Session所有的属性名
Enumeration getAttributeNames()
//设置Session属性
void setAttribute(String var1, Object var2)
//移除Session属性
void removeAttribute(String var1)
//销毁该Session
void invalidate()
//该Session是否为新的
boolean isNew()
session作为域对象
Session也是⼀个域对象。Session作为⼀种记录浏览器状态的机制, 只要Session对象没有被销毁, Servlet之间就可以通过,Session对象实现通讯
生命周期
Session在⽤户第⼀次访问服务器Servlet, jsp等动态资源就会被⾃动创建, Session对象保存在内存⾥,这也就为什么上⾯的例⼦可以直接使⽤request对象获取得到Session对象。如果访问HTML,IMAGE等静态资源Session不会被创建。
由于会有越来越多的⽤户访问服务器,因此Session也会越来越多。 为了防⽌内存溢出,服务器会把⻓时间没有活跃的Session从内存中删除,这个时间也就是Session的超时时间。Session的超时时间默认是30分钟,可以对Session的超时时间进⾏修改 。
在web.xml中进行配置
<session-config>
<session-timeout>20</session-timeout>
</session-config>
业务代码中设置
httpSession.setMaxInactiveInterval(60);
Session对象没有被销毁, Servlet之间就可以通过,Session对象实现通讯
生命周期
Session在⽤户第⼀次访问服务器Servlet, jsp等动态资源就会被⾃动创建, Session对象保存在内存⾥,这也就为什么上⾯的例⼦可以直接使⽤request对象获取得到Session对象。如果访问HTML,IMAGE等静态资源Session不会被创建。
由于会有越来越多的⽤户访问服务器,因此Session也会越来越多。 为了防⽌内存溢出,服务器会把⻓时间没有活跃的Session从内存中删除,这个时间也就是Session的超时时间。Session的超时时间默认是30分钟,可以对Session的超时时间进⾏修改 。
在web.xml中进行配置
<session-config>
<session-timeout>20</session-timeout>
</session-config>
业务代码中设置
httpSession.setMaxInactiveInterval(60);
注:仅用于学习交流