浅析JSP动态网页开发技术


    JSP<==>HTML?
    这种说法是完全错误的,无论是从JSP的运行环境,还是从JSP的工作原理,亦或是从JSP与Java语言的混合开发来看,JSP与HTML完全是八竿子打不着的两种事务。

1-JSP的运行环境

    JSP全称为:JSP Server Pages,是一种动态网页开发技术,主要用于服务器端的JavaEE程序开发。
    而要使用JSP技术开发JavaEE服务端程序,就必须预先提供Java开发工具JDK环境支持。同时为了解决JSP页面转译为Java-Servlet类的问题,还需要提供JSP引擎(还需提供包含JSP引擎的Tomcat服务器开发环境)。
    反观HTML(超文本标记语言),是一种静态网页开发技术,主要用于浏览器客户端网页页面的开发。也只需要有一个可以解析HTML静态页面、构建DOM树和完成页面渲染的浏览器即可。

2-JSP的工作原理

工作原理概述

    JSP是一种服务端的动态网页开发技术,那么就意味着:从服务器端的JSP页面到浏览器客户端的HTML页面,中间需要一系列的“转译”工作。详细过程可以描述如下:

    [1]客户端发起Request请求;
    
    [2]Web容器接收Request请求,并识别其为一个对JSP页面的请求,将其传递给JSP引擎;
    
    [3]JSP引擎从磁盘中载入JSP文件,然后将其转换为Servlet类(转换方式:将JSP中所有的模板文件转换为
    	PrintWriter对象的println()方法进行打印,同时将其它的JSP元素转换为Java代码);
    	
    [4]JSP引擎将Servlet编译为可执行类,并将原始请求传递给Servlet引擎处理;
    
    [5]Web服务器的某组件将会调用Servlet引擎,然后载入并执行Servlet类。在执行过程中,Servlet 产生
    	 HTML 格式的输出并将其内嵌于 HTTP response 中上交给 Web 服务器;
    	 
    [6]Web服务器以静态HTML网页的形式将HTTP response返回到浏览器中;
    
    [7]浏览器将接收到的HTTP response中包含的HTML网页内容,进行渲染

在这里插入图片描述

JSP文件的转译过程

原始JSP页面:score.jsp

    现有如下JSP页面,经过JSP引擎处理,可将其转译成为一个Java-Servlet类.

<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.text.DecimalFormat" %>
<%--
  Created by IntelliJ IDEA.
  User: 13241
  Date: 2022/2/7
  Time: 12:28
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>分数等级</title>
</head>
<body>
		score=
		<%
		    double score = Math.random() * 101;
		    PrintWriter writer = response.getWriter();
		%>
		<%=new DecimalFormat("0.00").format(score)%>
		
		grade=
		<%
		    String grade = "E";
		    switch ((int) score / 10) {
		        case 10:
		        case 9: {
		            grade = "A";
		            break;
		        }
		        case 8: {
		            grade = "B";
		            break;
		        }
		        case 7: {
		            grade = "C";
		            break;
		        }
		        case 6: {
		            grade = "D";
		            break;
		        }
		        default: {
		            grade = "E";
		        }
		    }
		%>
		<%=grade%>
</body>
</html>


转译后的Servlet类:score_jsp.java

    JSP文件(score.jsp)转译过来的Servlet类(score_jsp ),继承了org.apache.jasper.runtime.HttpJspBase类,实现了JSPSourceDependent,和JSPSourceImports两个接口。而HttpJspBase类继承自HttpServlet类,    因此,整个JSP文件本质上来说,就相当于一个Servlet类。这应当是JSP与HTML之间的最根本不同之处。

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.io.PrintWriter;
import java.text.DecimalFormat;

