ServletRequest

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。ServletRequest,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

12.ServletRequest
12.1.request对象和response对象的原理
  1. request和response对象是由服务器创建的。我们来使用它们
  2. request对象是来获取请求消息,response对象是来设置响应消息
12.2.request对象继承体系结构

ServletRequest接口
| 继承
HttpServletRequest接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)

12.3.HttpServletRequest类的API
12.3.1.获取请求消息数据
  1. 获取请求行数据
    • GET http//:localhost/app/temp?name=zhangsan&age=18 HTTP/1.1
      • public String getMethod() : 获取请求方法,返回发出此请求的HTTP方法的名称,例如GET、POST或PUT。
      • public String getContextPath() : 返回指示请求上下文的请求URI部分。/app
      • public String getServletPath() : 返回此请求的URL中调用servlet的部分。/temp
      • public String getQueryString() : 返回包含在路径后面的请求URL中的查询字符串。name=zhangsan&age=18
      • public String getRequestURI() : 返回此请求的URL的一部分,从协议名到HTTP请求第一行中的查询字符串。/app/temp
      • public StringBuffer getRequestURL() : 获取请求资源,重建客户端用于发出请求的URL。http://localhost/app/temp
        • URL: 统一资源定位符 :http://localhost/app/temp(范围较小)
        • URI:统一资源标识符 : /app/temp(范围较大)
      • public String getProtocol() : 获取版本协议,以protocol的形式返回请求使用的协议的名称和版本,继承于ServletRequest。HTTP/1.1
  2. 获取请求头数据
    • public String getHeader(String name) : 以字符串形式返回指定请求头的值。
    • public Enumeration getHeaderNames() : 返回此请求包含的所有头名称的枚举。
    • public Enumeration getHeaders(String name) : 返回指定请求头的所有值,作为字符串对象的枚举。
  3. 获取请求体数据:
    • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
    • 步骤:
      • 获取流对象
        • public BufferedReader getReader() : 使用BufferedReader将请求主体作为字符数据。继承于ServletRequest。
        • public ServletInputStream getInputStream() : 使用ServletInputStream作为二进制数据的请求主体。继承于ServletRequest。
      • 从流对象中拿数据
  4. 获取客户机信息
    • public String getRemoteAddr() : 返回发送请求的客户端或最后一个代理的Internet协议(IP)地址。继承于ServletRequest
    • public String getRemoteHost() : 返回发送请求的客户端或最后一个代理的完全限定名。如果引擎无法或选择不解析主机名(以提高性能)。继承于ServletRequest。
    • public int getRemotePort() : 返回发送请求的客户端或最后一个代理的Internet协议(IP)源端口。继承于ServletRequest。
  5. 获取本机信息
    • public String getLocalAddr() : 返回接收请求的接口的Internet协议(IP)地址。继承于ServletRequest。
    • public int getLocalPort() : 返回接收请求的接口的Internet协议(IP)端口号。继承于ServletRequest。
12.3.2.获取请求参数数据
  • 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
    • public String getParameter(String name) : 以字符串形式返回请求参数的值,如果参数不存在,则返回null。继承于ServletRequest。
    • public String[] getParameterValues(String name) :返回包含给定请求参数所具有的所有值的字符串对象数组,如果参数不存在,则返回null。继承于ServletRequest。
    • public Enumeration getParameterNames() : 返回字符串对象的枚举,其中包含此请求中包含的参数的名称。如果请求没有参数,则方法返回空枚举。
    • public Map<String,String[]> getParameterMap() : 返回java.util.Map文件此请求的参数。请求参数是随请求发送的额外信息。对于httpservlet,参数包含在查询字符串或发布的表单数据中。

    中文乱码问题:

    • get方式:tomcat 8 已经将get方式乱码问题解决了
    • post方式:会乱码
      • 在获取参数前,设置request的编码request.setCharacterEncoding(“utf-8”);
      • public void setCharacterEncoding(String env):重写此请求正文中使用的字符编码的名称。必须在读取请求参数或使用getReader()读取输入之前调用此方法。否则,就没有效果。
12.3.3.获取form表单的提交数据
  • 对于获取数据,form表单必须要有name属性,提交上的值才能是key-value形式,这样才能被成功获取到
public class User {

    private String username;
    private String password;
    private String gender;
    private String[] hobby;
    private String province;

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public String[] getHobby() {
        return hobby;
    }
    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }
    public String getProvince() {
        return province;
    }
    public void setProvince(String province) {
        this.province = province;
    }
    public User(String username, String password, String gender, String[] hobby, String province) {
        this.username = username;
        this.password = password;
        this.gender = gender;
        this.hobby = hobby;
        this.province = province;
    }
    public User() {
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", hobby=" + Arrays.toString(hobby) +
                ", province='" + province + '\'' +
                '}';
    }
}

