首页 > 编程语言 >javaweb2

javaweb2

时间:2022-11-24 23:35:11浏览次数:43  
标签:servlet request println import javaweb2 response out

Servlet核心

1.核心类与接口

  1. init:完成初始化操作

    • 只会执行一次

      • 没有配置1时才只会执行一次

      • 在实例类对象中配置(注解方式)

        @WebServlet(vlue="路径",loadonstartup=1)
        
      • 如果有多个service配置了loadonstartup,里面的数字就是在服务器中创建示例的顺序

    • init方法在执行的时候,对象已经被创建出来了

  2. service:处理用户请求的核心方法

    • 用户每发送一次请求,server方法就会执行进行
  3. doGet,doPost:根据客户端的请求方式,如果是get则调用doGet,如果是post则调用doPost.....

  4. destroy:Tomcat服务器在销毁对象之前,会调用一次destroy方法

    • 只会执行一次
    • destroy方法执行的时候,对象的内存还没有被销毁,即将被销毁
    • destroy方法中可以编写销毁前的准备
  5. 编写一个抽象类,有一个抽象方法service

    • 实现servlet接口

    • 以后编写的所有servlet类都继承这个抽象类,重写service方法即可

  6. 执行流程

    • 按照1234下来

2.线程安全问题

  • 因为servlet实例是单例模式,当多个客户端并发访问同一个servlet类时,Tomcat会创建多个线程,多个线程会使用同一个seven实例,有可能会导致线程安全问题,那如何保证线程安全呢?

2.1实现singlethreadmodel接口

  • 这种方式虽然避免了多线程使用通过servlet实例的请求,但是使用这种方式会导致客户端的请求响应效率变低,增加了服务器因频繁创建和销毁servlet实例的开销,因此这种方式不建议使用(已经淘汰)

2.2使用synchronize同步锁

  • 在实例类的do方法中锁住this即可

    do方法{
     	synchronize(this){
        //其他代码
        }
    }
    

2.3建议

  • servlet类中尽量不使用全局变量
    • 因为定义全局变量的话,这个变量是多个线程中共享的,就有可能因为同时修改这个变量导致并发问题
    • 因此我们可以将变量定义在处理业务的do方法中,定义为局部变量之后,每个线程都有属于自己的局部变量

3.servlet开发技术

3.1request对象

  1. 接收请求行数据

    1. 获取请求方式
      • request.getMethod();
    2. 获取请求url
      • request.getRequestURL();
    3. 获取请求url上的参数
      • request.getParameter("值");
    4. 获取请求协议
      • request.getProtocol();
  2. 接收请求头数据

    1. 获取请求头中所有的key
      • request,getHeaderNames();
      • 返回的值是枚举
    2. 获取请求头中对应的key
      • request,getHeader("值");
  3. 接收请求正文数据

    • 获取请求正文

      • request.getInputStream();

      • //使用
        //获取正文
        ServletInputStream inputStream = req.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        //从输入流中读取数据
        String s = reader.readLine();
        System.out.println(s);
        

3.2乱码问题

  • 产生

    • 客户端提交的数据通过网络发送到服务器,传输的过程数据通常会进行编码,服务器会对数据进行编码,如果服务器使用的解码方式与网页的原始编码不一致,将会导致服务器的解码出现乱码
  • get问题

    • get方式提交的数据会拼接在请求行的URL后面进行传递,不同的浏览器处理方式是不一样的,有的浏览器会进行编码,有的浏览器则会直接提交
    • 数据到达服务器之后,服务器会根据参数的编码方式对参数进行解码,如果没有编码则服务器直接接收,如果进行了服务器能够解析的编码,服务器也会进行转换
  • get解决

    • 在Tomcat的conf/server.xml中配置URL的编码方式

      <Connector post"8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8" />
      
  • post问题

    • post方式提交表单数据是通过请求正文进行传递的,会对数据进行编码;Tomcat会对URL传递的参数进行解码,但是不能对请求正文进行解码,因此需要我们在server类中接收数据之前对客户端提交的请求数据进行编码设置;
  • post解决

    • request.setCharaterEncoding("utf-8");

