Servlet丶ServletContext丶Response丶Request

版权声明:如需转载或引用请声明原文网址 https://blog.csdn.net/u013087359/article/details/81844990

1.Servlet

1.1 web.xml

<!-- 默认首页,从上到下依次查找,如果找到则显示,找不到则继续往下找 -->
<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<servlet>
    <!-- servlet名称 -->
    <servlet-name>MyServlet</servlet-name>
    <!-- Servlet的完整路径 -->
    <servlet-class>com.servlet.MyServlet</servlet-class>
    <!-- 初始化变量,可以在Servlet的inti()被访问 -->
    <init-param>
        <param-name>var</param-name>
        <param-value>我是变量值</param-value>
    </init-param>

    <!-- 在Tomcat启动时就创建本Servelt,值越小优先级越大 -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <!-- 这里的servlet名称对应上面的servlet名称-->
    <servlet-name>MyServlet</servlet-name>
    <!-- 浏览器访问servlet的url -->
    <!-- 多个url-pattern从上到下查找 -->

    <!-- 1.完全匹配方式,必须以/开头 -->
    <url-pattern>/MyServlet</url-pattern>

    <!-- 2.目录模糊匹配,必须以/开头,这里只需输入/ABC就能匹配,后面可以输入任何东西 -->
    <url-pattern>/ABC/*</url-pattern>

    <!-- 3.后缀名模糊匹配,不能使用/开头,以.jsp结尾的url都能匹配 -->
    <url-pattern>*.jsp</url-pattern>

    <!-- 4.任意匹配,所有url都能匹配到 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

1.2 HttpServlet

package com.servlet;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//Servlet由Tomcat创建,默认是首次访问本Servlet创建
public class MyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;


    //init()在Servlet创建时访问,因为Servlet只会创建一次,所以init()也只会被访问一次
    public void init(ServletConfig config) throws ServletException {
        //获取web.xml的servlet-name
        String servletName=config.getServletName();
        //获取web.xml的init-param
        String var=config.getInitParameter("var");
        ServletContext sc= config.getServletContext();

        System.out.println(servletName);
        System.out.println(var);
    }

    //Tomcat关闭时会执行一次
    public void destroy() {

    }

    //每次请求都会访问该方法
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("我是service");
    }

    //service()方法根据get请求访问doGet()方法
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("我是doGet");
    }

    //service()方法根据get请求访问doPost()方法
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("我是doPost");
    }
}

1.3登录例子

  • login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
    <form action="/Web01/LoginServlet" method="post">
        用户名:<input type="text" name="username"><br> 
        密码:<inputtype="password" name="password"><br> 
        <input type="submit" value="登录">
    </form>
</body>
</html>
  • LoginServlet
package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import com.domain.User;
import com.util.C3P0Util;

public class LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求和响应的编码
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        //获取参数值
        String username=request.getParameter("username");
        String password=request.getParameter("password");

        //构建sql语句
        String sql="select * from user where username=? and password=?";

        //执行查询
        QueryRunner qr=new QueryRunner(C3P0Util.getDataSource());
        User user=null;
        try {
            user= qr.query(sql, new BeanHandler<>(User.class),username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        //根据查询结果判断安是否登录成功
        if(user==null) {
            out.print("登录失败!用户名与密码不匹配!!!");
        }else {
            out.println("<h1>登录成功</h1>");
            out.print(user);
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

2.ServletContext

ServletContext是Web应用的上下文对象,封装了有关应用的信息,一个Web应用只有一个ServletContext,随着项目启动而存在,随着项目停止而销毁。

2.1 获取ServletContext对象

//1.使用Servlet自身对象获取ServletContext
ServletContext context= this.getServletContext();
//2.使用request获取ServletContext
ServletContext context=request.getServletContext();

2.2 获取web.xml全局变量

  • web.xml
<web-app>
  <!-- 在web-app节点下定义全局变量 -->
  <context-param>
    <param-name>globalVar</param-name>
    <param-value>我是全局变量</param-value>
  </context-param>
</web-app>
  • ContextServletServlet
public class ContextServletServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //在Servlet中可以直接获取ServletContext对象
        ServletContext context= this.getServletContext();
        //获取web.xml全局变量
        String value=context.getInitParameter("globalVar");
        System.out.println(value);
    }

2.3 获取物理路径

//使用Servlet自身对象获取ServletContext
ServletContext context= this.getServletContext();

//getRealPath()参数是相对与网站的路径,按照发布到Tomcat中的路径为准,与Eclipse文件结构无关
String realPath=context.getRealPath("WEB-INF/classes/c3p0-config.xml");
System.out.println(realPath);

2.4 域对象

    //ServletContext域对象存储的数据可以被所有Web动态资源访问(共享)
    //把数据online_count存放到ServletContext中
    context.setAttribute("online_count", 0);

    //从ServletContext中取出数据online_count
    int count=(int)context.getAttribute("online_count");

3. Response

3.1 重定向

  • 重定向是来回两次请求响应
  • 地址栏会改变
  • 重定向会先执行sendRedirect()后面的代码再跳转
  • 可以重定向站外资源
    //重定向方式1
    //设置302状态码
    response.setStatus(302);
    //设置响应头的Location值
    response.setHeader("Location", "http://www.baidu.com");

    //重定向方式2
    //重定向中以/开头是相对于服务器的,所以需要手动加上网站名称
    response.sendRedirect("/Web02/TestServlet");

    //等待5秒后跳转
    response.setHeader("refresh", "5;url=http://www.baidu.com");

3.2 设置字符编码防止乱码

    //设置字符串编码
    response.setCharacterEncoding("UTF-8");
    //设置文件类型和字符编码,要在输出内容前设置编码才生效
    response.setContentType("text/html;charset=UTF-8");

    PrintWriter out = response.getWriter();
    out.print("你好");

3.3 文件下载

    // 获取客户端传递过来的要下载的文件名
    String filename = request.getParameter("filename");

    // 解决get请求的中文乱码
    filename = new String(filename.getBytes("ISO-8859-1"), "UTF-8");

    // 设置文件的MIME
    response.setContentType(this.getServletContext().getMimeType(filename));

    /* ↓ ↓ ↓兼容下载文件中文名乱码↓ ↓ ↓ */
    String encodeFilename="";
    String userAgent = request.getHeader("User-Agent");
    if (userAgent.indexOf("MSIE")!=-1 || userAgent.indexOf("Trident")!=-1 || userAgent.indexOf("Edge")!=-1 ) {
        // IE浏览器
        encodeFilename = URLEncoder.encode(filename, "utf-8").replace("+", " ");                
    } else if (userAgent.contains("Firefox")) {
        // 火狐浏览器            
        encodeFilename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";
    } else {
        // 其它浏览器(IE10+,Edge,谷歌测试都成功)    ,空格在转码时会变成+,所以需要替换回去    
        encodeFilename = URLEncoder.encode(filename, "utf-8").replace("+", " ");
    }       
    /* ↑ ↑ ↑ 兼容下载文件中文名乱码 ↑ ↑ ↑ */

    // 告知浏览器下载的附件和文件名
    response.setHeader("Content-Disposition", "attachment;filename=" + encodeFilename);

    // 获取文件的物理路径
    String realPath = this.getServletContext().getRealPath("/imgs/" + filename);

    // 把文件写出到客户端
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));
    OutputStream os = response.getOutputStream();
    int len;
    byte[] bs = new byte[1024];
    while ((len = bis.read(bs)) != -1) {
        os.write(bs, 0, len);
    }
    os.close();
    bis.close();