@WebServlet("/submit")
public class SubmitServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //如何获取form表单提交的各种类型的请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String gender = request.getParameter("gender");
        //如果提交的参数是checkbox,使用该方法可能获取的结果不全
        //String hobby = request.getParameter("hobby");
        String province = request.getParameter("province");
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println(username);
        System.out.println(password);
        System.out.println(gender);
        //System.out.println(hobby);
        System.out.println(province);
        System.out.println(Arrays.toString(hobbies));
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
  • 在web目录下创建一个form.html文件,浏览器输入localhost/app/form.html,就可以提交到上面的Servlet中去
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    usename=xxx&password=xxx&gender=xxx&....
    <!-- 路径一定要写对,和Servlet相对应 -->
    <!-- 全路径写法:<form action="http://localhost:80/app/submit" method="get">
	<!-- 相对路径写法:<form action="submit" method="get">
	<!-- 相对应用路径写法,/应用名/资源名,把全路径中访问协议、主机、端口号部分给去掉,提交的路径始终不需要发生变更。推荐 -->
    <form action="/app/submit" method="get">
        <input type="text" name="username"><br>
        <input type="password" name="password"><br>
        <input type="radio" name="gender" value="male"><input type="radio" name="gender" value="female"><br>
        <input type="checkbox" name="hobby" value="java">java
        <input type="checkbox" name="hobby" value="python">python
        <input type="checkbox" name="hobby" value="c++">c++<br>
        <select name="province">
            <option value="wuhan">武汉</option>
            <option value="beijing">北京</option>
            <option value="shanghai">上海</option>
        </select>
        <input type="submit">
    </form>
</body>
</html>
12.3.4.BeanUtils
  • 介绍
    • 用于封装JavaBean的工具类
    • 要求:
      1. 类必须被public修饰
      2. 必须提供空参的构造器
      3. 成员变量必须使用private修饰
      4. 提供公共setter和getter方法
    • 功能:封装数据
  • 下载配置方式
    • https://mvnrepository.com/ 进去验证以后搜索beanutils,找到对应版本,下载jar包的同时,下载下方Compile Dependencies的两个依赖环境,共三个
    • 在module根目录下创建一个lib文件夹,将三个包复制进去,同时,在上面右键,选择Add as Library,相当于在IDEA中注册该资源
    • tomcat提供的类加载器加载应用下面的class以及jar包的时候,只会到WEB-INF/classes以及WEB-INF/lib目录下加载其他地方不会去加载
      • 方式一:将这三个包放在WEB-INF目录下
      • 方式二:打开Project Structure设置,找到Artifacts设置选项,点击Output Layout选项卡,会看到报错信息,缺失了beanutils资源包,在WEB-INF目录处右键,选择Create Directory,新建一个lib目录,在lib目录上右键,选择Add Copy of,点击Library Files,在新窗口选择beanutils,确定即可。
  • 封装原理:BeanUtils.poulate(Object, parameterMap)方法,会获取到parameterMap中的键值对,parameterMap中存储的是form表单提交上来的参数,对于map中的每个key值,会去Object中寻找setXxx方法,对其设置为对应的value值。
    • 同样对于上面例子的User和form表单,编写以下测试类
    @WebServlet("/beanutils")
    public class BeanUtilsTest extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            User user = new User();
            request.setCharacterEncoding("utf-8");
            Map<String, String[]> parameterMap = request.getParameterMap();
            try {
                BeanUtils.populate(user, parameterMap);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            System.out.println(user);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //doPost(request, response);
            String username = request.getParameter("username");
            System.out.println(username);
        }
    }
    
