一、Servlet
1、Servlet简介
-
Servlet是sun公司开发动态web的一门技术
-
sun在这些API中提供一个接口叫做:Servlet, 开发Servlet程序只需完成两个步骤:
-
编写一个类,实现Servlet接口。
-
把开发好的java类部署到web服务器中。
-
把实现了Servlet接口的Java程序叫做Servlet。
2、HelloServlet
Servlet接口在Sun公司有两个默认的实现类:HttpServlet, GenericServlet
1.构建一个普通的Maven项目,删掉里面的src目录,在这里建立Moudel;这个空的工程就是Maven的主工程。
2.关于Maven父子项目的理解:
-
父项目中会有:
-
子项目会有:
父项目的jar包子项目可以直接使用。
3、Maven环境优化
-
修改web.xml为最新的
-
将Maven的结构搭建完整
4、编写一个Servlet程序
-
编写一个普通类
-
实现一个Servlet接口,可以直接继承HttpServlet
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //ServletOutputStream outputStream = resp.getOutputStream(); PrintWriter writer = resp.getWriter();//相应流 writer.print("HelloServlet!"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
3.编写Servlet的映射
为什么需要映射:我们写的java程序需要通过浏览器访问,而浏览器需要连接web服务器,,所以我们需要在web服务中注册我们的servlet,还需要给它配置一个路径(web.xml)。
<!-- 注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.hl.servlet.HelloServlet</servlet-class> </servlet> <!-- servlet的请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
4.配置Tomcat服务
注意项目发布的路径
5.测试
5、Mapping问题
-
一个Servlet可以指定一个映射路径
-
一个Servlet可以指定多个映射路径
-
一个Servlet可以指定通用映射路径
-
默认请求路径
-
指定一些后缀或前缀等等......
-
优先级问题
指定了固有的映射优先级最高,如果找不到会走默认的处理请求;
6、ServletContext
web容器在启动的时候,它会为每个web程序创建一个对应的ServletContext对象,它代表了当前的web应用;
1、共享数据
一个servlet的数据可以在另一个servlet中使用
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String username = "李白!"; context.setAttribute("user",username);//将一个数据保存在了这个ServletContext中 } }
public class GetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String obj = (String) context.getAttribute("user"); resp.setContentType("text/html"); resp.setCharacterEncoding("UTF-8"); resp.getWriter().print("user="+obj); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
2、获取初始化参数
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String url = context.getInitParameter("url"); resp.getWriter().print(url); }
<!-- 配置一些web应用初始化参数--> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:8080/mybatis</param-value> </context-param>
3、请求转发
访问路径不发生改变
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); //请求转发 context.getRequestDispatcher("/gp").forward(req,resp); }
4、读取资源文件
Properties
-
在java目录下新建properties
-
在resources目录下新建properties
发现:都被打包在同一个路径下:classes, 我们俗称这个路径为classpath;
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); Properties prop = new Properties(); prop.load(stream); String username = prop.getProperty("username"); String password = prop.getProperty("password"); resp.getWriter().print(username+" : "+password); }
7、Response
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRquest对象,代表响应的一个HttpServletResponse;
-
如果要获取请求过来的参数:找HttpServletRquest;
-
如果要获取响应的参数:HttpServletResponse;
常见应用
-
向浏览器输出数据。
-
下载文件
import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder; public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.获取文件的下载路径 String realPath = this.getServletContext().getRealPath("/img.png"); System.out.println("下载文件的路径:"+realPath); //2.下载文件名是啥 String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1); //3.让浏览器支持下载我们需要的东西,设置编码 resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); //4.获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); //5.创建缓冲区 int len; 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(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
验证码功能
import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; public class ImageServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //让浏览器3秒刷新一次; resp.setHeader("refresh","3"); //在内存中创建一个图片 BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); //得到图片 Graphics2D g = (Graphics2D) bufferedImage.getGraphics(); //设置图片背景 g.setColor(Color.WHITE); g.fillRect(0,0,80,20); //给图片写数据,生成随机数 g.setColor(Color.BLUE); g.setFont(new Font(null,Font.BOLD,20)); g.drawString(makeNum(),0,20); //告诉浏览器,这个请求用图片的方式打开 resp.setContentType("image/jpeg"); //不让浏览器缓存 resp.setDateHeader("expires",-1); resp.setHeader("Cache-Control","no-cache"); resp.setHeader("Pragma","no-cache"); //把图片写给浏览器 ImageIO.write(bufferedImage,"jpg",resp.getOutputStream()); } //生成随机数 private String makeNum(){ Random random = new Random(); String s = random.nextInt(9999) + ""; StringBuffer sb = new StringBuffer(); for (int i = 0; i <4-s.length() ; i++) { sb.append("0"); } s=sb.toString()+s; return s; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
4.请求重定向( sendRedirect() )
一个web资源收到客户端请求后,他会通知客户端去访问另一个web资源,这个过程较重定向。
常见场景:
-
用户登录
public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("/r/img"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
5.请求重定向Demo
<%--${pageContext.request.contextPath} 代表当前的项目--%> <form action="${pageContext.request.contextPath}/login" method="get"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> <input type="submit" value="提交"> </form>
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //处理请求 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username+":"+password); resp.sendRedirect("/re/success.jsp"); }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>Success</h1> </body> </html>
6.请求转发Demo
<div style="text-align: center"> <form action="${pageContext.request.contextPath}/login" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> 爱好: <input type="checkbox" name="hobbys" value="唱歌">唱歌 <input type="checkbox" name="hobbys" value="跳舞">跳舞 <input type="checkbox" name="hobbys" value="看书">看书 <input type="checkbox" name="hobbys" value="跑步">跑步 <br> <input type="submit"> </form> </div>
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); String[] hobbys = req.getParameterValues("hobbys"); System.out.println("==================="); System.out.println(username); System.out.println(password); System.out.println(Arrays.toString(hobbys)); System.out.println("==================="); //请求转发 System.out.println(req.getContextPath()); req.getRequestDispatcher("/success.jsp").forward(req,resp); }
重定向和转发的区别:
相同点:
-
页面都会实现跳转
不同的:
-
请求转发url不会改变:307
-
重定向地址发生改变:302
8、Request
HttpServletRequest代表用户端的请求,用户通过http协议访问服务器,Http中所有的请求信息会被封装到HttpServletRequest,通过其方法可以获取客户端的多有信息。
二、Cookie、Session
1、 会话
-
用户打开了一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话。
-
有状态会话:每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。
3、保存会话的两种技术
cookie
-
客户端技术(响应、请求)
session
-
服务器技术,利用这个技术可以保存用户的会话信息。我们可以把信息放到Session中.
网站登录后,第二次就不需要重新登录了。
4、cookie
-
从请求中拿到cookie信息
-
服务器响应诶客户端cookie
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置编码 req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); //获取Cookie的值 Cookie[] cookies = req.getCookies(); if (cookies!=null){//判断Cookie是否有值 out.write("您上一次访问的时间是:"); for (Cookie cookie : cookies) { if (cookie.getName().equals("LastLoginTime")){ long l = Long.parseLong(cookie.getValue()); Date date = new Date(l); out.write(date.toLocaleString()); } } }else { out.write("这是第一次访问!"); } //服务器给客户端响应一个Cookie Cookie cookie = new Cookie("LastLoginTime", System.currentTimeMillis() + ""); cookie.setMaxAge(60*60);//设置cookie存在时间 resp.addCookie(cookie); }
关于cookie的细节:
-
一个cookie只能保存一个信息;
-
一个web站可以给浏览器发送多个cookie,最多存放20个cookie;
-
cookie大小限制4kb;
-
浏览器上线为300个cookie。
删除cookie的方式:
-
不设置有效期,关闭浏览器删除cookie。
5、session
什么是session:
-
服务器会给每一个浏览器创建一个session对象。
-
一个session独占一个浏览器。
-
用户登录后,整个网站都已经登录。
session和cookie的区别:
-
Cookie是把用户的数据写给浏览器保存。
-
Session是把用户订单数据写到独占的服务器端保存。
-
Session对象由服务器创建。
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码 req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=utf-8"); //得到session HttpSession session = req.getSession(); //给session中存东西 session.setAttribute("user", new Person("李白",1)); //获取session的ID String id = session.getId(); //判断是不是新的session if (session.isNew()){ resp.getWriter().write("创建成功,session的ID为:"+id); }else { resp.getWriter().write("已经存在,session的ID为:"+id); } } HttpSession session = req.getSession(); Person person = (Person)session.getAttribute("name"); System.out.println(person.toString()); //手动注销session session.invalidate();
会话自动过期,在web.xml中配置
<!-- 设置session默认过期时间--> <session-config> <!-- 一分钟后过期--> <session-timeout>1</session-timeout> </session-config>