Java web learning record

javaweb

Shang Silicon Valley java web learning record

HTML

html files can be written directly by changing txt to a suffix. Use the browser to view the effect. Here are a few demo s to understand what html files can do and how to do it.

<html>
   <head>
      <title>This is my first web page</title>
      <meta charset="UTF-8">
   </head>
   <body>
      <!--
      HELLO WORLD!<br/>Hello, HTML!
      <p>Here is a paragraph</p>
      <p>Here is the second paragraph</p>
      <img src="D:\sgg2021\0927_javaweb\1109\02.code\imgs\girl.jpg" width="57" height="73" alt="Here is a picture"/>
      <h1>Title I</h1>
      <h2>Title I</h2>
      <h3>Title I</h3>
      <h4>Title I</h4>
      <h5>Title I</h5>
      <h6>Title I</h6>
      -->
      Ranking of Wulin experts:
      <ol type="i" start="3">
         <li>Sweeping monk</li>
         <li>Xiao Yuanshan</li>
         <li>Murongbo</li>
         <li>Phyllostachys pubescens</li>
         <li>A Zi</li>
      </ol>
      List of Wulin assembly members:
      <ul type="circle">
         <li>Qiao Feng</li>
         <li>Aju</li>
         <li>Madame Ma</li>
         <li>Bai Shijing</li>
      </ul>

      You are?<b><i><u>like</u></i></b>yes<b>sweet</b>Moon cake or<i>salty</i><u>Moon Cake</u>?
      <br/>

      Chemical formula of water molecule: H<sub>2</sub>O <br/>
      Chemical formula of oxygen: O<sup>2</sup><br/>

      5&lt;10
      10&gt;5
      5&le;10
      10&ge;5
      Registered trademark &reg;
      Copyright symbol &copy;

      <span>You Ting Zhao</span>,Revenge for taking his wife.

      <a href="http://www.baidu. com" target="_ Self "> Baidu</a>

   </body>
</html>

<!--
1)
html Language is interpreted, not compiled
 Browsers are fault tolerant

2)
html The page consists of a pair of tags:<html></html>
<html> It's called the start tag
</html>Call it the end tag
3)
title Represents the title of the web page
4)
Can be in meta Set the encoding method in the label
5)
<br/>Indicates a line break. br The label is a single label. Single label: the start label and end label are the same, and the slash is placed after the word
6)
p Represents a paragraph label
7)
img Label picture label
   src Property indicates the path of the picture file
   width and height Represents the size of the picture
   alt Tips for pictures
8)
Problem path:
   1. Relative path
   2. Absolute path
9)
h1~h6 : Title label
10)
Tag list:
- ol Ordered list
   start Indicates from*Start, type Type of display: A a I i 1(deafult)
- ul Unordered list
   type disc(default) , circle , square
11) u Underline b bold  i Italics

12) Superscript sup   subscript sub

13) HTML Entities in: less than sign &lt; Greater than or equal to sign &ge; copyright &copy;

14) span Block markers without line breaks

15) a Represents a hyperlink
      href Linked address
      target:
         _self Open in this window
         _blank Open in a new window
         _parent Open in parent window
         _top  Open in top window

16) div layer
-->
<html>
   <head>
      <title>Form label learning</title>
      <meta charset="UTF-8">
      
   </head>
   <body>
      <table border="1" width="600" cellspacing="0" cellpadding="4">
         <tr align="center">
            <th>full name</th>
            <th>Sect</th>
            <th>Famous stunt</th>
            <th>Internal skill value</th>
         </tr>
         <tr align="center">
            <td>Qiao Feng</td>
            <td>a group of beggars</td>
            <td>Shaolin Changquan</td>
            <td>5000</td>
         </tr>
         <tr align="center">
            <td>Phyllostachys pubescens</td>
            <td>Lingjiu Palace</td>
            <td>Beiming magic skill</td>
            <td>15000</td>
         </tr>
         <tr align="center">
            <td>Sweeping monk</td>
            <td>Shaolin Temple</td>
            <td>72 stunts</td>
            <td>unknown</td>
         </tr>
      </table>
      <hr/>
      <table border="1" cellspacing="0" cellpadding="4" width="600">
         <tr>
            <th>name</th>
            <th>Unit Price</th>
            <th>quantity</th>
            <th>Subtotal</th>
            <th>operation</th>
         </tr>
         <tr align="center">
            <td>Apple</td>
            <td rowspan="2">5</td>
            <td>20</td>
            <td>100</td>
            <td><img src="imgs/del.jpg" width="24" height="24"/></td>
         </tr>
         <tr align="center">
            <td>pineapple</td>
            <td>15</td>
            <td>45</td>
            <td><img src="imgs/del.jpg" width="24" height="24"/></td>
         </tr>
         <tr align="center">
            <td>watermelon</td>
            <td>6</td>
            <td>6</td>
            <td>36</td>
            <td><img src="imgs/del.jpg" width="24" height="24"/></td>
         </tr>
         <tr align="center">
            <td>total</td>
            <td colspan="4">181</td>
         </tr>
      </table>
   </body>
</html>
<!--
17) form table
   that 's ok     tr
   column     td
   Header column    th

   table There are the following attributes in (although it has been eliminated, it's best to understand it)
   - border: Thickness of table border
   - width:Width of the table
   - cellspacing: Cell spacing
   - cellpadding: Cell fill

   tr There is an attribute in: align -> center , left , right 

   rowspan : Row merge
   colspan : Column merge

-->
<html>
   <head>
      <title>Form label learning</title>
      <meta charset="UTF-8">
      
   </head>
   <body>
      <form action="demo04.html" method="post">
         Nickname?<input type="text" value="Please enter your nickname"/><br/>
         password:<input type="password" name="pwd"/><br/>
         Gender:<input type="radio" name="gender" value="male"/>male
              <input type="radio" name="gender" value="female" checked/>female<br/>
         Hobbies:<input type="checkbox" name="hobby" value="basketball"/>Basketball
              <input type="checkbox" name="hobby" value="football" checked/>Football
              <input type="checkbox" name="hobby" value="earth" checked/>earth<br/>
         Constellation:<select name="star">
               <option value="1">Aries</option>
               <option value="2" selected>Taurus</option>
               <option value="3">Gemini</option>
               <option value="4">scorpio</option>
               <option value="5">libra</option>
              </select><br/>
         remarks:<textarea name="remark" rows="4" cols="50"></textarea><br/>
         <input type="submit" value=" Register "/>
         <input type="reset" value="Reset"/>
         <input type="button" value="This is a normal button"/>
      </form>
   </body>
</html>
<!--
18) form  form

19) input type="text" Represents a text box, where name Property must be specified, otherwise the data in this text box will not be sent to the server in the future
   input type="password" Indicates the password box
   input type="radio" Represents a radio button. It should be noted that, name The attribute values should be consistent, so as to have the effect of mutual exclusion;Can pass checked Property sets the item selected by default
   input type="checkbox" Indicates a check box. name It is recommended to keep the attribute values consistent, so that when we get the value on the server in the future, we will get an array
   select Represents a drop-down list. Each option is option,among value Property is the value sent to the server , selected Indicates the item selected by default
   textarea Represents a multiline text box (or text field),its value The value is the content between the start and end tags
   input type="submit" Indicates the submit button
   input type="reset" Indicates the reset button
   input type="button" Represents a normal button

-->
<html>
   <head>
      <meta charset="utf-8">
   </head>
   <body>
      Here is demo06 The content of the page!!
      <iframe src="frames/top.html"/>
   </body>
</html>

<!--
frameset Indicates the page frame. This label has been eliminated. Understand it. You don't need to master it
frame Represents a specific page reference in the framework

iframe Embed a sub page in a page

Summary:
1.HTML Is an interpreted text markup language, case insensitive
2.html,head,title,meta,body,br,p,hr,div,table,form,u,i,b,sup,sub,&nbsp;,span,ul,ol,li,tr,td,th,h1-h6,a,input,select,textarea,img
2-1. html , head , title , meta , body , br , ul , ol , h1-h6 , a , img , &nbsp;, p , div , span
2-2. table tr , th , td 
2-3. form(action='' , method='post') input type='text,pasword,radio,checkbox,submit,button,reset"   <select> , <textarea>

-->

CSS

It may be troublesome to adjust pages in html, but it is rather troublesome to use each label, but with css style, there is a fixed pattern for the same label.

1) CSS Role of: beautiful style of page display
2) CSS Basic syntax of: label style; Class style; ID Style; Combination style; Embedded style sheet; Internal style sheet; External style sheet
3) Box model: border,margin,padding
4) Positioning and floating: position,float,DIV+CSS layout
*{
   color: threeddarkshadow;
}
body{
   margin:0;
   padding:0;
   background-color:#808080;
}
div{
   position:relative;
   float:left;
}