4.Request

4.1 获取请求行信息

    //地址栏网址:http://localhost:6060/Web03/RequestServlet?key=name&value=zhangsan

    //  GET
    String method=request.getMethod();
    //  http://localhost:6060/Web03/RequestServlet
    StringBuffer url=request.getRequestURL();   
    //  /Web03/RequestServlet
    String uri=request.getRequestURI();
    //  /Web03
    String contextPath=request.getContextPath();
    //  /RequestServlet
    String servletPath=request.getServletPath();    
    //  key=name&value=zhangsan
    String queryString=request.getQueryString();

    //获取客户端的IP地址 
    String ip=request.getRemoteAddr();
    //获取客户端的主机名
    String host=request.getRemoteHost();
    //获取客户端的端口号
    int port=request.getRemotePort();

4.2 获取请求头信息

    // 获取浏览器信息
    String userAgent = request.getHeader("User-Agent");
    if (userAgent.indexOf("MSIE") != -1 || userAgent.indexOf("Trident") != -1 || userAgent.indexOf("Edge") != -1) {
        System.out.println("我是IE浏览器");
    } else if (userAgent.contains("Firefox")) {
        System.out.println("我是火狐浏览器");
    } else {
        System.out.println("我是其他浏览器");
    }

    // 获取访问来源网址
    String referer=request.getHeader("referer");

    if(referer!=null&&referer.startsWith("http://localhost:6060/Web03")) {
        out.print("正常访问");
    }else {
        out.print("站外访问,盗链访问");
    }