12.4.请求转发
  • 特点:
    • 一种在服务器内部的资源跳转方式
    • 一个请求到来之后,交给一个servlet来处理,servlet处理完毕之后,需要将请求交给另外一个servlet,或者将请求交给另外一个页面来最后做出响应,那么这个时候就可以使用转发。在真实应用中很少用到,页面跳转一般由前端负责
    • 一个组件(源组件)执行完毕之后,它将响应的主动权交给另外一个组件(目标组件),后续响应主要由另外一个组件(目标组件)来负责。这里面涉及到了一个主动权变更的过程。
    • 针对源组件来说,转发前后,源组件可以再最终的响应报文中留下响应头,但是无法留下响应体。
    • 包含主要用在页面包含另外一个页面中,最大的特征,主动权还在自己手中,源组件包含过后仍然可以设置响应体
    • 转发前后请求方法不变,而refresh、重定向,浏览器默认使用get方式
  • 原理:
    • 转发:servlet————–> html(响应体由该组件来提供)
    • 包含:html (响应体由该组件来提供)<—————— html
  • 步骤:
    1. 通过request对象获取请求转发器对象:public RequestDispatcher getRequestDispatcher(String path)
    2. 使用RequestDispatcher对象来进行转发:public void forward(ServletRequest request,ServletResponse response):将来自servlet的请求转发到服务器上的另一个资源(servlet、JSP文件或HTML文件)。此方法允许一个servlet对请求进行初步处理,并允许另一个资源生成响应
    • 或者,使用RequestDispatcher对象来进行包含:public void include(ServletRequest request,ServletResponse response):响应中资源的内容(servlet、JSP页、HTML文件)。本质上,此方法支持编程的服务器端包含。
  • 特点:
    1. 浏览器地址栏路径不发生变化
    2. 只能转发到当前服务器内部资源中。
    3. 转发是一次请求
  • 共享数据:
    • 域对象:一个有作用范围的对象,可以在范围内共享数据
    • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
    • 方法:
      1. public void setAttribute(String name,Object obj):存储数据
      2. public Object getAttitude(String name):通过键获取值
      3. public void removeAttribute(String name):通过键移除键值对
  • 获取ServletContext
    • public ServletContext getServletContext()
  • Example:
    • 登录案例:登录成功跳转到成功的页面,失败后跳转到失败的页面
    @WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //登录需要做什么事情?
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            //直接固定
            if("admin".equals(username) && "admin".equals(password)){
                //表示登录成功
                //转发里面/开头的路径必须要求把应用名给去掉才可以正常访问。因为Tomcat配置了应用名,但是服务器不知道应用名
                request.getRequestDispatcher("/success.html").forward(request,response);
            }else {
                request.getRequestDispatcher("/fail.html").forward(request, response);
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        }
    }
    
    • 如果该路径的执行解析主体是服务器,那么就不需要加应用,直接/资源路径即可,如:转发
    • 如果该路径的执行解析主体是浏览器,那么就需要加应用名,/应用名/资源路径,如:form action img src a href
    • 下面是登陆成功的页面和失败的页面,均将其放置在web文件夹下面
    <!-- 登录页面 -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/app/login" method="post">
            <input type="text" name="username"><br>
            <input type="password" name="password"><br>
            <input type="submit">
        </form>
    </body>
    </html>
    
    
    <!-- 登录成功页面 -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    login fail
    </body>
    </html>
    
    
    <!-- 登录失败页面 -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    login success
    </body>
    </html>
    
12.5.Request域
  • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据,每个请求都会生成一个request域
  • Request对象中也有一个map,只要两个Servlet能够拿到同一个Request对象,那么他们就可以共享该对象里面的map
  • 只有转发或包含的两个组件之间可以共享Request域,其他的都不能共享
  • 生命周期:
    • 创建:访问时创建
    • 销毁:响应结束request销毁
    • 作用域:一次请求中
  • API
    • public void setAttribute(String name,Object obj):存储数据
    • public Object getAttitude(String name):通过键获取值
    • public void removeAttribute(String name):通过键移除键值对
    @WebServlet("/domain1")
    public class DomainServlet1 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setAttitude("username","request");
            request.getRequestDispatcher("/domain2").forward(request,response);
        }
    }
    
    
    
    @WebServlet("/domain2")
    public class DomainServlet2 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String username = (String) request.getAttitude("username");
            System.out.println(username);
        }
    }
    
    //直接访问domain1,domain1会将其发送给domain2,可以看到控制台中输出了request
    
12.6.完整的登录案例
  • 用户登录案例需求:
    1. 编写login.html登录页面,username & password 两个输入框
    2. 使用Druid数据库连接池技术,操作mysql,day14数据库中user表
    3. 使用JdbcTemplate技术封装JDBC
    4. 登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您
    5. 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误