#div_container{
   width:80%;
   height:100%;
   border:0px solid blue;
   margin-left:10%;
   float:left;
   background-color: honeydew;
   border-radius:8px;
}
#div_fruit_list{
   width:100%;
   border:0px solid red;
}
#tbl_fruit{
   width:60%;
   line-height:28px;
   margin-top:120px;
   margin-left:20%;
}
#tbl_fruit , #tbl_fruit tr , #tbl_fruit th , #tbl_fruit td{
   border:1px solid gray;
   border-collapse:collapse;
   text-align:center;
   font-size:16px;
   font-family:"Blackbody";
   font-weight:lighter;
   
}
.w20{
   width:20%;
}
.delImg{
   width:24px;
   height:24px;
}
.btn{
   border:1px solid lightgray;
   width:80px;
   height:24px;
}
<html>
   <head>
      <meta charset="utf-8">
      <link rel="stylesheet" href="css/demo05.css">
   </head>
   <body>
      <div id="div_container">
         <div id="div_fruit_list">
            <table id="tbl_fruit">
               <tr>
                  <th class="w20">name</th>
                  <th class="w20">Unit Price</th>
                  <th class="w20">quantity</th>
                  <th class="w20">Subtotal</th>
                  <th>operation</th>
               </tr>
               <tr>
                  <td>Apple</td>
                  <td>5</td>
                  <td>20</td>
                  <td>100</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>
                  <td>watermelon</td>
                  <td>3</td>
                  <td>20</td>
                  <td>60</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>
                  <td>pineapple</td>
                  <td>4</td>
                  <td>25</td>
                  <td>100</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>
                  <td>Durian</td>
                  <td>3</td>
                  <td>30</td>
                  <td>90</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>
                  <td>total</td>
                  <td colspan="4">999</td>
               </tr>
            </table>
         </div>
      </div>
   </body>
</html>

JS

javascript, you can perform some operations on the page, but you need to bind events.

  1. JS is a script language running on the client side (browser side), and its syntax style is similar to that of java
  2. JS is a weakly typed language var str = 99;
  3. JS function hello(var num) {}
  4. DOM Technology:
    4-1) mouse hover: OnMouseOver, event Srclelement, event delivery, parentelement, style backgroundColor
    Mouse out: onmouseout
    4-2) mouse click: hand / pointer, onclick, TD innerText , td. innerHTML="", td. firstChild. value=oldPrice
    Lose focus: onblur, input parentElement. innerText = newPrice ;
    Update subtotal: input = event srcElement , tr = input. parentElement. parentElement ; tr.cells , parseInt
    Update total: document getElementById(“fruit_tbl”) , fruitTbl.rows
    4-3) delete a line: IMG, img parentElement. parentElement. rowIndex , table. deleteRow(rowIndex)
window.onload=function(){
   updateZJ();
   //When the page is loaded, we need to bind various events
   //Get the table by id
   var fruitTbl =  document.getElementById("tbl_fruit");
   //Get all rows in the table
   var rows = fruitTbl.rows ;
   for(var i = 1 ; i<rows.length-1 ; i++){
      var tr = rows[i];
      //1. Bind the mouse hover and set the background color event when leaving
      tr.onmouseover=showBGColor;
      tr.onmouseout=clearBGColor;
      //Get tr all cells in this row
      var cells = tr.cells;
      var priceTD = cells[1];
      //2. Bind the event that the mouse hovers in the unit price cell and changes the gesture
      priceTD.onmouseover = showHand ;
      //3. Bind the event of clicking the unit price cell with the mouse
      priceTD.onclick=editPrice;


      //7. Bind and delete the click event of the small icon
      var img = cells[4].firstChild;
      if(img && img.tagName=="IMG"){
         //Bind click event
         img.onclick = delFruit ;
      }

   }
}

function delFruit(){
   if(event && event.srcElement && event.srcElement.tagName=="IMG"){
      //alert means that a dialog box pops up with only the OK button
      //confirm means that a dialog box pops up with OK and Cancel buttons. When you click OK, it returns true; otherwise, it returns false
      if(window.confirm("Are you sure to delete the current inventory record")){
         var img = event.srcElement ;
         var tr = img.parentElement.parentElement ;
         var fruitTbl = document.getElementById("tbl_fruit");
         fruitTbl.deleteRow(tr.rowIndex);

         updateZJ();
      }
   }

}

//When the mouse clicks the unit price cell, the price is edited
function editPrice(){
   if(event && event.srcElement && event.srcElement.tagName=="TD"){
      var priceTD = event.srcElement ;
      //The purpose is to judge that the current priceTD has child nodes, and the first child node is a text node, TextNode corresponds to 3, and elementnode corresponds to 1
      if(priceTD.firstChild && priceTD.firstChild.nodeType==3){
         //innerText means to set or get the internal text of the current node
         var oldPrice = priceTD.innerText ;
         //innerHTML means to set the internal HTML of the current node
         priceTD.innerHTML="<input type='text' size='4'/>";
         // <td><input type='text' size='4'/></td>
         var input = priceTD.firstChild;
         if(input.tagName=="INPUT"){
            input.value = oldPrice ;
            //Check the text inside the input box
            input.select();
            //4. Bind the event that the input box loses focus, lose focus, and update the unit price
            input.onblur=updatePrice ;

            //8. Bind the event pressed by the keyboard on the input box. Here I need to ensure that the user inputs numbers
            input.onkeydown=ckInput;
         }
      }
      
   }
}

//Method for checking the value pressed by the keyboard
function ckInput(){
   var kc = event.keyCode ;
   // 0 ~ 9 : 48~57
   //backspace : 8
   //enter : 13
   //console.log(kc);

   if(!( ( kc>=48 && kc<=57 ) || kc==8 || kc==13 )){
      event.returnValue=false;
   }

   if(kc==13){
      event.srcElement.blur();
   }

}

//Method of updating unit price
function updatePrice(){
   if(event && event.srcElement && event.srcElement.tagName=="INPUT"){
      var input = event.srcElement ;
      var newPrice = input.value ;
      //The parent node of the input node is td
      var priceTD = input.parentElement ;
      priceTD.innerText = newPrice ;

      //5. Update the value of the cell of the subtotal of the current line
      //priceTD. The parent element of parentelement TD is tr
      updateXJ(priceTD.parentElement);

   }
}

//Update subtotal for specified line
function updateXJ(tr){
   if(tr && tr.tagName=="TR"){
      var tds = tr.cells;
      var price = tds[1].innerText ;
      var count = tds[2].innerText ;
      //The type of the value obtained by innerText is string type, so type conversion is required before mathematical operation
      var xj = parseInt(price) * parseInt(count);
      tds[3].innerText = xj ;

      //6. Update total
      updateZJ();
   }

}

//Update totals
function updateZJ(){
   var fruitTbl = document.getElementById("tbl_fruit");
   var rows = fruitTbl.rows ;
   var sum = 0 ;
   for(var i = 1; i<rows.length-1 ; i++){
      var tr = rows[i];
      var xj = parseInt(tr.cells[3].innerText);     //Nan not a number is not a number
      sum = sum + xj ;
   }
   rows[rows.length-1].cells[1].innerText = sum ;
}


//When the mouse hovers, the background color is displayed
function showBGColor(){
   //Event: current event
   //event. Srclelement: event source
   //alert(event.srcElement);
   //alert(event.srcElement.tagName); --> TD
   if(event && event.srcElement && event.srcElement.tagName=="TD"){
      var td = event.srcElement ;
      //td.parentElement indicates the parent element of TD - > tr
      var tr = td.parentElement ;
      //If you want to set the style of a node through js code, you need to add style
      tr.style.backgroundColor = "navy" ;

      //tr.cells means to get all the cells in this tr
      var tds = tr.cells;
      for(var i = 0 ; i<tds.length ; i++){
         tds[i].style.color="white";
      }
   }
}

//When the mouse leaves, the original style is restored
function clearBGColor(){
   if(event && event.srcElement && event.srcElement.tagName=="TD"){
      var td = event.srcElement ;
      var tr = td.parentElement ;
      tr.style.backgroundColor="transparent";
      var tds = tr.cells;
      for(var i = 0 ; i<tds.length ; i++){
         tds[i].style.color="threeddarkshadow";
      }
   }
}

//When the mouse hovers over the unit price cell, a gesture is displayed
function showHand(){
   if(event && event.srcElement && event.srcElement.tagName=="TD"){
      var td = event.srcElement ;
      //Cursor: cursor
      td.style.cursor="hand";
   }

}
<html>
   <head>
      <meta charset="utf-8">
      <link rel="stylesheet" href="css/demo05.css">
      <script type="text/javascript" src="js/demo09.js"></script>
   </head>
   <body>
      <div id="div_container">
         <div id="div_fruit_list">
            <table id="tbl_fruit">
               <tr>
                  <th class="w20">name</th>
                  <th class="w20">Unit Price</th>
                  <th class="w20">quantity</th>
                  <th class="w20">Subtotal</th>
                  <th>operation</th>
               </tr>
               <tr>
                  <td>Apple</td>
                  <td>5</td>
                  <td>20</td>
                  <td>100</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>   
                  <td>watermelon</td>
                  <td>3</td>
                  <td>20</td>
                  <td>60</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>
                  <td>pineapple</td>
                  <td>4</td>
                  <td>25</td>
                  <td>100</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>
                  <td>Durian</td>
                  <td>3</td>
                  <td>30</td>
                  <td>90</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
               <tr>
                  <td>total</td>
                  <td colspan="4">999</td>
               </tr>
            </table>
            <hr/>
            <div id="add_fruit_div">
               <table>
                  <tr>
                     <td>name:</td>
                     <td><input type='text' id='fname'/></td>
                  </tr>
                  <tr>
                     <td>Unit Price:</td>
                     <td><input type='text' id='price'/></td>
                  </tr>
                  <tr>
                     <td>number:</td>
                     <td><input type='text' id='fcount'/></td>
                  </tr>
                  <tr>
                     <th colspan="2">
                        <input type='button' class="btn" value="add to"/>
                        <input type='button' class="btn" value="Refill"/>
                     </th>
                  </tr>
               </table>
            </div>
         </div>
      </div>
   </body>