3.3response对象

  1. 设置响应状态行

    1. 设置状态中的状态码
      • response.setStatus(数字);例200
  2. 设置响应头

    1. 设置响应客户端的数据格式

      • response.setContentType("数据格式");例text/html
    2. 设置响应客户端的数据长度

      • response.setContentLength(数字);例1024
    3. 设置其他的响应头属性

      • response.setHeader("属性",格式);

      • //例
        response.setHeader("ContentType","text/html");
        //等价于
        response.setContentType("text/html");
        
  3. 设置响应正文

    • 设置响应客户端的数据编码格式
      • response.setCharacterEncoding("编码格式");例utf-8

4.Servlet练习

4.1环境准备

  1. 创建一个java web工程

    1. 右击模块->选择Add Framework Support..
    2. javaEE中选择Web Application
    3. 默认为4.0版本和创建一个web.xml文件
    4. 默认生成一个web目录(就是项目的名字)
  2. 搭建jdbc环境

    1. 导入jdbc所需的驱动jar包,数据库连接池jar包,DBUtils.jar包

      1. 在web-inf中新建一个lib目录,全小写

      2. 将jar包放入进来

      3. 添加到模块

        image-20221122211926813

    2. 配置连接池信息

      1. 在项目中新建一个properties文件存放连接池信息

      2. # 数据库连接池信息
        url=jdbc:mysql:///db-sgms?characterEncoding=utf8
        username=root
        password=123456
        driverClassName=com.mysql.cj.jdbc.Driver
        # 连接池属性
        # 连接池初始化连接数
        initiaSize=10
        # 最大的连接数
        maxActive=50
        # 最小空闲数
        minIdle=5
        # 超时等待时间(毫秒)
        maxWait=30000
        
    3. jdbc连接并且获取对象

      • package utils;
        
        import com.alibaba.druid.pool.DruidDataSource;
        import com.alibaba.druid.pool.DruidDataSourceFactory;
        import com.mysql.cj.SimpleQuery;
        
        import javax.sql.DataSource;
        import java.io.FileInputStream;
        import java.io.IOException;
        import java.io.InputStream;
        import java.sql.Connection;
        import java.sql.SQLException;
        import java.util.Properties;
        
        public class DruidUtils {
            private static DruidDataSource druidDataSource;
            static {
                try {
                    //导入配置文件,获取连接池对象
                    InputStream is = DruidUtils.class.getResourceAsStream("Druid.Properties");
                    Properties properties = new Properties();
                    properties.load(is);
                    druidDataSource = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);
                    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        //从连接池中获取连接池对象
            public static DataSource getDataSource() {
                return druidDataSource;
            }
            public static Connection getConnection(){
                Connection connection = null;
                try {
                    connection = druidDataSource.getConnection();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                return connection;
            }
        }
        
    4. 数据库环境准备

      • -- 学生信息表
        create table students(
        	stu_num char(5) primary key,
        	stu_name varchar(20) not null,
        	stu_gender char(2) not null,
        	stu_age int not null,
        	stu_pwd varchar(20) not null
        );
        
        -- 课程信息表
        create table courses(
        	course_id char(6) primary key,
        	course_name varchar(50) not null
        );
        
        -- 学生成绩表
        create table grades(
        	gid int primary key auto_increment,
        	snum char(5) not null,  
        	cid char(6) not null,   
          score int not null
        );
        

4.2练习要求

  • 根据项目业务流程图,完成需要数据库操作
    • 学生登录实现:
      • 根据输入的学号和密码查询学生信息,如果查询到了说明学号密码输入正确,登录成功;
      • 根据输入的学号查询学生,如果查询到了说明学号正确,再比较输入的密码和查询出来的密码是否一致,如果一致则登录成功;
    • 查询成绩:
      • 根据学号和课程号从成绩表中查询成绩
  • image-20221123164935222

4.3代码实现

4.3.1创建Student和StudentDAO

  • 根据学号和密码查询学生信息,验证是否登录成功

    package dto;
    //学生信息类
    public class Student {
        private String stuNum;
        private String stuName;
        private String stuGender;
        private int stuAge;
        private String stuPwd;
        //setget无参有参方法
    }
    
    package dao;
    
    import dto.Student;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import utils.DruidUtils;
    
    import javax.management.Query;
    import java.sql.SQLException;
    
    public class StudentDAO {
        public Student QueryStudentNumAndPwd(String stuNum,String stuPwd) {
            //如果查询不到就是为null
            Student student = null;
            try {
                //定义SQL语句
                String sql = "select stu_num stuNum,stu_name stuName,stu_gender stuGender,stu_age stuAge,stu_pwd stuPwd from students where stu_num=? and stu_pwd=?";
                //查询
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                student = queryRunner.query(sql,new BeanHandler<Student>(Student.class),stuNum,stuPwd);
            }catch (Exception e){
                e.printStackTrace();
            }
            //返回结果
            return student;
        }
    }
    

4.3.2创建Grade和GradeDAO

  • 根据学号和课程号查询学生的科目成绩

    package dto;
      
      public class Grade {
          private String snum;
          private String sname;
          private String cid;
          private String cname;
          private int score;
      	//setget无参有参方法
      }
    
    package dao;
      
      import dto.Grade;
      import dto.Student;
      import org.apache.commons.dbutils.QueryRunner;
      import org.apache.commons.dbutils.handlers.BeanHandler;
      import utils.DruidUtils;
      
      import java.sql.SQLException;
      
      public class GradeDAO {
          public Grade QueryGradeSnumAndCid(String snum, String cid) {
              //如果查询不到就是为null
              Grade grade = null;
              try {
                  //定义SQL语句
                  String sql = "select s.stu_num snum,s.stu_name sname,c.course_id cid,c.course_name cname ,g.score score from students s INNER JOIN grades g INNER JOIN courses c  on s.stu_num = g.snum and g.cid = c.course_id where s.stu_num=? and c.course_id=?";
                  //查询
                  QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                  grade = queryRunner.query(sql,new BeanHandler<Grade>(Grade.class),snum,cid);
              }catch (Exception e){
                  e.printStackTrace();
              }
              //返回结果
              return grade;
          }
      }
    

4.3.3实现LoginPageServlet登录界面

  • 编写动态网页发送信息

    package Servlets;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @WebServlet("/login")
    public class LoginPageServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        }
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            super.doGet(req, resp);
            //响应一个登录界面
            //设置响应信息
            response.setStatus(200);
            response.setContentType("text/html;charset=utf-8");
            response.setCharacterEncoding("utf-8");
    
            //输出
            PrintWriter out = response.getWriter();
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<meta charset='utf-8'>");
            out.println("<title>学生成绩查询系统-登录</title>");
            out.println("</head>");
            out.println("<body>");
            //发送到CheckStudent这个页面,让CheckStudent页面验证
             out.println("<form action='CheckStudent' method='post'>");
            out.println("<h3>学生成绩查询系统—学生登录</h3>");
            out.println("<p>学号:<input type='text' name='stuNum' placeholder='学生学号'/></p>");
            out.println("<p>密码:<input type='password' name='stuPwd' placeholder='登录密码'/></p>");
            out.println("<p><input type='submit' value='登录'/></p>");
            out.println("</form>");
            out.println("</body>");
            out.println("</html>");
            //刷新关闭
            out.flush();
            out.close();
        }
    }
    