* 开发步骤
    1. 创建项目,导入html页面,配置文件,jar包
    2. 创建数据库环境
        CREATE DATABASE day14;
        USE day14;
        CREATE TABLE USER(
        
            id INT PRIMARY KEY AUTO_INCREMENT,
            username VARCHAR(32) UNIQUE NOT NULL,
            PASSWORD VARCHAR(32) NOT NULL
        );

    3. 创建包cn.itcast.domain,创建类User
        package cn.itcast.domain;
        /**
         * 用户的实体类
         */
        public class User {
        
            private int id;
            private String username;
            private String password;
            
            public int getId() {
                return id;
            }

            public void setId(int id) {
                this.id = id;
            }
        
            public String getUsername() {
                return username;
            }
        
            public void setUsername(String username) {
                this.username = username;
            }
        
            public String getPassword() {
                return password;
            }
        
            public void setPassword(String password) {
                this.password = password;
            }
        
            @Override
            public String toString() {
                return "User{" +
                        "id=" + id +
                        ", username='" + username + '\'' +
                        ", password='" + password + '\'' +
                        '}';
            }
        }
    4. 创建包cn.itcast.util,编写工具类JDBCUtils
        package cn.itcast.util;

        import com.alibaba.druid.pool.DruidDataSourceFactory;
        
        import javax.sql.DataSource;
        import javax.xml.crypto.Data;
        import java.io.IOException;
        import java.io.InputStream;
        import java.sql.Connection;
        import java.sql.SQLException;
        import java.util.Properties;
        
        /**
         * JDBC工具类 使用Durid连接池
         */
        public class JDBCUtils {
        
            private static DataSource ds ;
        
            static {
        
                try {
                    //1.加载配置文件
                    Properties pro = new Properties();
                    //使用ClassLoader加载配置文件,获取字节输入流
                    InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
                    pro.load(is);
        
                    //2.初始化连接池对象
                    ds = DruidDataSourceFactory.createDataSource(pro);
        
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        
            /**
             * 获取连接池对象
             */
            public static DataSource getDataSource(){
                return ds;
            }
            
           /**
             * 获取连接Connection对象
             */
            public static Connection getConnection() throws SQLException {
                return  ds.getConnection();
            }
        }
    5. 创建包cn.itcast.dao,创建类UserDao,提供login方法
        package cn.itcast.dao;

        import cn.itcast.domain.User;
        import cn.itcast.util.JDBCUtils;
        import org.springframework.dao.DataAccessException;
        import org.springframework.jdbc.core.BeanPropertyRowMapper;
        import org.springframework.jdbc.core.JdbcTemplate;
        
        /**
         * 操作数据库中User表的类
         */
        public class UserDao {
        
            //声明JDBCTemplate对象共用
            private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        
            /**
             * 登录方法
             * @param loginUser 只有用户名和密码
             * @return user包含用户全部数据,没有查询到,返回null
             */
            public User login(User loginUser){
                try {
                    //1.编写sql
                    String sql = "select * from user where username = ? and password = ?";
                    //2.调用query方法
                    User user = template.queryForObject(sql,
                    new BeanPropertyRowMapper<User>(User.class),
                    loginUser.getUsername(), loginUser.getPassword());
                    return user;
                } catch (DataAccessException e) {
                    e.printStackTrace();//记录日志
                    return null;
                }
            }
        }

    6. 编写cn.itcast.web.servlet.LoginServlet类
            package cn.itcast.web.servlet;

            import cn.itcast.dao.UserDao;
            import cn.itcast.domain.User;

            import javax.servlet.ServletException;
            import javax.servlet.annotation.WebServlet;
            import javax.servlet.http.HttpServlet;
            import javax.servlet.http.HttpServletRequest;
            import javax.servlet.http.HttpServletResponse;
            import java.io.IOException;

            @WebServlet("/loginServlet")
            public class LoginServlet extends HttpServlet {            
                @Override
                protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                    //1.设置编码
                    req.setCharacterEncoding("utf-8");
                    //2.获取请求参数
                    String username = req.getParameter("username");
                    String password = req.getParameter("password");
                    //3.封装user对象
                    User loginUser = new User();
                    loginUser.setUsername(username);
                    loginUser.setPassword(password);
            
                    //4.调用UserDao的login方法
                    UserDao dao = new UserDao();
                    User user = dao.login(loginUser);
                    //5.判断user
                if(user == null){
                    //登录失败
                    req.getRequestDispatcher("/failServlet").forward(req,resp);
                }else{
                    //登录成功
                    //存储数据
                    req.setAttribute("user",user);
                    //转发
                    req.getRequestDispatcher("/successServlet").forward(req,resp);
                }
            }
                
            @Override
            protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                this.doGet(req,resp);
            }
        }

    7. 编写FailServlet和SuccessServlet类
        @WebServlet("/successServlet")
        public class SuccessServlet extends HttpServlet {
            protected void doPost(HttpServletRequest request, HttpServletResponse response) 
                throws ServletException, IOException{
                //获取request域中共享的user对象
                User user = (User) request.getAttribute("user");

                if(user != null){
                    //给页面写一句话
                    
                    
                    //设置编码
                    response.setContentType("text/html;charset=utf-8");
                    //输出
                    response.getWriter().write("登录成功!"+user.getUsername()+",欢迎您");
                }
            }
            
        @WebServlet("/failServlet")
        public class FailServlet extends HttpServlet {
            protected void doPost(HttpServletRequest request, HttpServletResponse response) 
                throws ServletException, IOException {
                //给页面写一句话
            }
        }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181055.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!