</html>

BS,CS

Tomcat

what is tomcat? My understanding is that it can link the operation of web pages with the data in the database.

In this part, it is difficult to deploy the project to tomcat at the beginning, but after actually understanding its principle, the steps become clear.

Briefly summarize the steps below:

New project – new module – add web to the module – create artifacts – add lib to artfcats – add tomcat configuration – add artifacts to the dependency of tomcat.

Simple implementation of tomcat - servlet

Realization idea

Project structure

Fruit database information

BaseDao.java

package com.atguigu.fruit.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 ;

    //Class object of T
    private Class entityClass ;

    public BaseDAO(){
        //getClass() gets the Class object. At present, we execute new FruitDAOImpl() and create an instance of FruitDAOImpl
        //Then the child class constructor will first call the parameterless constructor of the parent class (BaseDAO)
        //Therefore, getClass() here will be executed, but getClass gets the Class of FruitDAOImpl
        //So getGenericSuperclass() gets the Class of BaseDAO
        Type genericType = getClass().getGenericSuperclass();
        //ParameterizedType parameterized type
        Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
        //Get the real type of T in < T >
        Type actualType = actualTypeArguments[0];
        try {
            entityClass = Class.forName(actualType.getTypeName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected Connection getConn(){
        try {
            //1. Load drive
            Class.forName(DRIVER);
            //2. Obtain the connection object through the driver manager
            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();
        }
    }

    //Set parameters for preprocessing command objects
    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]);
            }
        }
    }

    //Execute update and return the number of affected rows
    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;
    }

    //Assign a propertyValue value to the property attribute of obj object through reflection technology
    private void setValue(Object obj ,  String property , Object propertyValue){
        Class clazz = obj.getClass();
        try {
            //Get the property name corresponding to the string property, such as "fid" to find the fid property in the obj object
            Field field = clazz.getDeclaredField(property);
            if(field!=null){
                field.setAccessible(true);
                field.set(obj,propertyValue);
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    //Execute complex queries and return, for example, statistical results
    protected Object[] executeComplexQuery(String sql , Object... params){
        try {
            conn = getConn() ;
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //The metadata of the result set can be obtained through rs
            //Metadata: data that describes the result set data. In short, it is the columns and types of the result set

            ResultSetMetaData rsmd = rs.getMetaData();
            //Gets the number of columns in the result set
            int columnCount = rsmd.getColumnCount();
            Object[] columnValueArr = new Object[columnCount];
            //6. Parsing rs
            if(rs.next()){
                for(int i = 0 ; i<columnCount;i++){
                    Object columnValue = rs.getObject(i+1);     //33 Apple 5
                    columnValueArr[i]=columnValue;
                }
                return columnValueArr ;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(rs,psmt,conn);
        }
        return null ;
    }

    //Execute the query and return a single entity object
    protected T load(String sql , Object... params){
        try {
            conn = getConn() ;
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //The metadata of the result set can be obtained through rs
            //Metadata: data that describes the result set data. In short, it is the columns and types of the result set

            ResultSetMetaData rsmd = rs.getMetaData();
            //Gets the number of columns in the result set
            int columnCount = rsmd.getColumnCount();
            //6. Parsing 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 Apple 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 ;
    }


    //Execute query and return 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();

            //The metadata of the result set can be obtained through rs
            //Metadata: data that describes the result set data. In short, it is the columns and types of the result set

            ResultSetMetaData rsmd = rs.getMetaData();
            //Gets the number of columns in the result set
            int columnCount = rsmd.getColumnCount();
            //6. Parsing 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 Apple 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 ;
    }
}

FruitDAOImpl.java

package com.atguigu.fruit.dao.impl;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.base.BaseDAO;
import com.atguigu.fruit.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()) ;
        //The insert statement returns the value of the auto increment column, not the number of rows
        //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;
    }
}

FruitDAO.java

package com.atguigu.fruit.dao;

import com.atguigu.fruit.pojo.Fruit;

import java.util.List;

public interface FruitDAO {
    //Query inventory list
    List<Fruit> getFruitList();

    //New inventory
    boolean addFruit(Fruit fruit);

    //Modify inventory
    boolean updateFruit(Fruit fruit);

    //Query specific inventory by name
    Fruit getFruitByFname(String fname);

    //Delete specific inventory records
    boolean delFruit(String fname);
}

Fruit.java

package com.atguigu.fruit.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 ;
    }
}

AddServlet.java

package com.atguigu.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.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 {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        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 ? "Added successfully!" : "Failed to add!");
    }
}

web.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. The user sends a request, action=add
    2. In the project, web.xml Found in url-pattern = /add   -> Line 12
    3. Find line 11 servlet-name = AddServlet
    4. Find peace servlet-mapping in servlet-name coincident servlet , Find line 7
    5. Find line 8 servlet-class -> com.atguigu.servlets.AddServlet
    6. The user sent post Request( method=post) , therefore tomcat Will execute AddServlet Medium doPost method
    -->
</web-app>

add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="add" method="post">
        name:<input type="text" name="fname"/><br/>
        Price:<input type="text" name="price"/><br/>
        stock:<input type="text" name="fcount"/><br/>
        remarks:<input type="text" name="remark"/><br/>
        <input type="submit" value="add to" />
    </form>
</body>
</html>

review:

  1. New project - new module
  2. Add web in module
  3. Create artifact - deploy package
  4. lib - artifact
    There is an artifact before adding mysql jar. At this time, the jar package is not added to the deployment package
    Then there will be a prompt in the Problems in the project settings. Click fix and select add to
    In addition, we can also directly create a new lib folder under WEB-INF.
    The bad thing is that this lib can only be exclusive to the current moudle. If there is a second moudle, we need to create a new lib again.
  5. During deployment, modify the application Context. Then go back to the server tab and check the value of the URL.
    The value of URL refers to the URL that will be accessed by default after tomcat automatically opens the browser you specify after startup.
    After startup, error 404.404 means that the specified resource cannot be found.
    If our website is: http://localhost:8080/pro01/ , then it indicates that we are visiting index html.
    We can set the welcome page through the tag (set it in the web.xml of tomcat or in the web.xml of our own project)
  6. 405 question. The currently requested method is not supported. For example, if our form method=post, the Servlet must correspond to doPost. Otherwise, a 405 error is reported.
  7. Null pointer or NumberFormatException. Because there is price and inventory. If you can't get the price, you want to integer null Parseint() will report an error. The reason for the error is mostly because the name="price" is wrong here. As a result, request is still used on the Servlet side Getparameter ("price") to get.
  8. Start with a slash in

servelt

review:

1. Set code
    tomcat8 Before, set the code:
      1)get Request method:
        //At present, the get method does not need to set the code (based on tomcat8)
        //If it is Chinese data sent by get request, transcoding is a little troublesome (before tomcat8)
        String fname = request.getParameter("fname");
        //1. Break the string into byte arrays
        byte[] bytes = fname.getBytes("ISO-8859-1");
        //2. Reassemble the byte array into a string according to the set encoding
        fname = new String(bytes,"UTF-8");
      2)post Request method:
        request.setCharacterEncoding("UTF-8");
    tomcat8 To start, set the code, just for post mode
        request.setCharacterEncoding("UTF-8");
    be careful:
        It should be noted that the code is set(post)This sentence of code must precede all actions to get parameters

2. Servlet Inheritance of - The focus is on service methods( service())
    1. Inheritance relationship
      javax.servlet.Servlet Interface
          javax.servlet.GenericServlet abstract class
              javax.servlet.http.HttpServlet Abstract subclass
    2. correlation method 
      javax.servlet.Servlet Interface:
        void init(config) - Initialization method
        void service(request,response) - Service method
        void destory() - Destruction method

      javax.servlet.GenericServlet Abstract class:
        void service(request,response) - Still abstract

      javax.servlet.http.HttpServlet Abstract subclass:
        void service(request,response) - Not abstract
        1. String method = req.getMethod(); How to get the request
        2. various if Judge and decide to call different requests according to different request methods do method
            if (method.equals("GET")) {
                this.doGet(req,resp);
            } else if (method.equals("HEAD")) {
                this.doHead(req, resp);
            } else if (method.equals("POST")) {
                this.doPost(req, resp);
            } else if (method.equals("PUT")) {
        3. stay HttpServlet In this abstract class, do The methods are similar:
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_get_not_supported");
            if (protocol.endsWith("1.1")) {
                resp.sendError(405, msg);
            } else {
                resp.sendError(400, msg);
            }
        }
    3.Summary:
    1) Inheritance relationship: HttpServlet -> GenericServlet -> Servlet
    2) Servlet Core methods in: init() , service() , destroy()
    3) Service method: when there is a request, service Method will respond automatically (actually tomcat (called by container)
            stay HttpServlet In, we will analyze the way of request: what is it get,post,head still delete wait
            Then decide which one to call do Starting method
            So in HttpServlet These do The default implementation style of methods is 405-We need subclasses to implement corresponding methods, otherwise 405 error will be reported by default
    4) Therefore, we are building a new one Servlet Then we will consider the request method and decide which one to rewrite do method


