JavaWeb之Servlet 图文详解

Servlet

1,Servlet简介

1.1,Servlet

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,主要功能在于交互式地浏览和生成数据,生成动态Web内容。 Servlet是指任何实现了这个Servlet接口的类

核心:Servlet是指实现了Servlet接口的类

1.2,编写Servlet的方法

继承HttpServlet类(本质是一个Serlvet接口的实现类)

public class Servlet extends HttpServlet {
   
}

实现Servlet接口

public class MyServlet 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 {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

2,Servlet源码分析

在这里插入图片描述

3,编写第一个Servlet

在这里插入图片描述

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyServlet extends HttpServlet {
    //doPost和doGet对应前端的两种上传方式,这里直接相互调用即可,因为后台的处理逻辑是相同的

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //这里讲一下
        //1.resp.getWriter():获取一个响应输出流
        //2.println  打印内容
        //3. resp.getWriter().println("Hello,World");和resp.getWriter().write("Hello,World");
        //的区别,通过源码可以发现   public void print(Object obj) {
        //        write(String.valueOf(obj));
        //    }   //用Print可以直接将对象,转化为字符串,从而调用Write方法输出
        resp.getWriter().println("Hello,World");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>MyServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

在这里插入图片描述

4,Servlet原理

在这里插入图片描述

5,Mapping

在这里插入图片描述

Mapping:建立URl与Class之间的

<!--单映射,/代表当前web项目,hello为对应的相应-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
<!--当然我们也可以给一个Servlet设置多个响应-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
<!--无论是访问/hello还是/hello2都会返回MyServlet-->
<!--当我们以/*设置时,无论时输入什么响应,都会返回MyServlet-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
<!--如果你的url-pattern定义的是资源格式例如*.do等,
那么对于所有符道合这种格式的资源的请求都由指定的servlet处理。 -->
<!--这里注意不能带/-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
<!--补充说明优先级问题,指定的映射,大于通配的映射-->

6,ServletContext

全局应用程序共享对象
在这里插入图片描述

6.1,servletContext是一个域对象

域对象是服务器在内存上创建的存储空间,用于在不同动态资源(servlet)之间传递与共享数据


public class Servlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          resp.setCharacterEncoding("UTF-8");
          resp.setContentType("text/html");
          getServletContext().setAttribute("name","haha");
          resp.getWriter().println("储存了name");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class Servlet02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = (String) getServletContext().getAttribute("name");
        resp.getWriter().println("1:"+name);//1:haha
        //移除
        getServletContext().removeAttribute("name");
        String name2 = (String) getServletContext().getAttribute("name");
        resp.getWriter().println("2:"+name2);//2:null
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

6.2,可以读取全局配置参数

getServletContext().getInitParameter(name);//根据指定的参数名获取参数值

getServletContext().getInitParameterNames();//获取所有参数名称列表

在web.xml中配置全局配置参数

<context-param>
    <param-name>name1</param-name>
    <param-value>1</param-value>
</context-param>
<context-param>
    <param-name>name2</param-name>
    <param-value>2</param-value>
</context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String para = getServletContext().getInitParameter("name1");
    resp.getWriter().println(para);//1
}

设置context-param和init-param的区别

<context-param>
  <param-name>context</param-name>
  <param-value>contextValue</param-value>
</context-param>
<servlet>
  <servlet-name>s1</servlet-name>
  <servlet-class>Servlet01</servlet-class>
  <init-param>
    <param-name>name1</param-name>
    <param-value>value1:1</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>s1</servlet-name>
  <url-pattern>/s1</url-pattern>
</servlet-mapping>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name1 = this.getInitParameter("name1");
    resp.getWriter().println(name1);//value:1    用this.getInitParameter只能获取指定Servlet的初始化数据
    String context =this.getInitParameter("context");
    resp.getWriter().println(context);//null
    String name2 = getServletContext().getInitParameter("name1");
    resp.getWriter().println(name2);// null     用getServletContext().getInitParameter只能获得指定上下文范围内初始化数据
    String context2 =getServletContext().getInitParameter("context");
    resp.getWriter().println(context2);//context
}

6.3,可以搜索当前工程目录下面的资源文件

getServletContext().getRealPath(path),根据相对路径获取服务器上资源的绝对路径

getServletContext().getResourceAsStream(path),根据相对路径获取服务器上资源的输入字节流

在Maven项目中,我们把资源文件放在resources下,在打包的时候,会直接放入classes下

在这里插入图片描述

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //获取输入流
    InputStream resourceAsStream = getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//    /代表当前项目
    Properties prop = new Properties();
    prop.load(resourceAsStream);
    //输出
    resp.getWriter().println(prop.getProperty("username"));//admin
    resp.getWriter().println(prop.getProperty("password"));//123456

}

6.4,可以获取当前工程名字

getServletContext().getContextPath();

//获取当前项目名
resp.getWriter().println(getServletContext().getContextPath());// /ServletConfig_war

6.5,请求转发

getServletContext().getRequestDispatcher(“请求的路径”).forward(req,resp);

//请求转发
getServletContext().getRequestDispatcher("/s1").forward(req,resp);

7, HttpServletRequest

Request即为从客户端产生的请求,主要用于获取从客户端产生的数据
在这里插入图片描述

主要以getXX的方法,获取从客户端带来的数据

7.1,获取从前端传输过来的数据,并进行转发

<html>
<body>
<h2>Login</h2>
<p>${pageContext.request.contextPath}</p>
<%--/HttpRequest_war--%>
<form action="${pageContext.request.contextPath}/r1" method="get">
    <input type="text" name="username"><br>
    <input type="password" name="password"><br>
    <input type="submit">
</form>
</body>
</html>

在这里插入图片描述

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    System.out.println("+++++++++++++++++++++++++++++++");
    System.out.println(username);
    System.out.println(password);
    System.out.println("++++++++++++++++++++++++++++++++");
    //下面进行请求转发,将请求转发到我们的成功页面中
    req.getRequestDispatcher("/s1").forward(req,resp);
}

8,HttpServletResponse

Response即为从服务端产生的响应,主要用于产生对客户端的响应

在这里插入图片描述在这里插入图片描述

8.1,向浏览器提供文件下载服务

在这里插入图片描述

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    //获取文件路径
    String realPath = "D:\\Environment\\WorkSpaceIdea\\JavaWebStudy\\HttpRequest\\target\\classes\\poster.png";
    //获取文件名
    String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
    //设置下载服务
    resp.setHeader("Content-Disposition","attachment;filename="+fileName);
    //获取文件输入流
    FileInputStream in =new FileInputStream(realPath);
    //创建缓冲区
    int len=0;
    byte[] buffer =new byte[1024];
    //获取OutputStream对象
    ServletOutputStream out = resp.getOutputStream();
    //进行输出到客户端
    while((len=in.read(buffer))>0){
        out.write(buffer,0,len);
    }
    in.close();
    out.close();

}

8.2,向浏览器提供验证码图片服务(应用举例)

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //设置响应头,让浏览器每5秒刷新一次
    resp.setHeader("refresh","5");
    //在内存中创建一张图片
    BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
    //得到图片
    Graphics2D g = (Graphics2D) image.getGraphics();
    //绘制图片
    g.setColor(Color.BLACK);
    g.fillRect(0,0,80,10);
    g.setColor(Color.WHITE);
    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(image,"jpg", resp.getOutputStream());
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
}
//生成随机数
private String makeNum(){
    Random random =new Random();
    String num =String.valueOf(random.nextInt(99999999));

    StringBuffer sb =new StringBuffer();
    for(int i=0;i<8-num.length();i++){
        sb.append("0");
    }
    return sb.toString()+num;
}

在这里插入图片描述

8.3 Response进行重定向

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.sendRedirect("/down");//将请求重定向到/down请求下
}
8.3.1,请求和重定向的区别

在这里插入图片描述

9,会话

9.1,什么是有状态会话

在这里插入图片描述

10,Cookie

Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息

客户端保存技术

10.1,Cookie源码

在这里插入图片描述

在这里插入图片描述

10.2,应用举例

=在这里插入图片描述

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        //从请求中获取Cookie
        Cookie[] cookies = req.getCookies();
        //处理cookies
        if(cookies!=null){
            for (Cookie cookie : cookies) {
                if(cookie.getName().equals("LastLoginTime")){
                    String value = cookie.getValue();
                    long l = Long.parseLong(value);
                    Date date = new Date(l);
                    resp.getWriter().write("你上一次登录本站的时间为:"+date.toString());
                }
            }
        }
        Cookie lastLoginTime = new Cookie("LastLoginTime", System.currentTimeMillis() + "");
        //通过resp响应一个cookie给客户端
        lastLoginTime.setMaxAge(24*60*60);//设置cookie有效期为1天,以秒为单位
        resp.addCookie(lastLoginTime);
    }

在这里插入图片描述
在这里插入图片描述

11,Session

在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。

在这里插入图片描述

sessionID可以用作用户的标识

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
    req.getSession().setAttribute("name","haha");

    //获得SessionID
    String sessionId=req.getSession().getId();

    //测试Session的创建情况
    if(req.getSession().isNew()){
        resp.getWriter().write("New session,ID"+sessionId);
    }else{
        resp.getWriter().write("Old session ID"+sessionId);
        resp.getWriter().write((String) req.getSession().getAttribute("name"));
        //Old session ID06F5EBBF8AD139F723F9E0C941AA9C65haha
    }

}

我们可以在Xml中设置session的失效时间

 <session-config>
<!--        设置session15分钟后失效-->
        <session-timeout>15</session-timeout>
    </session-config>

应用:

我们通常会选择将一些在一个网站各个页面通用的数据放在Session中,进行会话级别的数据保存

12,filter

Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。

可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。调用 Servlet 前调用所有附加的 Servlet 过滤器。

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

应用:中文乱码过滤器

public class Myfilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //利用Filter进行乱码过滤
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        chain.doFilter(request,response);//把请求和响应发出,不发出页面就会卡住
    }

    @Override
    public void destroy() {

    }
}
 <filter>
        <filter-name>code</filter-name>
         <filter-class>Myfilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>code</filter-name>
<!--        这里设置为过滤全部的请求-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

13,listener

在这里插入图片描述

事件(Event)是发生的事情,在Web应用程序世界中,事件可以是应用程序的初始化销毁应用程序从客户端请求创建/销毁会话会话中的属性修改等。

Servlet API提供了不同类型的侦听器接口,我们可以在web.xml中实现和配置,以便在特定事件发生时处理某些事件

使用方法:

在这里插入图片描述

public class MyListener implements HttpSessionListener {
    //创建session监听,监听session的创建
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext servletContext = se.getSession().getServletContext();
        Integer sessionCut = (Integer) servletContext.getAttribute("SessionCut");
        if(sessionCut == null){
             sessionCut=new Integer(1);
        }else{
             int value =sessionCut.intValue();//拆箱
             sessionCut=new Integer(value+1);//装箱
        }
        servletContext.setAttribute("SessionCut",sessionCut);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {

    }
}
<!--    注册监听-->
    <listener>
        <listener-class>MyListener</listener-class>
    </listener>
<html>
<body>
<h2>Login</h2>
<p><%=this.getServletConfig().getServletContext().getAttribute("SessionCut")%></p>
</body>
</html>

在前端页面中获取(这里开了两个浏览器模拟两个session)

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值