4.3.4实现CheckServlet验证登录

  • 验证登录信息

    package Servlets;
    
    import dao.StudentDAO;
    import dto.Student;
    import jakarta.servlet.*;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    
    @WebServlet("/CheckServlet")
    public class CheckServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //接收学号和密码
            //设置编码
            request.setCharacterEncoding("utf-8");
            //账户
            String num = request.getParameter("stuNum");
            //密码
            String pwd = request.getParameter("stuPwd");
    
            //调用studentDAO中的方法,根据学号和密码查询学生信息是否存在
            StudentDAO studentDAO = new StudentDAO();
            Student student = studentDAO.QueryStudentNumAndPwd(num, pwd);
            
            //判断查询结果,响应客户端
    //根据登录验证的不同结果响应给客户端不同的页面
    if(student == null){
        //登录失败:响应客户端登录页面,提示“登录失败,学号或密码错误!”
    
        //转发到下一个Servlet是可以通过request传递数据过去的
        request.setAttribute("tips","登录失败,学号或密码错误!");
        //转发到LoginPageServlet:在当前Servlet类的doPost方法转到,也会转发到下一个Servelt的doPost
        request.getRequestDispatcher("login").forward(request,response);
    }else{
        //登录成功:响应客户端系统的主页
        //重定向到IndexPageServlet:无需传递参数到IndexPageServlet,所以我们可以使用重定向
        response.sendRedirect("IndexPageServlet");
    }
    }
    }
    