3. Servlet Life cycle of
    1) Life cycle: the process from birth to death is the life cycle. corresponding Servlet Three methods in: init(),service(),destroy()
    2) By default:
        The first time you receive a request, this Servlet Instantiation will occur(Call construction method),initialization(call init()),Then service(call service())
        From the second request, every time is a service
        When the container is closed, all the servlet The instance will be destroyed and the destroy method will be called
    3) Through the case, we found that:
        - Servlet example tomcat Only one will be created, and all requests will be responded to by this instance.
        - By default, on the first request, tomcat Will be instantiated, initialized, and then served.What are the benefits? Improve the startup speed of the system. What are the disadvantages? The first request takes a long time.
        - Therefore, it is concluded that if the startup speed of the system needs to be improved, this is the current default. If we need to improve the response speed, we should set Servlet Initialization timing.
    4) Servlet Initialization time:
        - The default is instantiation and initialization when receiving a request for the first time
        - We can pass<load-on-startup>To set servlet Start sequence,The smaller the number, the more forward the start, and the minimum value is 0
    5) Servlet In the container: singleton, thread unsafe
        - Singleton: all requests are responded by the same instance
        - Thread unsafe: a thread needs to make logical judgment according to the value of a member variable in this instance. The value of the first thread's execution variable changes, but the value of another thread changes in the middle
        - We already know servlet It's thread unsafe. The inspiration for us is: try not to servlet Member variables are defined in. If you have to define member variables, do not:①Do not modify the value of member variables ②Don't make some logical judgments based on the value of member variables

4. Http agreement
    1) Http It is called hypertext transfer protocol
    2) Http Is stateless
    3) Http The request response consists of two parts: request and response
      - Request:
        The request consists of three parts: 1.Request line; two.Request message header; three.Request subject
        1)The request line contains three messages: 1. Method of request; two.Requested URL ; 3.Requested protocol (usually HTTP1.1)
        2)The request header contains a lot of information that the client needs to tell the server, such as: my browser model, version, type of content I can receive, type of content I send you, length of content, etc
        3)Request body, three cases
          get Method, there is no request body, but there is one queryString
          post Method, with request body, form data
          json Format, with request body, request payload
      - Response:
        The response also contains three copies: 1. Response line; two.Response head; three.Responder
        1)The response line contains three messages: 1.Agreement 2.Response status code(200) 3.Response status(ok)
        2)Response header: contains the information of the server; Information sent by the server to the browser (media type, coding, content length, etc.)
        3)Response body: the actual content of the response (such as the request) add.html Page, the content of the response is<html><head><body><form....)

5. conversation
    1) Http Is stateless
        - HTTP Stateless: the server cannot judge whether the two requests are from the same client or different clients
        - Realistic problems caused by statelessness: the first request is to add goods to the shopping cart, and the second request is to check out; If the two requests cannot be distinguished by the same user, it will lead to confusion
        - The stateless problem is solved by session tracking technology.

    2) Session tracking technology
        - The client sends a request to the server for the first time, and the server obtains session,If it cannot be obtained, create a new one and respond to the client
        - The next time the client sends a request to the server, it will sessionID Bring it to the server, and the server can get it. Then the server will judge that this request and the last request are the same client, so it can distinguish the client
        - frequently-used API: 
          request.getSession() -> Get the current session, if not, create a new session
          request.getSession(true) -> The effect is the same as without parameters
          request.getSession(false) -> Gets the current session. If not, it returns null,No new will be created

          session.getId() -> obtain sessionID
          session.isNew() -> Judge the current session Is it new
          session.getMaxInactiveInterval() -> session The inactivity interval of is 1800 seconds by default
          session.setMaxInactiveInterval()
          session.invalidate() -> Force the session to expire immediately
          ....

    3) session Save scope
      - session The save scope is related to a specific one session Corresponding
      - frequently-used API: 
        void session.setAttribute(k,v)
        Object session.getAttribute(k)
        void removeAttribute(k)

6. Server Internal forwarding and client redirection
    1) Server Internal forwarding : request.getRequestDispatcher("...").forward(request,response);
      - For a request response process, the client does not know how many times it has been forwarded internally
      - The address bar has not changed
    2) Client redirection: response.sendRedirect("....");
      - The process of responding to two requests. The client must know the request URL Change
      - The address bar has changed

Fruit inventory background management system

Thymeleaf

Implementation idea of index

Project structure

FruitDAOImpl.java

package com.atguigu.fruit.dao.impl;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.basedao.BaseDAO;

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 Fruit getFruitByFid(Integer fid) {
        return super.load("select * from t_fruit where fid = ? " , fid);
    }

    @Override
    public void updateFruit(Fruit fruit) {
        String sql = "update t_fruit set fname = ? , price = ? , fcount = ? , remark = ? where fid = ? " ;
        super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark(),fruit.getFid());
    }

    @Override
    public void delFruit(Integer fid) {
        super.executeUpdate("delete from t_fruit where fid = ? " , fid) ;
    }

    @Override
    public void addFruit(Fruit fruit) {
        String sql = "insert into t_fruit values(0,?,?,?,?)";
        super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark());
    }
}

FruitDAO.java

package com.atguigu.fruit.dao;

import com.atguigu.fruit.pojo.Fruit;

import java.util.List;

public interface FruitDAO {
    //Get all inventory list information
    List<Fruit> getFruitList();

    //Obtain specific fruit inventory information according to fid
    Fruit getFruitByFid(Integer fid);

    //Modify the specified inventory record
    void updateFruit(Fruit fruit);

    //Delete the specified inventory record according to fid
    void delFruit(Integer fid);

    //Add new inventory record
    void addFruit(Fruit fruit);
}

AddServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;

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

@WebServlet("/add.do")
public class AddServlet extends ViewBaseServlet {

    private FruitDAO fruitDAO = new FruitDAOImpl();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String fname = request.getParameter("fname");
        Integer price = Integer.parseInt(request.getParameter("price")) ;
        Integer fcount = Integer.parseInt(request.getParameter("fcount"));
        String remark = request.getParameter("remark");

        Fruit fruit = new Fruit(0,fname , price , fcount , remark ) ;

        fruitDAO.addFruit(fruit);

        response.sendRedirect("index");

    }
}

DelServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;
import com.atguigu.myssm.util.StringUtil;

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

@WebServlet("/del.do")
public class DelServlet extends ViewBaseServlet {
    private FruitDAO fruitDAO = new FruitDAOImpl();
    @Override
    public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            fruitDAO.delFruit(fid);

            //super.processTemplate("index",request,response);
            response.sendRedirect("index");
        }
    }
}

EditServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;
import com.atguigu.myssm.util.StringUtil;

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

@WebServlet("/edit.do")
public class EditServlet extends ViewBaseServlet {

    private FruitDAO fruitDAO = new FruitDAOImpl();

    @Override
    public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            Fruit fruit = fruitDAO.getFruitByFid(fid);
            request.setAttribute("fruit",fruit);
            super.processTemplate("edit",request,response);
        }
    }
}

IndexServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

//Servlet supports annotation registration from version 3.0
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
    @Override
    public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList();
        //Save to session scope
        HttpSession session = request.getSession() ;
        session.setAttribute("fruitList",fruitList);
        //The view name here is index
        //Then thymeleaf will map the logical view name to the physical view name
        //Logical view name: index
        //Physical view name: View prefix + logical view name + view suffix
        //So the real view name is: / index html
        super.processTemplate("index",request,response);
    }
}

UpdateServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;

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

@WebServlet("/update.do")
public class UpdateServlet extends ViewBaseServlet {

    private FruitDAO fruitDAO = new FruitDAOImpl();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. Set code
        request.setCharacterEncoding("utf-8");

        //2. Get parameters
        String fidStr = request.getParameter("fid");
        Integer fid = Integer.parseInt(fidStr);
        String fname = request.getParameter("fname");
        String priceStr = request.getParameter("price");
        int price = Integer.parseInt(priceStr);
        String fcountStr = request.getParameter("fcount");
        Integer fcount = Integer.parseInt(fcountStr);
        String remark = request.getParameter("remark");

        //3. Execute update
        fruitDAO.updateFruit(new Fruit(fid,fname, price ,fcount ,remark ));

        //4. Resource jump
        //super.processTemplate("index",request,response);
        //request.getRequestDispatcher("index.html").forward(request,response);
        //Redirection is required here. The purpose is to re send a request to the IndexServlet, re obtain the furitList, and then overwrite it in the session, so that the index The data in the session displayed on the HTML page is the latest
        response.sendRedirect("index");
    }
}

// java.lang.NumberFormatException: For input string: ""

ViewBaseServlet.java

package com.atguigu.myssm.myspringmvc;

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
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 ViewBaseServlet extends HttpServlet {

    private TemplateEngine templateEngine;

    @Override
    public void init() throws ServletException {

        // 1. Get ServletContext object
        ServletContext servletContext = this.getServletContext();

        // 2. Create Thymeleaf parser object
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);

        // 3. Set parameters for parser object
        // ① HTML is the default mode, which is explicitly set to make the code easier to understand
        templateResolver.setTemplateMode(TemplateMode.HTML);

        // ② Set prefix
        String viewPrefix = servletContext.getInitParameter("view-prefix");

        templateResolver.setPrefix(viewPrefix);

        // ③ Set suffix
        String viewSuffix = servletContext.getInitParameter("view-suffix");

        templateResolver.setSuffix(viewSuffix);

        // ④ Set cache expiration time (MS)
        templateResolver.setCacheTTLMs(60000L);

        // ⑤ Set whether to cache
        templateResolver.setCacheable(true);

        // ⑥ Set server-side encoding method
        templateResolver.setCharacterEncoding("utf-8");

        // 4. Create template engine object
        templateEngine = new TemplateEngine();

        // 5. Set the template parser for the template engine object
        templateEngine.setTemplateResolver(templateResolver);

    }

    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1. Set the content type and character set of the response body
        resp.setContentType("text/html;charset=UTF-8");

        // 2. Create a WebContext object
        WebContext webContext = new WebContext(req, resp, getServletContext());

        // 3. Processing template data
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}