public final class score_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = new java.util.HashSet<>();
    _jspx_imports_classes.add("java.io.PrintWriter");
    _jspx_imports_classes.add("java.text.DecimalFormat");
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      final java.lang.String _jspx_method = request.getMethod();
      if ("OPTIONS".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        return;
      }
      if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
    }

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write('\r');
      out.write('\n');
      out.write("\r\n");
      out.write("\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("    <title>分数等级</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("    score=\r\n");
      out.write("    ");

        double score=Math.random()*101;
        PrintWriter writer=response.getWriter();
    
      out.write("\r\n");
      out.write("\r\n");
      out.write('\r');
      out.write('\n');
      out.write('\r');
      out.write('\n');
      out.write('\r');
      out.write('\n');
      out.write("\r\n");
      out.write("    ");
      out.print(new DecimalFormat("0.00").format(score));
      out.write("\r\n");
      out.write("\r\n");
      out.write("    grade=\r\n");
      out.write("    ");

        String grade="E";
        switch ((int)score/10){
            case 10:
            case 9:{
                grade="A";
                break;
            }
            case 8:{
                grade="B";
                break;
            }
            case 7:{
                grade="C";
                break;
            }
            case 6:{
                grade="D";
                break;
            }
            default:{
                grade="E";
            }
        }
    
      out.write('\r');
      out.write('\n');
      out.write('\r');
      out.write('\n');
      out.write('\r');
      out.write('\n');
      out.write('\r');
      out.write('\n');
      out.write("\r\n");
      out.write("    ");
      out.print(grade);
      out.write("\r\n");
      out.write("</body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

score_jsp追根溯源:HttpJspBase

     HttpBase类(源码已经放在下面,可以对如下所述的内容进行验证)继承自HttpServlet类(具体继承结构如下图所示),HttpBase重写了父类中的init(),service()和destory()方法,并且自定义了 _jspInit,_jspService,_jspDestory,并在重写的init方法中调用了_JSPInit,在重写的service方法中调用了_jspService,在重写的destory方法中调用了_jspDestory.
     由于HttpBase类的内部重写了service()方法,在service内部调用了其定义的抽象方法 _jspService(request, response);。因此,HttpBase的子类只需重写这个抽象方法 _jspService(request, response);即可完成对客户端request请求的处理操作。

在这里插入图片描述

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jasper.runtime;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import org.apache.jasper.Constants;
import org.apache.jasper.compiler.Localizer;
/**
 * This is the super class of all JSP-generated servlets.
 *
 * @author Anil K. Vijendran
 */
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
    private static final long serialVersionUID = 1L;
    protected HttpJspBase() {
    }
    @Override
    public final void init(ServletConfig config)
            throws ServletException
    {
        super.init(config);
        jspInit();
        _jspInit();
    }
    @Override
    public String getServletInfo() {
        return Localizer.getMessage("jsp.engine.info", Constants.SPEC_VERSION);
    }
    @Override
    public final void destroy() {
        jspDestroy();
        _jspDestroy();
    }
    /**
     * Entry point into service.
     */
    @Override
    public final void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        _jspService(request, response);
    }
    @Override
    public void jspInit() {
    }
    public void _jspInit() {
    }
    @Override
    public void jspDestroy() {
    }
    protected void _jspDestroy() {
    }
    @Override
    public abstract void _jspService(HttpServletRequest request,
                                     HttpServletResponse response)
            throws ServletException, IOException;
}

JSP的实质

    可以用一句话来总结此部分的全部内容:JSP是未经过JSP引擎转移的Java-Servlet类。

3-JSP的重要概念

    JSP在重要的概念方面,主要如下:

1】三大指令标签:@page@include@taglib2】九大内置对象(如下图所示):与Servlet部分的ServletContext-Application域、HttpSession-Session域、HttpServletRequest-Request域的概念紧密相关,主要就是通过内置对象实现Java代码与JSP页面之间的数据传递。。

在这里插入图片描述
    在此对上述内容不再做详细的阐述,可查看:菜鸟教程-Servlet,里面已经讲得十分详尽了。

4-JSP+Servlet开发案例

前序

    虽然JSP与Java代码可以混合使用,甚至一个JSP文件就能够完全替换到相同功能的Servlet类,但是,这样开发服务器程序不仅效率低下,而且难以维护。

    于是,有了如下的开发思路:Servlet更适合专门编写JAVA代码,JSP更擅长展示数据,Servlet更适合做后台程序,所以在分层上,往往将Servlet作为控制层Controller使用,JSP作为视图层view使用,可以让Servlet将数据发送给JSP,然后在JSP上展示数据

案例开发

项目结构搭建

在这里插入图片描述

jdbc.properties配置文件编写

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT&useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
username=root
password=root
minSize=5
maxSize=10

pojo层源代码

package com.xwd.pojo;

import org.omg.CORBA.INTERNAL;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

/**
 * @ClassName Emp
 * @Description: com.xwd.dao
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 18:57
 * @version: 1.0
 */
