# JaveWeb的文件執行方式 ###### tags: `Java Web` ## 1.執行流程 ### 1.客戶端傳送add.html指令到服務器端 ### 2.服務器端調出add.html的資料,回傳到服務器端 ### 3.add.html的指令"action = "add" ",會觸發服務器端的add指令 ### 4.add指令調用AddServlet的方法 #### (1)獲取客戶端發送的數據 #### (2)調用DAO中的方法完成添加功能 #### (3)在控制台打印成功 ![](https://i.imgur.com/qQn4nJk.png) ## 2.AddServlet文件撰寫 ### (1)需要繼承HttpServlet類別: 在Servlet的導包中取得,因此需要導入Tomcat的導包 ![](https://i.imgur.com/3dJnICX.png) #### 導包的方式 ![](https://i.imgur.com/pVg4kqd.png) ```java= package com.atguigu.servlets; import com.atguigu.servlets.dao.FruitDAO; import com.atguigu.servlets.dao.impl.FruitDAOImpl; import com.atguigu.servlets.pojo.Fruit; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AddServlet extends HttpServlet { //doPost:響應html文件中的method="post"請求 //request:客戶端發送的數據會包裝成request @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //getParameter:獲取數據中的參數,只能是String(若是其他類,要自行強轉) String fname = request.getParameter("fname"); String priceStr = request.getParameter("price"); Integer price = Integer.parseInt(priceStr); String fcountStr = request.getParameter("fcount"); Integer fcount = Integer.parseInt(fcountStr); String remark = request.getParameter("remark"); System.out.println("fname = " +fname); System.out.println("price = " +price); System.out.println("fcount = " +fcount); System.out.println("remark = " +remark); } } ``` ## 3.設置action="add"與AddServlet的對應關係 指令action="add"並不會直接調用AddServlet.java的指令,而是要透過編輯WEB-INF底下的web.xml才能確立兩者的對應關係。 ![](https://i.imgur.com/akdcAYZ.png) ```xml= <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>AddServlet</servlet-name> <servlet-class>com.atguigu.servlets.AddServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AddServlet</servlet-name> <url-pattern>/add</url-pattern> </servlet-mapping> <!-- 1.用戶發請求,action = add 2.項目中,web.xml中找到url-pattern = /add ->第12行 3.找第11行的 servlet-name = AddServlet 4.找和servlet-mapping中servlet-name一致的servlet,找到第7行 5.找第8行的servlet-class ->com.atguigu.servlets.AddServlet 6.用戶發送的是post請求(method = post),因此tomcat會執行AddServlet中的doPost方法 --> </web-app> ``` ### 4.運行 #### 在網頁中生成請求 ![](https://i.imgur.com/klkK4LO.png) #### 請求過程 1.向pro07/add發送請求,請求方式"post" ![](https://i.imgur.com/XQXXbYW.png) ![](https://i.imgur.com/45qbPoQ.png) 2.控制台看到的打印值 ![](https://i.imgur.com/a8U6hh6.png) 3.建立對應的Fruit、FruitDAOImpl、BaseDAO文件 #### 实体类 ```java= package com.atguigu.servlets.pojo; public class Fruit { private Integer fid ; private String fname ; private Integer price ; private Integer fcount ; private String remark ; public Fruit(){} public Fruit(Integer fid, String fname, Integer price, Integer fcount, String remark) { this.fid = fid; this.fname = fname; this.price = price; this.fcount = fcount; this.remark = remark; } public Integer getFid() { return fid; } public void setFid(Integer fid) { this.fid = fid; } public String getFname() { return fname; } public void setFname(String fname) { this.fname = fname; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public Integer getFcount() { return fcount; } public void setFcount(Integer fcount) { this.fcount = fcount; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } @Override public String toString() { return fid + "\t\t" + fname + "\t\t" + price +"\t\t" + fcount +"\t\t" + remark ; } } ``` #### DAO 实现类 ```java= package com.atguigu.servlets.dao.impl; import com.atguigu.servlets.dao.FruitDAO; import com.atguigu.servlets.dao.base.BaseDAO; import com.atguigu.servlets.pojo.Fruit; import java.util.List; public class FruitDAOImpl extends BaseDAO<Fruit> implements FruitDAO { @Override public List<Fruit> getFruitList() { return super.executeQuery("select * from t_fruit"); } @Override public boolean addFruit(Fruit fruit) { String sql = "insert into t_fruit values(0,?,?,?,?)"; int count = super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark()) ; //insert语句返回的是自增列的值,而不是影响行数 //System.out.println(count); return count>0; } @Override public boolean updateFruit(Fruit fruit) { String sql = "update t_fruit set fcount = ? where fid = ? " ; return super.executeUpdate(sql,fruit.getFcount(),fruit.getFid())>0; } @Override public Fruit getFruitByFname(String fname) { return super.load("select * from t_fruit where fname like ? ",fname); } @Override public boolean delFruit(String fname) { String sql = "delete from t_fruit where fname like ? " ; return super.executeUpdate(sql,fname)>0; } } ``` #### 连接数据库 ```java= package com.atguigu.servlets.dao.base; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.sql.*; import java.util.ArrayList; import java.util.List; public abstract class BaseDAO<T> { public final String DRIVER = "com.mysql.jdbc.Driver" ; public final String URL = "jdbc:mysql://localhost:3306/fruitdb?useUnicode=true&characterEncoding=utf-8&useSSL=false"; public final String USER = "root"; public final String PWD = "123456" ; protected Connection conn ; protected PreparedStatement psmt ; protected ResultSet rs ; //T的Class对象 private Class entityClass ; public BaseDAO(){ //getClass() 获取Class对象,当前我们执行的是new FruitDAOImpl() , 创建的是FruitDAOImpl的实例 //那么子类构造方法内部首先会调用父类(BaseDAO)的无参构造方法 //因此此处的getClass()会被执行,但是getClass获取的是FruitDAOImpl的Class //所以getGenericSuperclass()获取到的是BaseDAO的Class Type genericType = getClass().getGenericSuperclass(); //ParameterizedType 参数化类型 Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); //获取到的<T>中的T的真实的类型 Type actualType = actualTypeArguments[0]; try { entityClass = Class.forName(actualType.getTypeName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } protected Connection getConn(){ try { //1.加载驱动 Class.forName(DRIVER); //2.通过驱动管理器获取连接对象 return DriverManager.getConnection(URL, USER, PWD); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return null ; } protected void close(ResultSet rs , PreparedStatement psmt , Connection conn){ try { if (rs != null) { rs.close(); } if(psmt!=null){ psmt.close(); } if(conn!=null && !conn.isClosed()){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } //给预处理命令对象设置参数 private void setParams(PreparedStatement psmt , Object... params) throws SQLException { if(params!=null && params.length>0){ for (int i = 0; i < params.length; i++) { psmt.setObject(i+1,params[i]); } } } //执行更新,返回影响行数 protected int executeUpdate(String sql , Object... params){ boolean insertFlag = false ; insertFlag = sql.trim().toUpperCase().startsWith("INSERT"); try { conn = getConn(); if(insertFlag){ psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); }else { psmt = conn.prepareStatement(sql); } setParams(psmt,params); int count = psmt.executeUpdate() ; rs = psmt.getGeneratedKeys(); if(rs.next()){ return ((Long)rs.getLong(1)).intValue(); } return count ; } catch (SQLException e) { e.printStackTrace(); }finally { close(rs,psmt,conn); } return 0; } //通过反射技术给obj对象的property属性赋propertyValue值 private void setValue(Object obj , String property , Object propertyValue){ Class clazz = obj.getClass(); try { //获取property这个字符串对应的属性名 , 比如 "fid" 去找 obj对象中的 fid 属性 Field field = clazz.getDeclaredField(property); if(field!=null){ field.setAccessible(true); field.set(obj,propertyValue); } } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } //执行复杂查询,返回例如统计结果 protected Object[] executeComplexQuery(String sql , Object... params){ try { conn = getConn() ; psmt = conn.prepareStatement(sql); setParams(psmt,params); rs = psmt.executeQuery(); //通过rs可以获取结果集的元数据 //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等 ResultSetMetaData rsmd = rs.getMetaData(); //获取结果集的列数 int columnCount = rsmd.getColumnCount(); Object[] columnValueArr = new Object[columnCount]; //6.解析rs if(rs.next()){ for(int i = 0 ; i<columnCount;i++){ Object columnValue = rs.getObject(i+1); //33 苹果 5 columnValueArr[i]=columnValue; } return columnValueArr ; } } catch (SQLException e) { e.printStackTrace(); } finally { close(rs,psmt,conn); } return null ; } //执行查询,返回单个实体对象 protected T load(String sql , Object... params){ try { conn = getConn() ; psmt = conn.prepareStatement(sql); setParams(psmt,params); rs = psmt.executeQuery(); //通过rs可以获取结果集的元数据 //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等 ResultSetMetaData rsmd = rs.getMetaData(); //获取结果集的列数 int columnCount = rsmd.getColumnCount(); //6.解析rs if(rs.next()){ T entity = (T)entityClass.newInstance(); for(int i = 0 ; i<columnCount;i++){ String columnName = rsmd.getColumnName(i+1); //fid fname price Object columnValue = rs.getObject(i+1); //33 苹果 5 setValue(entity,columnName,columnValue); } return entity ; } } catch (SQLException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } finally { close(rs,psmt,conn); } return null ; } //执行查询,返回List protected List<T> executeQuery(String sql , Object... params){ List<T> list = new ArrayList<>(); try { conn = getConn() ; psmt = conn.prepareStatement(sql); setParams(psmt,params); rs = psmt.executeQuery(); //通过rs可以获取结果集的元数据 //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等 ResultSetMetaData rsmd = rs.getMetaData(); //获取结果集的列数 int columnCount = rsmd.getColumnCount(); //6.解析rs while(rs.next()){ T entity = (T)entityClass.newInstance(); for(int i = 0 ; i<columnCount;i++){ String columnName = rsmd.getColumnName(i+1); //fid fname price Object columnValue = rs.getObject(i+1); //33 苹果 5 setValue(entity,columnName,columnValue); } list.add(entity); } } catch (SQLException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } finally { close(rs,psmt,conn); } return list ; } } ``` ## 5.更新addServlet文件 ```java= package com.atguigu.servlets; import com.atguigu.servlets.dao.FruitDAO; import com.atguigu.servlets.dao.impl.FruitDAOImpl; import com.atguigu.servlets.pojo.Fruit; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AddServlet extends HttpServlet { //doPost:響應html文件中的method="post"請求 //request:客戶端發送的數據會包裝成request @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //getParameter:獲取數據中的參數,只能是String(若是其他類,要自行強轉) String fname = request.getParameter("fname"); String priceStr = request.getParameter("price"); Integer price = Integer.parseInt(priceStr); String fcountStr = request.getParameter("fcount"); Integer fcount = Integer.parseInt(fcountStr); String remark = request.getParameter("remark"); FruitDAO fruitDAO = new FruitDAOImpl(); boolean flag = fruitDAO.addFruit(new Fruit(0,fname,price,fcount,remark)); System.out.println(flag ? "添加成功":"添加失敗"); } } ```