StringUtil.java

package com.atguigu.myssm.util;

public class StringUtil {
    //Determine whether the string is null or ''
    public static boolean isEmpty(String str){
        return str==null || "".equals(str);
    }

    public static boolean isNotEmpty(String str){
        return !isEmpty(str);
    }
}

add.css

*{
   color: threeddarkshadow;
}
body{
   margin:0;
   padding:0;
   background-color:#808080;
}
div{
   position:relative;
   float:left;
}

#div_container{
   width:80%;
   height:100%;
   border:0px solid blue;
   margin-left:10%;
   float:left;
   background-color: honeydew;
   border-radius:8px;
}
#div_fruit_list{
   width:100%;
   border:0px solid red;
}
#tbl_fruit{
   width:60%;
   line-height:28px;
   margin-top:16px;
   margin-left:20%;
}
#tbl_fruit , #tbl_fruit tr , #tbl_fruit th , #tbl_fruit td{
   border:1px solid gray;
   border-collapse:collapse;
   text-align:center;
   font-size:16px;
   font-family:"Blackbody";
   font-weight:lighter;
   
}
.w20{
   width:20%;
}
.delImg{
   width:24px;
   height:24px;
}
.btn{
   border:1px solid lightgray;
   width:80px;
   height:24px;
}

.center{
   text-align:center;
}
.f30{
   font-size: 30px;
}

edit.css

*{
   color: threeddarkshadow;
}
body{
   margin:0;
   padding:0;
   background-color:#808080;
}
div{
   position:relative;
   float:left;
}

#div_container{
   width:80%;
   height:100%;
   border:0px solid blue;
   margin-left:10%;
   float:left;
   background-color: honeydew;
   border-radius:8px;
}
#div_fruit_list{
   width:100%;
   border:0px solid red;
}
#tbl_fruit{
   width:60%;
   line-height:28px;
   margin-top:16px;
   margin-left:20%;
}
#tbl_fruit , #tbl_fruit tr , #tbl_fruit th , #tbl_fruit td{
   border:1px solid gray;
   border-collapse:collapse;
   text-align:center;
   font-size:16px;
   font-family:"Blackbody";
   font-weight:lighter;
   
}
.w20{
   width:20%;
}
.delImg{
   width:24px;
   height:24px;
}
.btn{
   border:1px solid lightgray;
   width:80px;
   height:24px;
}

.center{
   text-align:center;
}
.f30{
   font-size: 30px;
}

index.css

*{
   color: threeddarkshadow;
}
body{
   margin:0;
   padding:0;
   background-color:#808080;
}
div{
   position:relative;
   float:left;
}

#div_container{
   width:80%;
   height:100%;
   border:0px solid blue;
   margin-left:10%;
   float:left;
   background-color: honeydew;
   border-radius:8px;
}
#div_fruit_list{
   width:100%;
   border:0px solid red;
}
#tbl_fruit{
   width:60%;
   line-height:28px;
   margin-top:16px;
   margin-left:20%;
}
#tbl_fruit , #tbl_fruit tr , #tbl_fruit th , #tbl_fruit td{
   border:1px solid gray;
   border-collapse:collapse;
   text-align:center;
   font-size:16px;
   font-family:"Blackbody";
   font-weight:lighter;
   
}
.w20{
   width:20%;
}
.delImg{
   width:24px;
   height:24px;
}
.btn{
   border:1px solid lightgray;
   width:80px;
   height:24px;
}

.center{
   text-align:center;
}
.f30{
   font-size: 30px;
}

web.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">
    <!-- Configure context parameters -->
    <context-param>
        <param-name>view-prefix</param-name>
        <param-value>/</param-value>
    </context-param>
    <context-param>
        <param-name>view-suffix</param-name>
        <param-value>.html</param-value>
    </context-param>


</web-app>

aad.html

<html xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="utf-8">
   <link rel="stylesheet" href="css/add.css">
</head>
<body>
<div id="div_container">
   <div id="div_fruit_list">
      <p class="center f30">New inventory information 2</p>
      <!--<form action="add.do" method="post">-->
      <form action="add.do" method="post">
         <table id="tbl_fruit">
            <tr>
               <th class="w20">name:</th>
               <!-- <td><input type="text" name="fname" th:value="${fruit.fname}"/></td> -->
               <td><input type="text" name="fname" /></td>
            </tr>
            <tr>
               <th class="w20">Unit Price:</th>
               <td><input type="text" name="price" /></td>
            </tr>
            <tr>
               <th class="w20">stock:</th>
               <td><input type="text" name="fcount" /></td>
            </tr>
            <tr>
               <th class="w20">remarks:</th>
               <td><input type="text" name="remark" /></td>
            </tr>
            <tr>
               <th colspan="2">
                  <input type="submit" value="add to" />
               </th>
            </tr>
         </table>
      </form>
   </div>
</div>
</body>
</html>

edit.html

<html xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="utf-8">
   <link rel="stylesheet" href="css/edit.css">
</head>
<body>
<div id="div_container">
   <div id="div_fruit_list">
      <p class="center f30">Edit inventory information 3</p>
      <form th:action="@{/update.do}" method="post" th:object="${fruit}">
         <!-- Hidden field: the function is similar to a text box. Its value will be sent to the server as the form is sent, but the user cannot see it on the interface -->
         <input type="hidden" name="fid" th:value="*{fid}"/>
         <table id="tbl_fruit">
            <tr>
               <th class="w20">name:</th>
               <!-- <td><input type="text" name="fname" th:value="${fruit.fname}"/></td> -->
               <td><input type="text" name="fname" th:value="*{fname}"/></td>
            </tr>
            <tr>
               <th class="w20">Unit Price:</th>
               <td><input type="text" name="price" th:value="*{price}"/></td>
            </tr>
            <tr>
               <th class="w20">stock:</th>
               <td><input type="text" name="fcount" th:value="*{fcount}"/></td>
            </tr>
            <tr>
               <th class="w20">remarks:</th>
               <td><input type="text" name="remark" th:value="*{remark}"/></td>
            </tr>
            <tr>
               <th colspan="2">
                  <input type="submit" value="modify" />
               </th>
            </tr>
         </table>
      </form>
   </div>
</div>
</body>
</html>

index.html

<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <meta charset="utf-8">
      <link rel="stylesheet" href="css/index.css">
   </head>
   <body>
      <div id="div_container">
         <div id="div_fruit_list">
            <p class="center f30">Welcome to the background management system of fruit inventory</p>
            <table id="tbl_fruit">
               <tr>
                  <th class="w20">name</th>
                  <th class="w20">Unit Price</th>
                  <th class="w20">stock</th>
                  <th>operation</th>
               </tr>
               <tr th:if="${#lists.isEmpty(session.fruitList)}">
                  <td colspan="4">Sorry, the inventory is empty!</td>
               </tr>
               <tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}">
                  <td th:text="${fruit.fname}">Apple</td>
                  <td th:text="${fruit.price}">5</td>
                  <td th:text="${fruit.fcount}">20</td>
                  <td><img src="imgs/del.jpg" class="delImg"/></td>
               </tr>
            </table>
         </div>
      </div>
   </body>
</html>

review:

7. Thymeleaf - View template technology
    1) add to thymeleaf of jar package
    2) Create a new one Servlet class ViewBaseServlet
    3) stay web.xml Add configuration to file
       - Configure prefix view-prefix
       - Configuration suffix view-suffix
    4) Make our Servlet inherit ViewBaseServlet

    5) Get the physical view name according to the logical view name
    //The view name here is index
    //Then thymeleaf will map the logical view name to the physical view name
    //Logical view name: index
    //Physical view name: View prefix + logical view name + view suffix
    //So the real view name is: / index html
    super.processTemplate("index",request,response);
    6) use thymeleaf Label of
      th:if   ,  th:unless   , th:each   ,   th:text

Paging – session

FruitDAOImpl.java - increase the total number of query database data

package com.atguigu.fruit.dao.impl;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.basedao.BaseDAO;

import java.util.List;

public class FruitDAOImpl extends BaseDAO<Fruit> implements FruitDAO {
    @Override
    public List<Fruit> getFruitList(Integer pageNo) {
        return super.executeQuery("select * from t_fruit limit ? , 5" , (pageNo-1)*5);
    }

    @Override
    public Fruit getFruitByFid(Integer fid) {
        return super.load("select * from t_fruit where fid = ? " , fid);
    }

    @Override
    public void updateFruit(Fruit fruit) {
        String sql = "update t_fruit set fname = ? , price = ? , fcount = ? , remark = ? where fid = ? " ;
        super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark(),fruit.getFid());
    }

    @Override
    public void delFruit(Integer fid) {
        super.executeUpdate("delete from t_fruit where fid = ? " , fid) ;
    }

    @Override
    public void addFruit(Fruit fruit) {
        String sql = "insert into t_fruit values(0,?,?,?,?)";
        super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark());
    }

    @Override
    public int getFruitCount() {
        return ((Long)super.executeComplexQuery("select count(*) from t_fruit")[0]).intValue();
    }
}