4.3.5实现IndexPageServlet主页面

  • 显示成绩查询的主页面,并且能够输入学号和课程号查询成绩

    package Servlets;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @WebServlet("/IndexPageServlet")
    public class IndexPageServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //响应一个登录界面
            //设置响应信息
            response.setStatus(200);
            response.setContentType("text/html;charset=utf-8");
            response.setCharacterEncoding("utf-8");
    
            //输出
             PrintWriter out = response.getWriter();
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<meta charset='utf-8'>");
            out.println("<title>学生成绩查询系统-主页面</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<table border='1' width='100%' height='700'>");
            out.println("<tr height='100'><td colspan='2'><label>学生成绩查询系统欢迎您!</label></td></tr>");
            out.println("<tr>");
            out.println("<td width='200'>2-1</td>");
            out.println("<td align='center' valign='top'>");
            //跳转到GradeQueryServlet类
            out.println("<form action='GradeQueryServlet' method='post'>");
                out.println("<h3>查询成绩</h3>");
                out.println("<p>学号:<input type='text' name='stuNum' placeholder='学生学号'/></p>");
                out.println("<p>课程:<input type='text' name='courseId' placeholder='课程编号'/></p>");
                out.println("<p><input type='submit' value='查询'/></p>");
                out.println("</form>");
            out.println("</td>");
            out.println("</tr>");
            out.println("</table>");
            out.println("</body>");
            out.println("</html>");
            //关闭
            out.flush();
            out.close();
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        }
    }
    
    

4.3.6登录失败转发到LoginPageServlet

  • CheckServlet转发到LoginPageServlet,并传递参数

    //3.判断查询结果,响应客户端
    //根据登录验证的不同结果响应给客户端不同的页面
    if(student == null){
        //登录失败:响应客户端登录页面,提示“登录失败,学号或密码错误!”
    
        //转发到下一个Servlet是可以通过request传递数据过去的
        request.setAttribute("tips","登录失败,学号或密码错误!");
        //转发到LoginPageServlet:在当前Servlet类的doPost方法转到,也会转发到下一个Servelt的doPost
        request.getRequestDispatcher("login").forward(request,response);
    }else{
        //登录成功:响应客户端系统的主页
        
    }
    

    LoginPageServlet接收参数响应登录页面

    package Servlets;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @WebServlet("/login")
    public class LoginPageServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //doPost调用doGet
            doGet(request,response);
        }
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //接收从CheckServlet传递的提示信息
            String tips = (String) request.getAttribute("tips");
    
            //响应一个登录界面
            //设置响应信息
            response.setStatus(200);
            response.setContentType("text/html;charset=utf-8");
            response.setCharacterEncoding("utf-8");
    
            //输出
            PrintWriter out = response.getWriter();
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<meta charset='utf-8'>");
            out.println("<title>学生成绩查询系统-登录</title>");
            out.println("</head>");
            out.println("<body>");
            if(tips != null) {
                out.println("<label style='color:red'>" + tips + "</label>");
                //发送到CheckStudent这个页面,让CheckStudent页面验证
                out.println("<form action='CheckStudent' method='post'>");
                out.println("<h3>学生成绩查询系统—学生登录</h3>");
                out.println("<p>学号:<input type='text' name='stuNum' placeholder='学生学号'/></p>");
                out.println("<p>密码:<input type='password' name='stuPwd' placeholder='登录密码'/></p>");
                out.println("<p><input type='submit' value='登录'/></p>");
                out.println("</form>");
                out.println("</body>");
                out.println("</html>");
                //刷新关闭
                out.flush();
                out.close();
    
            }
        }
    }
    

