Servlet
Servlet
开发流程
编写一个java类,直接实现HttpServlet接口或者通过扩展实现这个这个接口的类
重写HttpServlet类的doGet方法和doPost方法
配置web.xml文件,或者使用注解对servlet进行配置
Servlet是一个接口,如何继承这个接口,就需要实现接口中的所有的方法。而HttpServlet继承了这个接口,就代表已经实现了关于Servlet的所有接口,并且比较规范和实用。我们只需要通过HttpServlet中的doPost()和doGet()方法去实现业务逻辑既可以。
流程
客户端发送请求至服务器
服务器依据Servlet映射找到对应的Servlet
Servlet依据客户端请求生成响应内容并将其传给服务器
服务器将响应返回客户端
网页->url-pattern->servlet-name->servlet-class->解释字节码->响应
servlet配置
使用web.xml配置
<!--
注册servlet
使用标签:<servlet>
<servlet-name>:名称,为这个servlet起名
<servlet-class>:路径
-->
<servlet>
<servlet-name>ServletDemo</servlet-name>
<servlet-class>mian.java.com.servlet.test.ServletDemo</servlet-class>
</servlet>
<!--
servlet映射
<servlet-name>确定使用哪一个servlet
<url-pattern>浏览器访问的路径,要求/开头且名称唯一
-->
<servlet-mapping>
<servlet-name>ServletDemo</servlet-name>
<url-pattern>/ServletDemo</url-pattern>
</servlet-mapping>
public class ServletDemo implements Servlet{
}
使用注解配置
@WebServlet("/test")
public class test extends HttpServlet {
}
生命周期
@WebServlet("/test")
public class test implements Servlet {
@Override
public void init(ServletConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
}
第一次请求:
调用构造函数
获取init()方法
调用init,服务器创建ServletConfig对象,作为实参
获取service()方法
调用service,服务器创建ServletRequse和ServletResponse,作为实参
第二次请求
从缓存中获取class
获取service方法↓
调用service服务器先创建ServletRequest ServletResponse
服务器关闭
获取class
获取destory方法
调用
init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet从“出生”到“工作”再到“死亡 ”的过程。Servlet容器(例如TomCat)会根据下面的规则来调用这三个方法:
1.init( )方法,当Servlet第一次被请求时Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,但是这个方法在后续请求中不会在被Servlet容器调用。我们可以利用init( )方法来执行相应的初始化工作。调用这个方法时,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化。例如数据库连接初始化。
2.service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。
3.destory( )方法,当要销毁Servlet时,Servlet容器就会调用这个方法,在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码
另外:
getServletInfo( ),这个方法会返回Servlet的一段描述,可以返回一段字符串。
getServletConfig( ),这个方法会返回由Servlet容器传给init( )方法的ServletConfig对象。
GenericServlet
HTTPServlet
@WebServlet("/test")
public class test extends HttpServlet {
public test() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
doGet和doPost
不同点一:
通过get方式提交的数据有大小的限制,通常在1024字节左右。也就是说如果提交的数据很大,用get方法就可需要小心;而post方式没有数据大小的限制,理论上传送多少数据都可以。
不同点二:
通过get传递数据,实际上是将传递的数据按照”key,value”的方式跟在URL的后面来达到传送的目的的;而post传递数据是通过http请求的附件进行的,在URL中并没有明文显示。
不同点三:
通过Get方式提交的数据安全性不高,而Post方式的更加安全
Servlet 接口中定义的方法
ServletConfig
当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象。可以获得配置参数
ServletContext
ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。
通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。
有了ServletContext对象,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中。保存在ServletContext中的对象被称作属性。
1、共享数据
在这个Servlet中保存的数据,可以在另外一个servlet中拿到
主要方法:
setAttribute(String var1, Object var2);
removeAttribute(String var1);
getAttribute(String var1);
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
ServletContext context = this. getServletContext();
String username = "patrick";//数据
context.setAttribute("username", username);//将一个数据保存在ServletContext中
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
ServletContext context = this. getServletContext();
String username = (String)context.getAttribute("username");
resp.getWriter().print("name"+username);
}
2、获取初始化参数
<!--配置一些web应用初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
3、请求转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
//requestDispatcher.forward(req,resp); //调用forward实现请求转发;
context.getRequestDispatcher("/gp").forward(req,resp);
}
//在服务器内部请求Demo04转到gp,Demo04从gp获取资源
Requset
Servlet容器对于接受到的每一个Http请求,都会创建一个ServletRequest对象,并把这个对象传递给Servlet的Sevice( )方法。其中,ServletRequest对象内封装了关于这个请求的许多详细信息。
String getContextPath();//返回请求上下文的请求URI部分
Cookie[] getCookies();//返回一个cookie对象数组
String getHeader(String var1);//返回指定HTTP标题的值
String getMethod();//返回生成这个请求HTTP的方法名称
String getQueryString();//返回请求URL中的查询字符串
HttpSession getSession();//返回与这个请求相关的会话对象
获取前端参数并请求转发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 这里超交的路径,需要寻找到项目的路径
${pageContext.request.contextPath}代表当前的项目
-->
<form action="form" method="get">
<span>用户名</span><input type="text" name="username"><br>
<span>密码</span><input type="password" name="password"><br>
<span>爱好</span>
<input type="checkbox" name="hobbys" value="1">阅读
<input type="checkbox" name="hobbys" value="2">写作
<input type="checkbox" name="hobbys" value="3">音乐
<input type="checkbox" name="hobbys" value="4">敲代码
<br>
<input type="submit" name="submit">
</form>
</body>
</html>
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应的编码格式为UTF-8编码,否则发生中文乱码现象
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//1.获得请求方式
String method = request.getMethod();
//2.获得请求的资源相关的内容
String requestURI = request.getRequestURI();//获得请求URI
String webName = request.getContextPath();//获得应用路径(应用名称)
String querryString = request.getQueryString();//获得查询字符串
//3.获得前端
String username = request.getParameter("username");
String password = request.getParameter("password");
String hobby = request.getParameter("hobbys");
String[] hobbys = request.getParameterValues("hobbys");
System.out.println("==========");
//后台接收中文乱码问题
System.out.println(username);
System.out.println(password);
System.out.println(hobby);
System.out.println(Arrays.toString(hobbys));
System.out.println("============");
System.out.println(request.getContextPath());
System.out.println(username+":"+password);
response.getWriter().write("method(HTTP方法):"+method+"<br>");
response.getWriter().write("requestURi(请求URI)" + requestURI + "");
response.getWriter().write("webname(应用名称):<" + webName + "<br>");
response.getWriter().write("querrystring(查询字符串):" + querryString + "");
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
Response
响应
addCookie(Cookie var1);//给这个响应添加一个cookie
addHeader(String var1, String var2);//给这个请求添加一个响应头
sendRedirect(String var1) throws IOException;//发送一条响应码,讲浏览器跳转到指定的位置
setStatus(int var1);//设置响应行的状态码
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;
负责向浏览器发送数据的方法:
下载文件
要获取下载文件的路径
下载的文件名是啥?
设置想办法让浏览器能够支持下载我们需要的东西
获取下载文件的输入流
创建缓冲区
获取OutputStream对象
将FileOutputStream流写入到bufer缓冲区
使用OutputStream将缓冲区中的数据输出到客户端!
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
String realPath = this.getServletContext().getRealPath("/1.png");
System.out.println("下载文件的路径:"+realPath);
// 2. 下载的文件名是啥?
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码
resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
// 5. 创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6. 获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
// 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端!
while ((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}
实现重定向
B一个web资源收到客户端A请求后,B他会通知A客户端去访问另外-一个web资源C,这个过程叫重定向
response.sendRedirect(location);
重定向到location
resp. setHeader("Location","/r/img");
resp. setstatus (302);
重定向和请求转发
相同点:页面会跳转
cookie&session
保存会话的两种技术
cookie
客户端技术 (响应,请求)
session
服务器技术,利用这个技术,可以保存用户的会话信息,可以把信息或者数据放在Session中
cookie
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
解码
URLEncoder.encode("name","utf-8")
URLDecoder.decode(cookie.getValue(),"UTF-8")
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
//Cookie,服务端从用户端获取
Cookie[] cookies = request.getCookies();//这里返回数组,说明cookie存在多个
//判断cookie是否存在
if (cookies!=null) {
//如果存在
out.write("你上一次访问的时间");
for (int i=0;i<cookies.length;i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (cookie.getName().equals("lastLoginTime")) {
//获取值
out.write(URLDecoder.decode(cookie.getValue(), "UTF-8"));
}
}
}else {
out.write("这是您第一次访问本站");
}
//服务器给客户响应一个cookie
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
response.addCookie(cookie);
}
session
Session:
服务器会给每一个用户(浏览器)创建一个Seesion对象;
一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
用户登录之后,整个网站它都可以访问!–> 保存用户的信息;保存购物车的信息……
…
…
…
Session和cookie的区别:
Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)
Session对象由服务创建;
使用场景:
保存一个登录用户的信息;
购物车信息;
在整个网站中经常会使用的数据,我们将它保存在Session中
<!--设置Session默认的失效时间-->
<session-config>
<!--15分钟后Session自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
获取session
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//解决乱码问题,设置浏览器响应格式
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
//得到Session
HttpSession session = request.getSession();
String name = (String) session.getAttribute("name");
System.out.println(name);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//解决乱码问题,设置浏览器响应格式
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
//得到Session
HttpSession session = request.getSession();
//给Session中存东西
session.setAttribute("name","patrick");
//session.setAttribute("name",new Person("patrick",1));
//获取Session的ID
String sessionId = session.getId();
//判断Session是不是新创建
if (session.isNew()){
response.getWriter().write("session创建成功,ID:"+sessionId);
}else {
response.getWriter().write("session以及在服务器中存在了,ID:"+sessionId);
}
//Session创建的时候做了什么事情;
// Cookie cookie = new Cookie("JSESSIONID",sessionId);
// resp.addCookie(cookie);
}