public class Emp
        implements Serializable {
    private static final long serialVersionUID = -4657007327124076894L;
    //properties
    private Integer empno;
    private String ename;
    private Integer mgr;
    private String job;
    private Date hiredate;
    private BigDecimal sal;
    private BigDecimal comm;
    private Integer deptno;
    private String grade;
    //setter
    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public void setSal(BigDecimal sal) {
        this.sal = sal;
    }

    public void setComm(BigDecimal comm) {
        this.comm = comm;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    //getter
    public Integer getEmpno() {
        return empno;
    }

    public String getEname() {
        return ename;
    }

    public Integer getMgr() {
        return mgr;
    }

    public String getJob() {
        return job;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public BigDecimal getSal() {
        return sal;
    }

    public BigDecimal getComm() {
        return comm;
    }

    public Integer getDeptno() {
        return deptno;
    }

    public String getGrade() {
        return grade;
    }

    //constructors
    public Emp() {
        this(null,null,null,null,null,null,null,null,null);
    }

    public Emp(Integer empno, String ename, Integer mgr, String job, Date hiredate, BigDecimal sal, BigDecimal comm, Integer deptno, String grade) {
        super();
        this.empno = empno;
        this.ename = ename;
        this.mgr = mgr;
        this.job = job;
        this.hiredate = hiredate;
        this.sal = sal;
        this.comm = comm;
        this.deptno = deptno;
        this.grade = grade;
    }

    //methods
    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", mgr=" + mgr +
                ", job='" + job + '\'' +
                ", hiredate=" + hiredate +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptno=" + deptno +
                ", grade=" + grade +
                '}';
    }
}

dao层源代码

数据库连接池类:ConnectionPool
package com.xwd.dao;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties;

/**
 * @ClassName ConnectionPool
 * @Description: com.xwd.utils
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 19:07
 * @version: 1.0
 */
public class ConnectionPool {
    //properties
    private static String DRIVER;
    private static String URL;
    private static String USERNAME;
    private static String PASSWORD;
    private static int maxSize;
    private static int minSize;
    private static Properties properties;
    private static LinkedList<Connection> pools;

    //block
    static {
        //获取输入流对象
        InputStream inputStream = ConnectionPool.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            properties=new Properties();
            properties.load(inputStream);
            //初始化Connection数据库连接参数
            DRIVER=properties.getProperty("driver");
            URL=properties.getProperty("url");
            USERNAME=properties.getProperty("username");
            PASSWORD=properties.getProperty("password");
            minSize=Integer.valueOf(properties.getProperty("minSize"));
            maxSize=Integer.valueOf(properties.getProperty("maxSize"));
            //注册数据库连接驱动
            Class.forName(DRIVER);
            //初始化数据库连接池
            pools=new LinkedList<>();
            for (int i = 0; i < minSize; i++) {
                Connection connection = initConnection();
                System.out.println("Connection "+connection.hashCode()+" has been initialized");
                pools.addFirst(connection);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("JDBC Driver Initialized ERROR!");
        }
    }

    //methods
    /*
     * 初始化minSize个数据库连接对象
     * @return
     */
    private static Connection initConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("Connection "+connection.hashCode()+" initialized ERROR!");
        }
        return connection;
    }

    /*
     * 从数据库连接池中获取数据库连接对象
     * @return
     */
    public static Connection getConnection(){
        Connection connection=null;
        //判断数据库连接池中是否还有Connection
        if (pools.size()>0){
            connection=pools.removeLast();
        }else {
            connection = initConnection();
        }
        return connection;
    }


    /*
     * 归还数据库连接对象
     * @param connection 要归还的数据库连接对象
     */
    public static void returnConnection(Connection connection){
        if (connection==null){
            System.out.println("OPERATION was denied because connection is null");
            return;
        }
        //如果connection未被关闭
        try {
            if (!connection.isClosed()) {
                //修改事务处理模式为——自动提交模式
                connection.setAutoCommit(true);
                //判断pools是否达到存储上限
                if (pools.size()<maxSize){
                    //归还数据库连接对象
                    pools.addFirst(connection);
                }else {
                    connection.close();
                }
            }else {
                System.out.println("Connection "+connection.hashCode()+" has been closed already!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }



}

数据库操作基类:BaseDao
package com.xwd.dao;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName BaseDao
 * @Description: com.xwd.dao
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 19:06
 * @version: 1.0
 */
public abstract class BaseDao extends ConnectionPool {
    //methods
    public static List baseQuery(Class clazz,String sql,Object ...args){
        List list=null;
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        //数据库操作
        try {
            //获取数据库连接
            connection = getConnection();
            statement = connection.prepareStatement(sql);
            //设置查询参数
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i+1,args[i]);
            }
            //执行SQL查询
            resultSet = statement.executeQuery();
            //实例化集合
            list=new ArrayList();
            //解析结果集
            while (resultSet.next()) {
                //通过反射创建对象
                Object newInstance = clazz.newInstance();
                //通过反射获取属性字段
                Field[] declaredFields = clazz.getDeclaredFields();
                int index=1;
                if (null!=declaredFields){
                    for (Field declaredField : declaredFields) {
                        //如果为static字段,就直接进入下一次循环
                        if (Modifier.isStatic(declaredField.getModifiers()))
                            continue;
                        //非static字段,进行解析
                        //获取字段名称
                        String name = declaredField.getName();
                        //获取setter方法
                        String setMethodName = getSetterByFiledNmae(name);
                        //通过反射获取setter方法
                        Method declaredMethod = clazz.getDeclaredMethod(setMethodName, declaredField.getType());
                        //System.out.println("setMethodName:"+setMethodName+"\t"+"ParamType:"+declaredField.getType().getName());
                        //调用gsetter方法
                        declaredMethod.invoke(newInstance,resultSet.getObject(index));
                        index++;
                    }
                    //System.out.println(newInstance.toString());
                    //将封装好的newInstance放入list中
                    list.add(newInstance);
                }
            }
            return list;
        }  catch (Exception e){
            e.printStackTrace();
            return list;
        }
    }

    private static String getSetterByFiledNmae(String fieldName) {
        if (null==fieldName||"".equals(fieldName))
            return null;
        return "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
    }
}

EmpDao接口定义
package com.xwd.dao;

import com.xwd.pojo.Emp;

import java.util.List;

/**
 * @ClassName EmoDao
 * @Description: com.xwd.dao
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 19:01
 * @version: 1.0
 */
public interface EmpDao {
    //methods

    /*
     * query all Emp in DB
     * @return the list of Emp's info
     */
    public abstract List<Emp> findAll();
}

EmpDaoImpl子类实现
package com.xwd.dao.impl;

import com.xwd.dao.BaseDao;
import com.xwd.dao.EmpDao;
import com.xwd.pojo.Emp;

import java.util.List;

/*
 * @ClassName EmpDaoImpl
 * @Description: com.xwd.dao.impl
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 19:01
 * @version: 1.0
 */
public class EmpDaoImpl extends BaseDao implements EmpDao {
    //methods
    @Override
    public List<Emp> findAll() {
        String query_sql="\tSELECT emp.empno,ename,mgr,job,hiredate,sal,comm,deptno,grade\n" +
                "\tFROM emp,\t(SELECT empno,\n" +
                "\t\t\t\t\t\t\t(CASE\n" +
                "\t\t\t\t\t\t\t\tWHEN (sal+comm)>10000.0 THEN 'A'\n" +
                "\t\t\t\t\t\t\t\tWHEN (sal+comm)>8000.0 AND (sal+comm)<10000.0 THEN 'B'\n" +
                "\t\t\t\t\t\t\t\tELSE 'C' \n" +
                "\t\t\t\t\t\t\t\tEND)\n" +
                "\t\t\t\t\t\t\tas grade\n" +
                "\t\t\t\t\t\t\tFROM emp ) as A\n" +
                "\tWHERE emp.empno=A.empno";
        return (List<Emp>)(baseQuery(Emp.class, query_sql));
    }
}


service层源代码

EmpService接口定义
package com.xwd.service;

import com.xwd.pojo.Emp;

import java.util.List;

/**
 * @ClassName EmpService
 * @Description: com.xwd.service
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 19:05
 * @version: 1.0
 */
public interface EmpService {
    //methods
    /**
     * query all Emp in DB
     * @return the list of Emp's info
     */
    public abstract List<Emp> findAll();
}

EmpServiceImpl子类实现
package com.xwd.service.impl;

import com.xwd.dao.EmpDao;
import com.xwd.dao.impl.EmpDaoImpl;
import com.xwd.pojo.Emp;
import com.xwd.service.EmpService;

import java.util.List;

/**
 * @ClassName EmpServiceImpl
 * @Description: com.xwd.service.impl
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 19:05
 * @version: 1.0
 */
public class EmpServiceImpl implements EmpService {
    //properties
    private static EmpDao empDao=new EmpDaoImpl();

    //methods
    @Override
    public List<Emp> findAll() {
        return empDao.findAll();
    }
}

servlet层源代码

EmpServlet类实现
package com.xwd.servlet;

import com.alibaba.fastjson.JSON;
import com.xwd.pojo.Emp;
import com.xwd.service.EmpService;
import com.xwd.service.impl.EmpServiceImpl;

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;
import java.io.PrintWriter;
import java.util.List;

/**
 * @ClassName EmpServlet
 * @Description: com.xwd.servlet
 * @Auther: xiwd
 * @Date: 2022/2/7 - 02 - 07 - 19:02
 * @version: 1.0
 */
@WebServlet(
        name = "empservlet",
        value = {
                "/empservlet"
        }
)
public class EmpServlet extends HttpServlet {
    //properties
    private static EmpService empService=new EmpServiceImpl();


    //methods
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //super.doGet(req, resp);
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //super.doPost(req, resp);
        //设置参数解析字符编码格式
        req.setCharacterEncoding("UTF-8");
        //设置响应字符编码格式
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        //解析请求参数
        List<Emp> emps = empService.findAll();
        //设置request域的attribute属性信息
        req.setAttribute("emps",emps);
        //请求转发
        req.getRequestDispatcher("/showEmp.jsp").forward(req,resp);
    }
}