// Line 39 reports an error ClassCastException: Java lang.Long cannot be cast to java. lang.Integer

FruitDAO.java

package com.atguigu.fruit.dao;

import com.atguigu.fruit.pojo.Fruit;

import java.util.List;

public interface FruitDAO {
    //Obtain the inventory list information on the specified page number, and 5 items are displayed on each page
    List<Fruit> getFruitList(Integer pageNo);

    //Obtain specific fruit inventory information according to fid
    Fruit getFruitByFid(Integer fid);

    //Modify the specified inventory record
    void updateFruit(Fruit fruit);

    //Delete the specified inventory record according to fid
    void delFruit(Integer fid);

    //Add new inventory record
    void addFruit(Fruit fruit);

    //Query the total number of inventory records
    int getFruitCount();
}

Index.java - increase the number of pages in the session

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;
import com.atguigu.myssm.util.StringUtil;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

//Servlet supports annotation registration from version 3.0
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
    @Override
    public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        Integer pageNo = 1 ;
        String pageNoStr = request.getParameter("pageNo");
        if(StringUtil.isNotEmpty(pageNoStr)){
            pageNo = Integer.parseInt(pageNoStr);
        }

        HttpSession session = request.getSession() ;
        session.setAttribute("pageNo",pageNo);

        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList(pageNo);

        session.setAttribute("fruitList",fruitList);

        //Total records
        int fruitCount = fruitDAO.getFruitCount();
        //PageCount 
        int pageCount = (fruitCount+5-1)/5 ;
        /*
        Total records total pages
        1               1
        5               1
        6               2
        10              2
        11              3
        fruitCount      (fruitCount+5-1)/5
         */
        session.setAttribute("pageCount",pageCount);

        //The view name here is index
        //Then thymeleaf will map the logical view name to the physical view name
        //Logical view name: index
        //Physical view name: View prefix + logical view name + view suffix
        //So the real view name is: / index html
        super.processTemplate("index",request,response);
    }
}

index.html – paging and page turning functions

<html xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="utf-8">
   <link rel="stylesheet" href="css/index.css">
   <script language="JavaScript" src="js/index.js"></script>
</head>
<body>
<div id="div_container">
   <div id="div_fruit_list">
      <p class="center f30">Welcome to the background management system of fruit inventory</p>
      <div style="border:0px solid red;width:60%;margin-left:20%;text-align:right;">
         <a th:href="@{/add.html}" style="border:0px solid blue;margin-bottom:4px;">Add new inventory record</a>
      </div>
      <table id="tbl_fruit">
         <tr>
            <th class="w20">Name 1</th>
            <th class="w20">Unit Price</th>
            <th class="w20">stock</th>
            <th>operation</th>
         </tr>
         <tr th:if="${#lists.isEmpty(session.fruitList)}">
            <td colspan="4">Sorry, the inventory is empty!</td>
         </tr>
         <tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}">
            <!-- <td><a th:text="${fruit.fname}" th:href="@{'/edit.do?fid='+${fruit.fid}}">Apple</a></td> -->
            <td><a th:text="${fruit.fname}" th:href="@{/edit.do(fid=${fruit.fid})}">Apple</a></td>
            <td th:text="${fruit.price}">5</td>
            <td th:text="${fruit.fcount}">20</td>
            <!-- <td><img src="imgs/del.jpg" class="delImg" th:οnclick="'delFruit('+${fruit.fid}+')'"/></td> -->
            <td><img src="imgs/del.jpg" class="delImg" th:onclick="|delFruit(${fruit.fid})|"/></td>
         </tr>
      </table>
      <div style="width:60%;margin-left:20%;border:0px solid red;padding-top:4px;" class="center">
         <input type="button" value="Home page 1" class="btn" th:onclick="|page(1)|" th:disabled="${session.pageNo==1}"/>
         <input type="button" value="previous page" class="btn" th:onclick="|page(${session.pageNo-1})|" th:disabled="${session.pageNo==1}"/>
         <input type="button" value="next page" class="btn" th:onclick="|page(${session.pageNo+1})|" th:disabled="${session.pageNo==session.pageCount}"/>
         <input type="button" value="Last page" class="btn" th:onclick="|page(${session.pageCount})|" th:disabled="${session.pageNo==session.pageCount}"/>
      </div>
   </div>
</div>
</body>
</html>

Keyword lookup – sql(like)

FruitDAOImpl.java

package com.atguigu.fruit.dao.impl;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.basedao.BaseDAO;

import java.util.List;

public class FruitDAOImpl extends BaseDAO<Fruit> implements FruitDAO {
    @Override
    public List<Fruit> getFruitList(String keyword , Integer pageNo) {
        return super.executeQuery("select * from t_fruit where fname like ? or remark like ? limit ? , 5" ,"%"+keyword+"%","%"+keyword+"%", (pageNo-1)*5);
    }

    @Override
    public Fruit getFruitByFid(Integer fid) {
        return super.load("select * from t_fruit where fid = ? " , fid);
    }

    @Override
    public void updateFruit(Fruit fruit) {
        String sql = "update t_fruit set fname = ? , price = ? , fcount = ? , remark = ? where fid = ? " ;
        super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark(),fruit.getFid());
    }

    @Override
    public void delFruit(Integer fid) {
        super.executeUpdate("delete from t_fruit where fid = ? " , fid) ;
    }

    @Override
    public void addFruit(Fruit fruit) {
        String sql = "insert into t_fruit values(0,?,?,?,?)";
        super.executeUpdate(sql,fruit.getFname(),fruit.getPrice(),fruit.getFcount(),fruit.getRemark());
    }

    @Override
    public int getFruitCount(String keyword ) {
        return ((Long)super.executeComplexQuery("select count(*) from t_fruit where fname like ? or remark like ?" , "%"+keyword+"%","%"+keyword+"%")[0]).intValue();
    }
}

// Line 39 reports an error ClassCastException: Java lang.Long cannot be cast to java. lang.Integer

IndexServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;
import com.atguigu.myssm.util.StringUtil;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

//Servlet supports annotation registration from version 3.0
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        HttpSession session = request.getSession() ;
        Integer pageNo = 1 ;

        String oper = request.getParameter("oper");
        //If oper= Null indicates that it is clicked through the query button of the form
        //If oper is empty, it means that it is not clicked through the query button of the form

        String keyword = null ;
        if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
            //Description is to click the form to query the sent request
            //At this point, pageNo should be restored to 1, and the keyword should be obtained from the request parameters
            pageNo = 1 ;
            keyword = request.getParameter("keyword");
            if(StringUtil.isEmpty(keyword)){
                keyword = "" ;
            }
            session.setAttribute("keyword",keyword);
        }else{
            //Note that this is not a request sent by clicking the form query (for example, click the previous page and the next page below or directly enter the website address in the address bar)
            //At this point, the keyword should be obtained from the session scope
            String pageNoStr = request.getParameter("pageNo");
            if(StringUtil.isNotEmpty(pageNoStr)){
                pageNo = Integer.parseInt(pageNoStr);
            }
            Object keywordObj = session.getAttribute("keyword");
            if(keywordObj!=null){
                keyword = (String)keywordObj ;
            }else{
                keyword = "" ;
            }
        }

        session.setAttribute("pageNo",pageNo);

        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList(keyword , pageNo);

        session.setAttribute("fruitList",fruitList);

        //Total records
        int fruitCount = fruitDAO.getFruitCount(keyword);
        //PageCount 
        int pageCount = (fruitCount+5-1)/5 ;
        /*
        Total records total pages
        1               1
        5               1
        6               2
        10              2
        11              3
        fruitCount      (fruitCount+5-1)/5
         */
        session.setAttribute("pageCount",pageCount);

        //The view name here is index
        //Then thymeleaf will map the logical view name to the physical view name
        //Logical view name: index
        //Physical view name: View prefix + logical view name + view suffix
        //So the real view name is: / index html
        super.processTemplate("index",request,response);
    }
}

mvc–FruitServlet

Original client request process

Current request process

FruitServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;
import com.atguigu.myssm.util.StringUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

@WebServlet("/fruit.do")
public class FruitServlet extends ViewBaseServlet {
    private FruitDAO fruitDAO = new FruitDAOImpl();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. Set code
        request.setCharacterEncoding("utf-8");

        //2. Get parameters
        String fidStr = request.getParameter("fid");
        Integer fid = Integer.parseInt(fidStr);
        String fname = request.getParameter("fname");
        String priceStr = request.getParameter("price");
        int price = Integer.parseInt(priceStr);
        String fcountStr = request.getParameter("fcount");
        Integer fcount = Integer.parseInt(fcountStr);
        String remark = request.getParameter("remark");

        //3. Execute update
        fruitDAO.updateFruit(new Fruit(fid,fname, price ,fcount ,remark ));