4.3 获取请求参数值


    //解决post请求参数的中文乱码问题
    request.setCharacterEncoding("UTF-8");

    //获取查询字符串参数的值
    String operate=request.getParameter("operate");
    //解决get请求参数或查询字符串中文乱码问题
    operate=new String(operate.getBytes("ISO-8859-1"),"UTF-8");
    System.out.println(operate);

    //1.获取表单参数的值
    String username=request.getParameter("username");
    System.out.println(username);


    //2.获取拥有多个值的参数
    String[] hobby=request.getParameterValues("hobby");
    for(String s : hobby) {
        System.out.println(s);
    }

    //3.获取所有参数的名称
    Enumeration<String> names=request.getParameterNames();
    while(names.hasMoreElements()) {
        System.out.println(names.nextElement());
    }

    System.out.println("------------------------------");
    //4.获取所有的参数名称和参数值
    Map<String, String[]> parameterMap=request.getParameterMap();
    for (Entry<String,String[]> entry : parameterMap.entrySet()) {
        String key=entry.getKey();
        for (String value : entry.getValue()) {
            System.out.println("key:"+key+",value:"+value);
        }
    }
}

4.4 请求转发

请求转发:客户端发送请求到服务器端某一个处理程序,该程序把处理权转发给另一个程序,最好把处理结果响应给客户端

  • 转发过程浏览器只发送了一次请求
  • 原处理程序和被转发的处理程序的Request对象是共用的
  • 地址栏不会改变
  • 转发等同于一个普通方法,所以执行到forward()方法会马上去执行被转发的处理程序的代码,执行完毕后再执行原处理程序forward()后面的代码
  • 不能转发站外资源
public class Servlet1 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {      
        String username=request.getParameter("username");
        //输出zhangsan
        System.out.println(username);

        //在请求域中存储数据
        request.setAttribute("data", "mydata");

        //在网站内部访问站内资源不需要以网站名称开头
        //转发时把request和response传递给下一个Servlet,所以下一个Servlet也可以从request中获取同样的信息
        request.getRequestDispatcher("/Servlet2").forward(request, response);
    }
public class Servlet2 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //这里的数据跟Servlet1的数据是一样的
        String username=request.getParameter("username");

        //从请求域中获取数据
        String data=(String)request.getAttribute("data");
        //从请求域中移除数据
        request.removeAttribute("data");

        //输出zhangsan
        System.out.println(data);
        //输出mydata
        System.out.println(username);
    }
}

4.5 Request域对象

  • 只在单次请求中数据共享(请求转发也有效)
  • 代码参考4.3例子

5. 总结区别

5.1 重定向与转发区别

  • 重定向两次请求,转发一次请求
  • 重定向地址栏的地址变化,转发地址不变
  • 重新定向可以访问外部网站 转发只能访问内部资源
  • 转发的性能要优于重定向

5.2 客户端访问服务器端资源与服务器端访问站内资源的路径区别

  • 前端页面所有访问服务器端资源都要在路径前面加上网站名称(/网站名称/XXX)
  • 服务器端资源访问站内资源不需要加上网站名称(/XXX),包括各种静态资源,转发资源
  • 重定向需要加上网站名称,因为重定向是先响应到客户端,再次发起的请求

猜你喜欢

转载自blog.csdn.net/u013087359/article/details/81844990
今日推荐