JSP页面编写:showEmp.jsp

<%@ page import="java.util.List" %>
<%@ page import="com.xwd.pojo.Emp" %>
<%--
  Created by IntelliJ IDEA.
  User: 13241
  Date: 2022/2/7
  Time: 20:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Emp-Infomation</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .infotable {
            margin: 0px auto;
            border: 2px solid skyblue;
            width: 80%;
        }

        tr,
        td {
            border: 1px solid black;
        }
        td {
            text-align: center;
        }

        tr:first-child {
            font-weight: 700;
        }
    </style>
</head>
<body>
<table class="infotable" cellspacing="0px" cellpadding="0px">
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>上级编号</td>
        <td>职务</td>
        <td>入职日期</td>
        <td>薪资</td>
        <td>补助</td>
        <td>部门号</td>
        <td>薪资等级</td>
    </tr>
    <%
        //从request内置对象读取参数信息
        List<Emp> emps = (List<Emp>)(request.getAttribute("emps"));
        int size = emps.size();
    %>
    <%
        for (int i = 0; i < size; i++) {
            //Emp emp = emps.get(i);
            //将数据设置到PageContext域,不断更新相同属性名称的值即可
            pageContext.setAttribute("emp",emps.get(i));
    %>
        <tr>
            <td>${pageScope.emp.empno}</td>
            <td>${pageScope.emp.ename}</td>
            <td>${pageScope.emp.mgr}</td>
            <td>${pageScope.emp.job}</td>
            <td>${pageScope.emp.hiredate}</td>
            <td>${pageScope.emp.sal}</td>
            <td>${pageScope.emp.comm}</td>
            <td>${pageScope.emp.deptno}</td>
            <td>${pageScope.emp.grade}</td>
        </tr>
    <%}%>