        //4. Resource jump
        //super.processTemplate("index",request,response);
        //request.getRequestDispatcher("index.html").forward(request,response);
        //Redirection is required here. The purpose is to re send a request to the IndexServlet, re obtain the furitList, and then overwrite it in the session, so that the index The data in the session displayed on the HTML page is the latest
        response.sendRedirect("fruit.do");
    }

    private void edit(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            Fruit fruit = fruitDAO.getFruitByFid(fid);
            request.setAttribute("fruit",fruit);
            super.processTemplate("edit",request,response);
        }
    }

    private void del(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            fruitDAO.delFruit(fid);

            //super.processTemplate("index",request,response);
            response.sendRedirect("fruit.do");
        }
    }

    private void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String fname = request.getParameter("fname");
        Integer price = Integer.parseInt(request.getParameter("price")) ;
        Integer fcount = Integer.parseInt(request.getParameter("fcount"));
        String remark = request.getParameter("remark");

        Fruit fruit = new Fruit(0,fname , price , fcount , remark ) ;

        fruitDAO.addFruit(fruit);

        response.sendRedirect("fruit.do");

    }

    private void index(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        HttpSession session = request.getSession() ;

        // Set current page, default 1
        Integer pageNo = 1 ;

        String oper = request.getParameter("oper");

        //If oper= Null indicates that it is clicked through the query button of the form
        //If oper is empty, it means that it is not clicked through the query button of the form
        String keyword = null ;
        if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
            //Description is to click the form to query the sent request
            //At this point, pageNo should be restored to 1, and the keyword should be obtained from the request parameters
            pageNo = 1 ;
            keyword = request.getParameter("keyword");
            //If the keyword is null, it needs to be set to the empty string '', otherwise it will be spliced into% null% during query. We expect%% to be used
            if(StringUtil.isEmpty(keyword)){
                keyword = "" ;
            }
            //Save (overwrite) the keyword into the session
            session.setAttribute("keyword",keyword);
        }else{
            //Note that this is not a request sent by clicking the form query (for example, click the previous page and the next page below or directly enter the website address in the address bar)
            //At this point, the keyword should be obtained from the session scope
            String pageNoStr = request.getParameter("pageNo");
            if(StringUtil.isNotEmpty(pageNoStr)){
                pageNo = Integer.parseInt(pageNoStr);   //If pageNo is read from the request, the type is converted. Otherwise, pageNo defaults to 1
            }
            //If the query button is not clicked, the query is based on the existing keyword saved in the session
            Object keywordObj = session.getAttribute("keyword");
            if(keywordObj!=null){
                keyword = (String)keywordObj ;
            }else{
                keyword = "" ;
            }
        }

        // Re update the value of the current page
        session.setAttribute("pageNo",pageNo);

        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList(keyword , pageNo);
        session.setAttribute("fruitList",fruitList);

        //Total records
        int fruitCount = fruitDAO.getFruitCount(keyword);
        //PageCount 
        int pageCount = (fruitCount+5-1)/5 ;
        /*
        Total records total pages
        1               1
        5               1
        6               2
        10              2
        11              3
        fruitCount      (fruitCount+5-1)/5
         */
        session.setAttribute("pageCount",pageCount);

        //The view name here is index
        //Then thymeleaf will map the logical view name to the physical view name
        //Logical view name: index
        //Physical view name: View prefix + logical view name + view suffix
        //So the real view name is: / index html
        super.processTemplate("index",request,response);
    }
}

mvc – integrated FruitServlet approach – reflection

FruitServlet.java

package com.atguigu.fruit.servlets;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;
import com.atguigu.myssm.util.StringUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

@WebServlet("/fruit.do")
public class FruitServlet extends ViewBaseServlet {
    private FruitDAO fruitDAO = new FruitDAOImpl();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //Set code
        request.setCharacterEncoding("UTF-8");

        String operate = request.getParameter("operate");
        if(StringUtil.isEmpty(operate)){
            operate = "index" ;
        }

        switch(operate){
            case "index":
                index(request,response);
                break;
            case "add":
                add(request,response);
                break;
            case "del":
                del(request,response);
                break;
            case "edit":
                edit(request,response);
                break;
            case "update":
                update(request,response);
                break;
            default:
                throw new RuntimeException("operate Illegal value!");
        }
    }

    private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. Set code
        request.setCharacterEncoding("utf-8");

        //2. Get parameters
        String fidStr = request.getParameter("fid");
        Integer fid = Integer.parseInt(fidStr);
        String fname = request.getParameter("fname");
        String priceStr = request.getParameter("price");
        int price = Integer.parseInt(priceStr);
        String fcountStr = request.getParameter("fcount");
        Integer fcount = Integer.parseInt(fcountStr);
        String remark = request.getParameter("remark");

        //3. Execute update
        fruitDAO.updateFruit(new Fruit(fid,fname, price ,fcount ,remark ));

        //4. Resource jump
        //super.processTemplate("index",request,response);
        //request.getRequestDispatcher("index.html").forward(request,response);
        //Redirection is required here. The purpose is to re send a request to the IndexServlet, re obtain the furitList, and then overwrite it in the session, so that the index The data in the session displayed on the HTML page is the latest
        response.sendRedirect("fruit.do");
    }

    private void edit(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            Fruit fruit = fruitDAO.getFruitByFid(fid);
            request.setAttribute("fruit",fruit);
            super.processTemplate("edit",request,response);
        }
    }

    private void del(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            fruitDAO.delFruit(fid);

            //super.processTemplate("index",request,response);
            response.sendRedirect("fruit.do");
        }
    }

    private void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String fname = request.getParameter("fname");
        Integer price = Integer.parseInt(request.getParameter("price")) ;
        Integer fcount = Integer.parseInt(request.getParameter("fcount"));
        String remark = request.getParameter("remark");

        Fruit fruit = new Fruit(0,fname , price , fcount , remark ) ;

        fruitDAO.addFruit(fruit);

        response.sendRedirect("fruit.do");

    }

    private void index(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        HttpSession session = request.getSession() ;

        // Set current page, default 1
        Integer pageNo = 1 ;

        String oper = request.getParameter("oper");

        //If oper= Null indicates that it is clicked through the query button of the form
        //If oper is empty, it means that it is not clicked through the query button of the form
        String keyword = null ;
        if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
            //Description is to click the form to query the sent request
            //At this point, pageNo should be restored to 1, and the keyword should be obtained from the request parameters
            pageNo = 1 ;
            keyword = request.getParameter("keyword");
            //If the keyword is null, it needs to be set to the empty string '', otherwise it will be spliced into% null% during query. We expect%% to be used
            if(StringUtil.isEmpty(keyword)){
                keyword = "" ;
            }
            //Save (overwrite) the keyword into the session
            session.setAttribute("keyword",keyword);
        }else{
            //Note that this is not a request sent by clicking the form query (for example, click the previous page and the next page below or directly enter the website address in the address bar)
            //At this point, the keyword should be obtained from the session scope
            String pageNoStr = request.getParameter("pageNo");
            if(StringUtil.isNotEmpty(pageNoStr)){
                pageNo = Integer.parseInt(pageNoStr);   //If pageNo is read from the request, the type is converted. Otherwise, pageNo defaults to 1
            }
            //If the query button is not clicked, the query is based on the existing keyword saved in the session
            Object keywordObj = session.getAttribute("keyword");
            if(keywordObj!=null){
                keyword = (String)keywordObj ;
            }else{
                keyword = "" ;
            }
        }

        // Re update the value of the current page
        session.setAttribute("pageNo",pageNo);

        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList(keyword , pageNo);
        session.setAttribute("fruitList",fruitList);

        //Total records
        int fruitCount = fruitDAO.getFruitCount(keyword);
        //PageCount 
        int pageCount = (fruitCount+5-1)/5 ;
        /*
        Total records total pages
        1               1
        5               1
        6               2
        10              2
        11              3
        fruitCount      (fruitCount+5-1)/5
         */
        session.setAttribute("pageCount",pageCount);

        //The view name here is index
        //Then thymeleaf will map the logical view name to the physical view name
        //Logical view name: index
        //Physical view name: View prefix + logical view name + view suffix
        //So the real view name is: / index html
        super.processTemplate("index",request,response);
    }
}

BaseDAO.java

