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<10 10>5 5≤10 10≥5 Registered trademark ® Copyright symbol © <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 < Greater than or equal to sign ≥ copyright © 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, ,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 , , 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.
- JS is a script language running on the client side (browser side), and its syntax style is similar to that of java
- JS is a weakly typed language var str = 99;
- JS function hello(var num) {}
- 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:
- New project - new module
- Add web in module
- Create artifact - deploy package
- 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. - 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) - 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.
- 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.
- 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 -->