5Servlet

Servlet

1简介

  • Servlet就是sun公司开发动态web的一门技术
  • Sun在这些API中提供一个接口叫做:Servlet
  • 如果你想开发一个Servlet程序,只需要完成两个小步骤:1编写一个类,实现Servlet接口 2把开发好的Java类部署到web服务器中
  • 我们把实现了Servlet接口的Java程序叫做Servlet

2编写一个servlet程序

  • 导入依赖
  • 实现Servlet 接口 直接继承 HttpServlet
  • 编写Serviet 的映射(为什么写映射: 我们写的是JAVA程序,但是要通过浏览器访问,浏览器需要连接web浏览器, 所以我们需要在web服务中注册我们写的Servlet 还需要给他一个浏览器能够访问的路径)
<!--  1pom.xml中导入依赖  -->
<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
 </dependency>
//2java.com.fao.servlet包下编写servlet类继承HttpServlet
public class helloservlet extends HttpServlet {
    //由于gat或者post只是请求实现的不同方法,可以互相调用,业务逻辑一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//ervletOutputStream outputStream = resp.getOutputStream();
        System.out.println("进入do get方法");
        PrintWriter writer = resp.getWriter();//响应流
        writer.print("hello servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--  3.1配置映射方式一:xml方式,在web.xml下注册servlet  -->
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

<!--  注册servlet-->
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.fao.servlet.helloservlet</servlet-class>
  </servlet>

<!--  servlet请求路径-->
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
  
</web-app>
//3.2配置映射方式二:注解方式,在servler类上面加@WebServlet
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入doGet方法");
        PrintWriter writer = resp.getWriter();
        writer.write("hello servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
//乱码问题
public class ErrorServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码
        resp.setHeader("Content-type", "text/html;charset=UTF-8");
        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print("<h1>404</h1>");
    }

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

3Servlet原理

4Mapping问题

  • 一个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>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello4</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello5</url-pattern>
</servlet-mapping>
  • 一个Servlet可以指定通用映射路径
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  • 默认请求路径
<!--默认请求路径-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
  • 指定一些后缀或者前缀等等...
 <!--可以自定义后缀实现请求映射    
    注意点,*前面不能加项目映射的路径    
    hello/sajdlkajda.fao  
    只要以 .fao  就能访问
-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.fao</url-pattern>
</servlet-mapping
  • 优先级问题
  • 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求(404)

5ServletContext

  • web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用

​ 5.1共享数据

public class ServletContext1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //this.getServletConfig()  //servlet 配置
        //this.getInitParameter()   //初始化参数
        //this.getServletContext();   //servlet上下文
        ServletContext context = this.getServletContext();
        String username="Fao";//数据
        context.setAttribute("username",username);//将一个数据保存在了ServletContext中,  名字为: username 值: username
        System.out.println("欢迎");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class ServeletContext1a extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //数据
        ServletContext context = this.getServletContext();
        String username = (String)context.getAttribute("username");

        ////响应
        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().println("姓名: "+username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
   <servlet>
        <servlet-name>servlet1</servlet-name>
        <servlet-class>com.fao.servlet.ServletContext1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet1</servlet-name>
        <url-pattern>/s1</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>servlet1a</servlet-name>
        <servlet-class>com.fao.servlet.ServeletContext1a</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet1a</servlet-name>
        <url-pattern>/s1a</url-pattern>
    </servlet-mapping>

​ 5.2请求转发

public class ServletContext2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext  context = this.getServletContext();
        System.out.println("进入到servletcontext2");
        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/hello");//转发的请求路径
        requestDispatcher.forward(req,resp);//调用forward实现请求转发
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
   <servlet>
        <servlet-name>servlet2</servlet-name>
        <servlet-class>com.fao.servlet.ServletContext2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet2</servlet-name>
        <url-pattern>/s2</url-pattern>
    </servlet-mapping>

​ 5.3读取资源文件

  • 在java目录下新建properties,在resources目录下新建properties
  • 发现: 都被打包到了同一路径下: classes,俗称为类路径
  • 如果测试报未找到文件,很有可能是maven没加过滤
//ServletContext3.properties
username=fao
id=1
password=123
public class ServletContext3 extends HelloServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        InputStream is = context.getResourceAsStream("/WEB-INF/classes/com/fao/servlet/ServletContext3.properties");
        Properties prop = new Properties();
        prop.load(is);
        String username = prop.getProperty("username");
        String id = prop.getProperty("id");
        String passworld = prop.getProperty("password");
        resp.getWriter().println(username+", "+passworld+", "+id);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
    <servlet>
        <servlet-name>servlet3</servlet-name>
        <servlet-class>com.fao.servlet.ServletContext3</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet3</servlet-name>
        <url-pattern>/s3</url-pattern>
    </servlet-mapping>

6HttpServletResponse&

  • web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse
  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:找HttpServletResponse

​ 6.1简单分类

//负责向浏览器发送数据的方法
ServletOutputStream getOutputStream()throwsIOException;
PrintWriter getWriter()throwsIOException;//一般中文用
//负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1,long var2);
void addDateHeader(String var1,long var2);
void setHeader(String var1,String var2);
void addHeader(String var1,String var2);
void setIntHeader(String var1,int var2);
void addIntHeader(String var1,int var2);

​ 6.2常见应用之下载文件

  1. 要获取下载文件的路径
  2. 下载的文件名是啥?
  3. 设置想办法让浏览器能够支持下载我们需要的东西
  4. 获取下载文件的输入流
  5. 创建缓冲区
  6. 获取OutputStream对象
  7. 将FileOutputStream流写入到buffer缓冲区
  8. 使用OutputStream将缓冲区中的数据输出到客户端!
//先在resources下放一张图片
public class ServletResponse4 extends HelloServlet {
    @Override
    protected void doGet(HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws ServletException, IOException {
        //1要获取下载文件的路径
        String realPath = "D:\\java\\faoservletfuxi\\servletfuxi1\\src\\main\\resources\\4.jpg";
        System.out.println(realPath);

        //2下载的文件名是啥
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);//等于4.jpg

        //3设置想办法让浏览器能够支持下载我们需要的东西
        //如果是中文文件名需要设置编码 否则有可能乱码
        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将outputstram流写入到buffer缓冲区
        while ((len=in.read(buffer))!=-1){
            out.write(buffer,0,len);
        }

        //8流关闭
        in.close();
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
 <servlet>
        <servlet-name>servlet4</servlet-name>
        <servlet-class>com.fao.servlet.ServletResponse4</servlet-class>
  </servlet>
  <servlet-mapping>
        <servlet-name>servlet4</servlet-name>
        <url-pattern>/s4</url-pattern>
  </servlet-mapping>

​ 6.3常见应用之实现重定向

  • B一个web资源收到客户端A请求后,B会通知A去访问另外一个web资源C,这个过程叫重定向
  • 重定向和转发的区别?
  • 相同点:页面都会跳转
  • 不同点:1请求转发 url不会产生变化, 重定向会发生变化 2请求转发 可以携带参数, 重定向不能携带参数 3请求转发 只能发送一个请求, 重定向至少发送两次请求
<%--  成功页面  --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <h1>
        success
    </h1>

</body>
</html>
public class ServletResponse5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入请求");
        //处理请求
        //从那个请求中获取参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+" : "+password);
        //重定向时一定要注意路径问题  否则44
        resp.sendRedirect("/fx1/success.jsp");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
 <servlet>
        <servlet-name>servlet5</servlet-name>
        <servlet-class>com.fao.servlet.ServletResponse5</servlet-class>
    </servlet>
  <servlet-mapping>
        <servlet-name>servlet5</servlet-name>
        <url-pattern>/s5</url-pattern>
  </servlet-mapping>

6.4HttpServletRequest之获取前端传递的参数 并 请求转发

  • HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息
<%--  login.jsp  --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<div style="text-align: center">
    <%--  {pageContext.request.contextPath}表示当前页面  --%>
    <form action="${pageContext.request.contextPath}/s6" 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>
</body>
</html>
public class ServletRequest6 extends HttpServlet {
    @Override
    protected void doGet(javax.servlet.http.HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbys = req.getParameterValues("hobbys");

        System.out.println("*************************");
        //后台接收中文乱码问题       req.setCharacterEncoding("utf-8");
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbys));
        System.out.println("*************************");

        resp.sendRedirect("/fx1/success.jsp");
    }

    @Override
    protected void doPost(javax.servlet.http.HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
posted @ 2022-05-21 11:54  fao99  阅读(24)  评论(0)    收藏  举报