package com.atguigu.myssm.basedao;

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 ;

    //Class object of T
    private Class entityClass ;

    public BaseDAO(){
        //getClass() gets the Class object. At present, we execute new FruitDAOImpl() and create an instance of FruitDAOImpl
        //Then the child class constructor will first call the parameterless constructor of the parent class (BaseDAO)
        //Therefore, getClass() here will be executed, but getClass gets the Class of FruitDAOImpl
        //So getGenericSuperclass() gets the Class of BaseDAO
        Type genericType = getClass().getGenericSuperclass();
        //ParameterizedType parameterized type
        Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
        //Get the real type of T in < T >
        Type actualType = actualTypeArguments[0];
        try {
            entityClass = Class.forName(actualType.getTypeName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected Connection getConn(){
        try {
            //1. Load drive
            Class.forName(DRIVER);
            //2. Obtain the connection object through the driver manager
            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();
        }
    }

    //Set parameters for preprocessing command objects
    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]);
            }
        }
    }

    //Execute update and return the number of affected rows
    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() ;

            if(insertFlag){
                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;
    }

    //Assign a propertyValue value to the property attribute of obj object through reflection technology
    private void setValue(Object obj ,  String property , Object propertyValue){
        Class clazz = obj.getClass();
        try {
            //Get the property name corresponding to the string property, such as "fid" to find the fid property in the obj object
            Field field = clazz.getDeclaredField(property);
            if(field!=null){
                field.setAccessible(true);
                field.set(obj,propertyValue);
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    //Execute complex queries and return, for example, statistical results
    protected Object[] executeComplexQuery(String sql , Object... params){
        try {
            conn = getConn() ;
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //The metadata of the result set can be obtained through rs
            //Metadata: data that describes the result set data. In short, it is the columns and types of the result set

            ResultSetMetaData rsmd = rs.getMetaData();
            //Gets the number of columns in the result set
            int columnCount = rsmd.getColumnCount();
            Object[] columnValueArr = new Object[columnCount];
            //6. Parsing rs
            if(rs.next()){
                for(int i = 0 ; i<columnCount;i++){
                    Object columnValue = rs.getObject(i+1);     //33 Apple 5
                    columnValueArr[i]=columnValue;
                }
                return columnValueArr ;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(rs,psmt,conn);
        }
        return null ;
    }

    //Execute the query and return a single entity object
    protected T load(String sql , Object... params){
        try {
            conn = getConn() ;
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //The metadata of the result set can be obtained through rs
            //Metadata: data that describes the result set data. In short, it is the columns and types of the result set

            ResultSetMetaData rsmd = rs.getMetaData();
            //Gets the number of columns in the result set
            int columnCount = rsmd.getColumnCount();
            //6. Parsing 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 Apple 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 ;
    }


    //Execute query and return 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();

            //The metadata of the result set can be obtained through rs
            //Metadata: data that describes the result set data. In short, it is the columns and types of the result set

            ResultSetMetaData rsmd = rs.getMetaData();
            //Gets the number of columns in the result set
            int columnCount = rsmd.getColumnCount();
            //6. Parsing 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 Apple 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 ;
    }
}

mvc–dispatherServlet

thinking

Project structure

FruitController.java

package com.atguigu.fruit.controllers;

import com.atguigu.fruit.dao.FruitDAO;
import com.atguigu.fruit.dao.impl.FruitDAOImpl;
import com.atguigu.fruit.pojo.Fruit;
import com.atguigu.myssm.myspringmvc.ViewBaseServlet;
import com.atguigu.myssm.util.StringUtil;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

public class FruitController extends ViewBaseServlet {

    //Previously, FruitServlet was a Sevlet component, so the init method must be called
    //In the previous init method, there will be a sentence: super init();

    private ServletContext servletContext ;

    public void setServletContext(ServletContext servletContext) throws ServletException {
        this.servletContext = servletContext;
        super.init(servletContext);
    }

    private FruitDAO fruitDAO = new FruitDAOImpl();

    private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. Set code
        request.setCharacterEncoding("utf-8");

        //2. Get parameters
        String fidStr = request.getParameter("fid");
        Integer fid = Integer.parseInt(fidStr);
        String fname = request.getParameter("fname");
        String priceStr = request.getParameter("price");
        int price = Integer.parseInt(priceStr);
        String fcountStr = request.getParameter("fcount");
        Integer fcount = Integer.parseInt(fcountStr);
        String remark = request.getParameter("remark");

        //3. Execute update
        fruitDAO.updateFruit(new Fruit(fid,fname, price ,fcount ,remark ));

        //4. Resource jump
        //super.processTemplate("index",request,response);
        //request.getRequestDispatcher("index.html").forward(request,response);
        //Redirection is required here. The purpose is to re send a request to the IndexServlet, re obtain the furitList, and then overwrite it in the session, so that the index The data in the session displayed on the HTML page is the latest
        response.sendRedirect("fruit.do");
    }

    private void edit(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            Fruit fruit = fruitDAO.getFruitByFid(fid);
            request.setAttribute("fruit",fruit);
            super.processTemplate("edit",request,response);
        }
    }

    private void del(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        String fidStr = request.getParameter("fid");
        if(StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            fruitDAO.delFruit(fid);

            //super.processTemplate("index",request,response);
            response.sendRedirect("fruit.do");
        }
    }

    private void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        String fname = request.getParameter("fname");
        Integer price = Integer.parseInt(request.getParameter("price")) ;
        Integer fcount = Integer.parseInt(request.getParameter("fcount"));
        String remark = request.getParameter("remark");

        Fruit fruit = new Fruit(0,fname , price , fcount , remark ) ;

        fruitDAO.addFruit(fruit);

        response.sendRedirect("fruit.do");

    }

    private void index(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        HttpSession session = request.getSession() ;

        // Set current page, default 1
        Integer pageNo = 1 ;

        String oper = request.getParameter("oper");

        //If oper= Null indicates that it is clicked through the query button of the form
        //If oper is empty, it means that it is not clicked through the query button of the form
        String keyword = null ;
        if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
            //Description is to click the form to query the sent request
            //At this point, pageNo should be restored to 1, and the keyword should be obtained from the request parameters
            pageNo = 1 ;
            keyword = request.getParameter("keyword");
            //If the keyword is null, it needs to be set to the empty string '', otherwise it will be spliced into% null% during query. We expect%% to be used
            if(StringUtil.isEmpty(keyword)){
                keyword = "" ;
            }
            //Save (overwrite) the keyword into the session
            session.setAttribute("keyword",keyword);
        }else{
            //Note that this is not a request sent by clicking the form query (for example, click the previous page and the next page below or directly enter the website address in the address bar)
            //At this point, the keyword should be obtained from the session scope
            String pageNoStr = request.getParameter("pageNo");
            if(StringUtil.isNotEmpty(pageNoStr)){
                pageNo = Integer.parseInt(pageNoStr);   //If pageNo is read from the request, the type is converted. Otherwise, pageNo defaults to 1
            }
            //If the query button is not clicked, the query is based on the existing keyword saved in the session
            Object keywordObj = session.getAttribute("keyword");
            if(keywordObj!=null){
                keyword = (String)keywordObj ;
            }else{
                keyword = "" ;
            }
        }

        // Re update the value of the current page
        session.setAttribute("pageNo",pageNo);

        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList(keyword , pageNo);
        session.setAttribute("fruitList",fruitList);

        //Total records
        int fruitCount = fruitDAO.getFruitCount(keyword);
        //PageCount 
        int pageCount = (fruitCount+5-1)/5 ;
        /*
        Total records total pages
        1               1
        5               1
        6               2
        10              2
        11              3
        fruitCount      (fruitCount+5-1)/5
         */
        session.setAttribute("pageCount",pageCount);

        //The view name here is index
        //Then thymeleaf will map the logical view name to the physical view name
        //Logical view name: index
        //Physical view name: View prefix + logical view name + view suffix
        //So the real view name is: / index html
        super.processTemplate("index",request,response);
    }
}

DisoatherServelt.java

package com.atguigu.myssm.myspringmvc;

import com.atguigu.myssm.util.StringUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {

    private Map<String,Object> beanMap = new HashMap<>();

    public DispatcherServlet(){
    }

    public void init(){
        try {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
            //1. Create DocumentBuilderFactory
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            //2. Create DocumentBuilder object
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder() ;
            //3. Create Document object
            Document document = documentBuilder.parse(inputStream);

            //4. Get all bean nodes
            NodeList beanNodeList = document.getElementsByTagName("bean");
            for(int i = 0 ; i<beanNodeList.getLength() ; i++){
                Node beanNode = beanNodeList.item(i);
                if(beanNode.getNodeType() == Node.ELEMENT_NODE){
                    Element beanElement = (Element)beanNode ;
                    String beanId =  beanElement.getAttribute("id");
                    String className = beanElement.getAttribute("class");
                    Class controllerBeanClass = Class.forName(className);
                    Object beanObj = controllerBeanClass.newInstance() ;
                    Method setServletContextMethod = controllerBeanClass.getDeclaredMethod("setServletContext",ServletContext.class);
                    setServletContextMethod.invoke(beanObj , this.getServletContext());

                    beanMap.put(beanId , beanObj) ;
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //Set code
        request.setCharacterEncoding("UTF-8");
        //Suppose the url is: http://localhost:8080/pro15/hello.do
        //Then servletPath is: / Hello do
        // My idea is:
        // Step 1: / Hello Do - > hello or / fruit do  -> fruit
        // Step 2: Hello - > hellocontroller or fruit - > fruitcontroller
        String servletPath = request.getServletPath();
        servletPath = servletPath.substring(1);
        int lastDotIndex = servletPath.lastIndexOf(".do") ;
        servletPath = servletPath.substring(0,lastDotIndex);

        Object controllerBeanObj = beanMap.get(servletPath);

        String operate = request.getParameter("operate");
        if(StringUtil.isEmpty(operate)){
            operate = "index" ;
        }

        try {
            Method method = controllerBeanObj.getClass().getDeclaredMethod(operate,HttpServletRequest.class,HttpServletResponse.class);
            if(method!=null){
                method.setAccessible(true);
                method.invoke(controllerBeanObj,request,response);
            }else{
                throw new RuntimeException("operate Illegal value!");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

applicationContext.xml

<?xml version="1.0" encoding="utf-8"?>

<beans>
    <!-- this bean The function of the label is the future servletpath The names referred to in correspond to fruit,Then FruitController This class handles -->
    <bean id="fruit" class="com.atguigu.fruit.controllers.FruitController"/>
</beans>

<!--
1.concept
HTML : Hypertext markup language
XML : Extensible markup language
HTML yes XML A subset of

2.XML It consists of three parts:
1) XML Declaration, and this line of code must be XML First line of file
2) DTD Document type definition
3) XML text
 -->

Keywords: Java Javascript html css

Added by trufla on Tue, 15 Feb 2022 09:38:39 +0200