</table>

</body>
</html>

数据表emp:sql转储文件

在这里插入图片描述

/*
 Navicat Premium Data Transfer

 Source Server         : mysql8
 Source Server Type    : MySQL
 Source Server Version : 80023
 Source Host           : localhost:3306
 Source Schema         : test

 Target Server Type    : MySQL
 Target Server Version : 80023
 File Encoding         : 65001

 Date: 07/02/2022 21:20:01
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for emp
-- ----------------------------
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp`  (
  `empno` int(0) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `ename` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '姓名',
  `job` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '职务',
  `mgr` int(0) DEFAULT NULL COMMENT '上级编号',
  `hiredate` date DEFAULT NULL COMMENT '入职日期',
  `sal` decimal(10, 0) DEFAULT NULL COMMENT '薪资',
  `comm` decimal(10, 0) DEFAULT NULL COMMENT '补助',
  `deptno` int(0) NOT NULL COMMENT '部门号',
  PRIMARY KEY (`empno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES (1, 'Mark', 'MANAGER', 7369, '2020-12-25', 10000, 2000, 10);
INSERT INTO `emp` VALUES (2, 'Tom', 'MANAGER', 7369, '2020-12-25', 10000, 2000, 10);
INSERT INTO `emp` VALUES (3, 'Smith', 'CLERK', 7902, '2018-12-27', 8000, 500, 20);
INSERT INTO `emp` VALUES (4, 'Ward', 'SALESMAN', 7698, '2019-12-27', 9000, 0, 20);

SET FOREIGN_KEY_CHECKS = 1;

案例效果

在这里插入图片描述

    完整项目文件也可访问:Gitee仓库下载此案例。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是席木木啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值