4.3.7登录成功重定向IndexPageServlet

  • CheckServlet重定向IndexPageServlet

    //3.判断查询结果,响应客户端
    //根据登录验证的不同结果响应给客户端不同的页面
    if(student == null){
        //登录失败:响应客户端登录页面,提示“登录失败,学号或密码错误!”
    
        //转发到下一个Servlet是可以通过request传递数据过去的
        request.setAttribute("tips","登录失败,学号或密码错误!");
        //转发到LoginPageServlet:在当前Servlet类的doPost方法转到,也会转发到下一个Servelt的doPost
        request.getRequestDispatcher("login").forward(request,response);
    }else{
        //登录成功:响应客户端系统的主页
        //重定向到IndexPageServlet:无需传递参数到IndexPageServlet,所以我们可以使用重定向
        response.sendRedirect("IndexPageServlet");
    }
    

4.3.8实现GradeQueryServlet查询成绩

  • GradeQueryServlet接收客户端输入的学号、课程ID,查询成绩

    package Servlets;
    
    import dao.GradeDAO;
    import dto.Grade;
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    
    @WebServlet("/GradeQueryServlet")
    public class GradeQueryServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //接收浏览器输入的学号和课程id
            String snum = request.getParameter("stuNum");
            String cid = request.getParameter("courseId");
            //调用gradeDAO中的方法看是否匹配并且查询创建
            GradeDAO gradeDAO = new GradeDAO();
            Grade grade = gradeDAO.QueryGradeSnumAndCid(snum, cid);
            //查询到成绩之后,将成绩传递到GradePageServlet
            //由GradePageServlet响应给浏览器一个页面,并把成绩显示出来
            request.setAttribute("grage",grade);
            request.getRequestDispatcher("GradePageServlet").forward(request,response);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //如果允许客户端get和post方式提交,我们可以在doGet中调用doPost,业务代码写在doPost
            doPost(request,response);
        }
    }
    
    

4.3.9实现GradePageServlet显示成绩

  • GradePageServle响应给客户端一个成绩结果页面,并显示成绩
package Servlets;

import dto.Grade;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/GradePageServlet")
public class GradePageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doPost(req,resp);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1.接收转发时传递的成绩
        Grade grade = (Grade) request.getAttribute("grade");

        //2.设置响应头
        response.setStatus(200);
        response.setContentType("text/html;charset=utf-8");
        response.setCharacterEncoding("utf-8");

        //3.响应成绩结果页面
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<meta charset='utf-8'>");
        out.println("<title>学生成绩查询系统</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<table border='1' width='100%' height='700'>");
        out.println("<tr height='100'><td colspan='2'><label>学生成绩查询系统欢迎您!</label></td></tr>");
        out.println("<tr>");
        out.println("<td width='200'>2-1</td>");
        out.println("<td align='center' valign='top'>");
        //查询成绩的表单 : 修改action属性为 GradeQueryServlet
        out.println("<h3>查询结果</h3>");
        if(grade != null){
            out.println("<table width='200' border='1' cellspacing='0'>");
            out.println("<tr><td>学号</td><td>"+grade.getSnum()+"</td></tr>");
            out.println("<tr><td>姓名</td><td>"+grade.getSname()+"</td></tr>");
            out.println("<tr><td>课程ID</td><td>"+grade.getCid()+"</td></tr>");
            out.println("<tr><td>课程名</td><td>"+grade.getCname()+"</td></tr>");
            out.println("<tr><td>成绩</td><td><label style='color:red;font-weight:bold'>"+grade.getScore()+"</label></td></tr>");
            out.println("</table>");
        }else{
            out.println("<label style='color:red;font-weight:bold;font-size:20px'>学号或课程号有误!</label>");
        }
        out.println("<a href='IndexPageServlet'>继续查询</a>");
        out.println("</td>");
        out.println("</tr>");
        out.println("</table>");
        out.println("</body>");
        out.println("</html>");
        //关闭
        out.flush();
        out.close();
    }
}

标签:servlet,request,println,import,javaweb2,response,out
From: https://www.cnblogs.com/Myvlog/p/16923844.html

相关文章