dom解析器
1.DocumentBuilderFactory–解析器工厂(抽象类 javax.xml.parsers.DocumentBuilderFactory)
newInstance ( ) 获取 DocumentBuilderFactory 的新实例。
newDocumentBuilder ( ) 使用当前配置的参数创建一个新的 DocumentBuilder 实例。
2.DocumentBuilder–解析器(抽象类 javax.xml.parsers.DocumentBuilder)
parse ( String uri)
将给定 URI 的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。( url是相对路径-- - 项目)
- Document ( 接口,父接口Node org. w3c. dom. Document)
- Node ( 接口 org. w3c. dom. Node )
3.Document(接口,父接口Node org.w3c.dom.Document)
getElementsByTagName ( String tagname)
返回文档中所有指定的标签名节点( NodeList )
getElementById ( String elementId)
返回具有带给定值的 ID 属性的 Element 。
createElement ( String tagName)
创建指定的节点(标签)。
createTextNode ( String data)
创建给定指定字符串的 Text 节点。
4.NodeList(接口)
jdk文档介绍:NodeList 接口提供对节点的有序集合的抽象,没有定义或约束如何实现此集合。DOM 中的 NodeList 对象是活动的
getLength ( ) 列表中的节点数。
item ( int index) 返回集合中的第 index 个项(Node 类型)。
5.Node(接口 org.w3c.dom.Node )常用方法
- 获取
getFirstChild ( ) 此节点的第一个子节点。
getLastChild ( ) 此节点的最后一个节点。
getParentNode ( ) 此节点的父节点。
getChildNodes ( ) 包含此节点的所有子节点的 NodeList 。
getNextSibling ( ) 直接在此节点之后的节点。
getNodeValue ( ) 此节点的值,取决于其类型;
getPreviousSibling ( ) 直接在此节点之前的节点。
getTextContent ( ) 此属性返回此节点及其后代的文本内容。
- 添加
appendChild ( Node newChild)
将节点 newChild 添加到此节点的子节点列表的末尾。
insertBefore ( Node newChild, Node refChild)
在现有子节点 refChild 之前插入节点 newChild。
- 删除
removeChild ( Node oldChild)
从子节点列表中移除 oldChild 所指示的子节点,并将其返回。
- 修改
replaceChild ( Node newChild, Node oldChild)
将子节点列表中的子节点 oldChild 替换为 newChild,并返回 oldChild 节点。
setNodeValue ( String nodeValue) 此节点的值,取决于其类型;
setTextContent ( String textContent) 此属性返回此节点及其后代的文本内容。
- 判断
isEqualNode ( Node arg) 测试两个节点是否相等
初步学习MVC(提取视图资源处理通用代码,在核心控制器中统一获取参数以及视图处理)
最初的做法是: 一个请求对应一个Servlet,这样存在的问题是servlet太多了 把一些列的请求都对应一个Servlet, IndexServlet/AddServlet/EditServlet/DelServlet/UpdateServlet -> 合并成FruitServlet 通过一个operate的值来决定调用FruitServlet中的哪一个方法 使用的是switch-case 在上一个版本中,Servlet中充斥着大量的switch-case,试想一下,随着我们的项目的业务规模扩大,那么会有很多的Servlet,也就意味着会有很多的switch-case,这是一种代码冗余 因此,我们在servlet中使用了反射技术,我们规定operate的值和方法名一致,那么接收到operate的值是什么就表明我们需要调用对应的方法进行响应,如果找不到对应的方法,则抛异常 在上一个版本中我们使用了反射技术,但是其实还是存在一定的问题:每一个servlet中都有类似的反射技术的代码。因此继续抽取,设计了中央控制器类:DispatcherServlet DispatcherServlet这个类的工作分为两大部分: 1.根据url定位到能够处理这个请求的controller组件: 1)从url中提取servletPath : /fruit.do -> fruit 2)根据fruit找到对应的组件:FruitController , 这个对应的依据我们存储在applicationContext.xml中 <bean id=“fruit” class="com.atguigu.fruit.controllers.FruitController/> 通过DOM技术我们去解析XML文件,在中央控制器中形成一个beanMap容器,用来存放所有的Controller组件 3)根据获取到的operate的值定位到我们FruitController中需要调用的方法 2.调用Controller组件中的方法:
获取参数 获取即将要调用的方法的参数签名信息: Parameter[] parameters = method.getParameters(); 通过parameter.getName()获取参数的名称; 准备了Object[] parameterValues 这个数组用来存放对应参数的参数值 另外,我们需要考虑参数的类型问题,需要做类型转化的工作。通过parameter.getType()获取参数的类型 执行方法 Object returnObj = method.invoke(controllerBean , parameterValues); 视图处理 String returnStr = (String)returnObj; if(returnStr.startWith(“redirect:”)){ … }else if…
最终版本(代码)
FruitController
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. util. StringUtil ;
import javax. servlet. ServletException ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpSession ;
import java. io. IOException ;
import java. util. List ;
public class FruitController {
private FruitDAO fruitDAO = new FruitDAOImpl ( ) ;
private String update ( Integer fid , String fname , Integer price , Integer fcount , String remark ) {
fruitDAO. updateFruit ( new Fruit ( fid, fname, price , fcount , remark ) ) ;
return "redirect:fruit.do" ;
}
private String edit ( Integer fid , HttpServletRequest request) {
if ( fid!= null ) {
Fruit fruit = fruitDAO. getFruitByFid ( fid) ;
request. setAttribute ( "fruit" , fruit) ;
return "edit" ;
}
return "error" ;
}
private String del ( Integer fid ) {
if ( fid!= null ) {
fruitDAO. delFruit ( fid) ;
return "redirect:fruit.do" ;
}
return "error" ;
}
private String add ( String fname , Integer price , Integer fcount , String remark ) {
Fruit fruit = new Fruit ( 0 , fname , price , fcount , remark ) ;
fruitDAO. addFruit ( fruit) ;
return "redirect:fruit.do" ;
}
private String index ( String oper , String keyword , Integer pageNo , HttpServletRequest request ) {
HttpSession session = request. getSession ( ) ;
if ( pageNo== null ) {
pageNo = 1 ;
}
if ( StringUtil . isNotEmpty ( oper) && "search" . equals ( oper) ) {
pageNo = 1 ;
if ( StringUtil . isEmpty ( keyword) ) {
keyword = "" ;
}
session. setAttribute ( "keyword" , keyword) ;
} else {
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) ;
int fruitCount = fruitDAO. getFruitCount ( keyword) ;
int pageCount = ( fruitCount+ 5 - 1 ) / 5 ;
session. setAttribute ( "pageCount" , pageCount) ;
return "index" ;
}
}
FruitDAOImpl
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 ( ) ;
}
}
FruitDAO
package com. atguigu. fruit. dao ;
import com. atguigu. fruit. pojo. Fruit ;
import java. util. List ;
public interface FruitDAO {
List < Fruit > getFruitList ( String keyword , Integer pageNo) ;
Fruit getFruitByFid ( Integer fid) ;
void updateFruit ( Fruit fruit) ;
void delFruit ( Integer fid) ;
void addFruit ( Fruit fruit) ;
int getFruitCount ( String keyword) ;
}
Fruit
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 ;
}
}
BaseDAO
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 ;
private Class entityClass ;
public BaseDAO ( ) {
Type genericType = getClass ( ) . getGenericSuperclass ( ) ;
Type [ ] actualTypeArguments = ( ( ParameterizedType ) genericType) . getActualTypeArguments ( ) ;
Type actualType = actualTypeArguments[ 0 ] ;
try {
entityClass = Class . forName ( actualType. getTypeName ( ) ) ;
} catch ( ClassNotFoundException e) {
e. printStackTrace ( ) ;
}
}
protected Connection getConn ( ) {
try {
Class . forName ( DRIVER ) ;
return DriverManager . getConnection ( URL , USER , PWD ) ;
} catch ( ClassNotFoundException | SQLException e) {
e. printStackTrace ( ) ;
}
return null ;
}
protected void close ( ResultSet rs , PreparedStatement psmt , Connection conn) {
try {
if ( rs != null ) {
rs. close ( ) ;
}
if ( psmt!= null ) {
psmt. close ( ) ;
}
if ( conn!= null && ! conn. isClosed ( ) ) {
conn. close ( ) ;
}
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
}
private void setParams ( PreparedStatement psmt , Object . . . params) throws SQLException {
if ( params!= null && params. length> 0 ) {
for ( int i = 0 ; i < params. length; i++ ) {
psmt. setObject ( i+ 1 , params[ i] ) ;
}
}
}
protected int executeUpdate ( String sql , Object . . . params) {
boolean insertFlag = false ;
insertFlag = sql. trim ( ) . toUpperCase ( ) . startsWith ( "INSERT" ) ;
try {
conn = getConn ( ) ;
if ( insertFlag) {
psmt = conn. prepareStatement ( sql, Statement . RETURN_GENERATED_KEYS ) ;
} else {
psmt = conn. prepareStatement ( sql) ;
}
setParams ( psmt, params) ;
int count = psmt. executeUpdate ( ) ;
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 ;
}
private void setValue ( Object obj , String property , Object propertyValue) {
Class clazz = obj. getClass ( ) ;
try {
Field field = clazz. getDeclaredField ( property) ;
if ( field!= null ) {
field. setAccessible ( true ) ;
field. set ( obj, propertyValue) ;
}
} catch ( NoSuchFieldException | IllegalAccessException e) {
e. printStackTrace ( ) ;
}
}
protected Object [ ] executeComplexQuery ( String sql , Object . . . params) {
try {
conn = getConn ( ) ;
psmt = conn. prepareStatement ( sql) ;
setParams ( psmt, params) ;
rs = psmt. executeQuery ( ) ;
ResultSetMetaData rsmd = rs. getMetaData ( ) ;
int columnCount = rsmd. getColumnCount ( ) ;
Object [ ] columnValueArr = new Object [ columnCount] ;
if ( rs. next ( ) ) {
for ( int i = 0 ; i< columnCount; i++ ) {
Object columnValue = rs. getObject ( i+ 1 ) ;
columnValueArr[ i] = columnValue;
}
return columnValueArr ;
}
} catch ( SQLException e) {
e. printStackTrace ( ) ;
} finally {
close ( rs, psmt, conn) ;
}
return null ;
}
protected T load ( String sql , Object . . . params) {
try {
conn = getConn ( ) ;
psmt = conn. prepareStatement ( sql) ;
setParams ( psmt, params) ;
rs = psmt. executeQuery ( ) ;
ResultSetMetaData rsmd = rs. getMetaData ( ) ;
int columnCount = rsmd. getColumnCount ( ) ;
if ( rs. next ( ) ) {
T entity = ( T ) entityClass. newInstance ( ) ;
for ( int i = 0 ; i< columnCount; i++ ) {
String columnName = rsmd. getColumnName ( i+ 1 ) ;
Object columnValue = rs. getObject ( i+ 1 ) ;
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 ;
}
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 ( ) ;
ResultSetMetaData rsmd = rs. getMetaData ( ) ;
int columnCount = rsmd. getColumnCount ( ) ;
while ( rs. next ( ) ) {
T entity = ( T ) entityClass. newInstance ( ) ;
for ( int i = 0 ; i< columnCount; i++ ) {
String columnName = rsmd. getColumnName ( i+ 1 ) ;
Object columnValue = rs. getObject ( i+ 1 ) ;
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 ;
}
}
DispatcherServlet
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. lang. reflect. Parameter ;
import java. util. HashMap ;
import java. util. Map ;
@WebServlet ( "*.do" )
public class DispatcherServlet extends ViewBaseServlet {
private Map < String , Object > beanMap = new HashMap < > ( ) ;
public DispatcherServlet ( ) {
}
public void init ( ) throws ServletException {
super . init ( ) ;
try {
InputStream inputStream = getClass ( ) . getClassLoader ( ) . getResourceAsStream ( "applicationContext.xml" ) ;
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory . newInstance ( ) ;
DocumentBuilder documentBuilder = documentBuilderFactory. newDocumentBuilder ( ) ;
Document document = documentBuilder. parse ( inputStream) ;
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 ( ) ;
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 ( ) ;
}
}
@Override
protected void service ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
request. setCharacterEncoding ( "UTF-8" ) ;
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 [ ] methods = controllerBeanObj. getClass ( ) . getDeclaredMethods ( ) ;
for ( Method method : methods) {
if ( operate. equals ( method. getName ( ) ) ) {
Parameter [ ] parameters = method. getParameters ( ) ;
Object [ ] parameterValues = new Object [ parameters. length] ;
for ( int i = 0 ; i < parameters. length; i++ ) {
Parameter parameter = parameters[ i] ;
String parameterName = parameter. getName ( ) ;
if ( "request" . equals ( parameterName) ) {
parameterValues[ i] = request ;
} else if ( "response" . equals ( parameterName) ) {
parameterValues[ i] = response ;
} else if ( "session" . equals ( parameterName) ) {
parameterValues[ i] = request. getSession ( ) ;
} else {
String parameterValue = request. getParameter ( parameterName) ;
String typeName = parameter. getType ( ) . getName ( ) ;
Object parameterObj = parameterValue ;
if ( parameterObj!= null ) {
if ( "java.lang.Integer" . equals ( typeName) ) {
parameterObj = Integer . parseInt ( parameterValue) ;
}
}
parameterValues[ i] = parameterObj ;
}
}
method. setAccessible ( true ) ;
Object returnObj = method. invoke ( controllerBeanObj, parameterValues) ;
String methodReturnStr = ( String ) returnObj ;
if ( methodReturnStr. startsWith ( "redirect:" ) ) {
String redirectStr = methodReturnStr. substring ( "redirect:" . length ( ) ) ;
response. sendRedirect ( redirectStr) ;
} else {
super . processTemplate ( methodReturnStr, request, response) ;
}
}
}
} catch ( IllegalAccessException e) {
e. printStackTrace ( ) ;
} catch ( InvocationTargetException e) {
e. printStackTrace ( ) ;
}
}
}
ViewBaseServlet
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 {
ServletContext servletContext = this . getServletContext ( ) ;
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver ( servletContext) ;
templateResolver. setTemplateMode ( TemplateMode . HTML ) ;
String viewPrefix = servletContext. getInitParameter ( "view-prefix" ) ;
templateResolver. setPrefix ( viewPrefix) ;
String viewSuffix = servletContext. getInitParameter ( "view-suffix" ) ;
templateResolver. setSuffix ( viewSuffix) ;
templateResolver. setCacheTTLMs ( 60000L ) ;
templateResolver. setCacheable ( true ) ;
templateResolver. setCharacterEncoding ( "utf-8" ) ;
templateEngine = new TemplateEngine ( ) ;
templateEngine. setTemplateResolver ( templateResolver) ;
}
protected void processTemplate ( String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp. setContentType ( "text/html;charset=UTF-8" ) ;
WebContext webContext = new WebContext ( req, resp, getServletContext ( ) ) ;
templateEngine. process ( templateName, webContext, resp. getWriter ( ) ) ;
}
}
StringUtil
package com. atguigu. myssm. util ;
public class StringUtil {
public static boolean isEmpty ( String str) {
return str== null || "" . equals ( str) ;
}
public static boolean isNotEmpty ( String str) {
return ! isEmpty ( str) ;
}
}
pro16-fruit2.1-mvc-controller.iml
< ? xml version= "1.0" encoding= "UTF-8" ? >
< module type = "JAVA_MODULE" version= "4" >
< component name= "FacetManager" >
< facet type= "web" name= "Web" >
< configuration>
< descriptors>
< deploymentDescriptor name= "web.xml" url= "file://$MODULE_DIR$/web/WEB-INF/web.xml" / >
< / descriptors>
< webroots>
< root url= "file://$MODULE_DIR$/web" relative= "/" / >
< / webroots>
< / configuration>
< / facet>
< / component>
< component name= "NewModuleRootManager" inherit- compiler- output= "true" >
< exclude- output / >
< content url= "file://$MODULE_DIR$" >
< sourceFolder url= "file://$MODULE_DIR$/src" isTestSource= "false" / >
< / content>
< orderEntry type= "inheritedJdk" / >
< orderEntry type= "sourceFolder" forTests= "false" / >
< orderEntry type= "library" scope= "PROVIDED" name= "Tomcat 8.0.42" level= "application_server_libraries" / >
< orderEntry type= "library" name= "lib" level= "project" / >
< orderEntry type= "library" name= "lib_thymeleaf" level= "project" / >
< / component>
< / module >
add.css
* {
color: threeddarkshadow;
}
body{
margin: 0 ;
padding: 0 ;
background- color: #808080 ;
}
div{
position: relative;
float : left;
}
#div_container{
width: 80 % ;
height: 100 % ;
border: 0 px solid blue;
margin- left: 10 % ;
float : left;
background- color: honeydew;
border- radius: 8 px;
}
#div_fruit_list{
width: 100 % ;
border: 0 px solid red;
}
#tbl_fruit{
width: 60 % ;
line- height: 28 px;
margin- top: 16 px;
margin- left: 20 % ;
}
#tbl_fruit , #tbl_fruit tr , #tbl_fruit th , #tbl_fruit td{
border: 1 px solid gray;
border- collapse: collapse;
text- align: center;
font- size: 16 px;
font- family: "黑体" ;
font- weight: lighter;
}
. w20{
width: 20 % ;
}
. delImg{
width: 24 px;
height: 24 px;
}
. btn{
border: 1 px solid lightgray;
width: 80 px;
height: 24 px;
}
. center{
text- align: center;
}
. f30{
font- size: 30 px;
}
edit.css
* {
color: threeddarkshadow;
}
body{
margin: 0 ;
padding: 0 ;
background- color: #808080 ;
}
div{
position: relative;
float : left;
}
#div_container{
width: 80 % ;
height: 100 % ;
border: 0 px solid blue;
margin- left: 10 % ;
float : left;
background- color: honeydew;
border- radius: 8 px;
}
#div_fruit_list{
width: 100 % ;
border: 0 px solid red;
}
#tbl_fruit{
width: 60 % ;
line- height: 28 px;
margin- top: 16 px;
margin- left: 20 % ;
}
#tbl_fruit , #tbl_fruit tr , #tbl_fruit th , #tbl_fruit td{
border: 1 px solid gray;
border- collapse: collapse;
text- align: center;
font- size: 16 px;
font- family: "黑体" ;
font- weight: lighter;
}
. w20{
width: 20 % ;
}
. delImg{
width: 24 px;
height: 24 px;
}
. btn{
border: 1 px solid lightgray;
width: 80 px;
height: 24 px;
}
. center{
text- align: center;
}
. f30{
font- size: 30 px;
}
index.css
* {
color: threeddarkshadow;
}
a{
text- decoration: none;
}
body{
margin: 0 ;
padding: 0 ;
background- color: #808080 ;
}
div{
position: relative;
float : left;
}
#div_container{
width: 80 % ;
height: 100 % ;
border: 0 px solid blue;
margin- left: 10 % ;
float : left;
background- color: honeydew;
border- radius: 8 px;
}
#div_fruit_list{
width: 100 % ;
border: 0 px solid red;
}
#tbl_fruit{
width: 60 % ;
line- height: 28 px;
margin- top: 16 px;
margin- left: 20 % ;
}
#tbl_fruit , #tbl_fruit tr , #tbl_fruit th , #tbl_fruit td{
border: 1 px solid gray;
border- collapse: collapse;
text- align: center;
font- size: 16 px;
font- family: "黑体" ;
font- weight: lighter;
}
. w20{
width: 20 % ;
}
. delImg{
width: 24 px;
height: 24 px;
}
. btn{
border: 1 px solid lightgray;
width: 80 px;
height: 24 px;
}
. center{
text- align: center;
}
. f30{
font- size: 30 px;
}
index.js
function delFruit ( fid) {
if ( confirm ( '是否确认删除?') ) {
window. location. href= 'fruit. do ? fid= '+fid+' & operate= del';
}
}
function page ( pageNo) {
window. location. href= "fruit.do?pageNo=" + pageNo;
}
web.xml
< 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" >
< ! -- 配置上下文参数 -- >
< 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>
add.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" > 新增库存信息< / p>
< ! -- < form action= "add.do" method= "post" > -- >
< ! -- < form th: action= "@{/fruit.do}" method= "post" > -- >
< form action= "fruit.do" method= "post" >
< input type= "hidden" name= "operate" value= "add" / >
< table id= "tbl_fruit" >
< tr>
< th class = "w20" > 名称:< / th>
< ! -- < td> < input type= "text" name= "fname" th: value= "${fruit.fname}" / > < / td> -- >
< td> < input type= "text" name= "fname" / > < / td>
< / tr>
< tr>
< th class = "w20" > 单价:< / th>
< td> < input type= "text" name= "price" / > < / td>
< / tr>
< tr>
< th class = "w20" > 库存:< / th>
< td> < input type= "text" name= "fcount" / > < / td>
< / tr>
< tr>
< th class = "w20" > 备注:< / th>
< td> < input type= "text" name= "remark" / > < / td>
< / tr>
< tr>
< th colspan= "2" >
< input type= "submit" value= "添加" / >
< / 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" > 编辑库存信息3 < / p>
< form th: action= "@{/fruit.do}" method= "post" th: object= "${fruit}" >
< input type= "hidden" name= "operate" value= "update" >
< ! -- 隐藏域 : 功能类似于文本框 , 它的值会随着表单的发送也会发送给服务器,但是界面上用户看不到 -- >
< input type= "hidden" name= "fid" th: value= "*{fid}" / >
< table id= "tbl_fruit" >
< tr>
< th class = "w20" > 名称:< / 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" > 单价:< / th>
< td> < input type= "text" name= "price" th: value= "*{price}" / > < / td>
< / tr>
< tr>
< th class = "w20" > 库存:< / th>
< td> < input type= "text" name= "fcount" th: value= "*{fcount}" / > < / td>
< / tr>
< tr>
< th class = "w20" > 备注:< / th>
< td> < input type= "text" name= "remark" th: value= "*{remark}" / > < / td>
< / tr>
< tr>
< th colspan= "2" >
< input type= "submit" value= "修改" / >
< / 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" >
< script language= "JavaScript" src= "js/index.js" > < / script>
< / head>
< body>
< div id= "div_container" >
< div id= "div_fruit_list" >
< p class = "center f30" > 欢迎使用水果库存后台管理系统< / p>
< div style= "border:0px solid red;width:60%;margin-left:20%;text-align:right;" >
< form th: action= "@{/fruit.do}" method= "post" style= "float:left;width:60%;margin-left:20%;" >
< input type= "hidden" name= "oper" value= "search" / >
请输入关键字:< input type= "text" name= "keyword" th: value= "${session.keyword}" / >
< input type= "submit" value= "查询" class = "btn" / >
< / form>
< a th: href= "@{/add.html}" style= "border:0px solid blue;margin-bottom:4px;" > 添加新库存记录< / a>
< / div>
< table id= "tbl_fruit" >
< tr>
< th class = "w20" > 名称< / th>
< th class = "w20" > 单价< / th>
< th class = "w20" > 库存< / th>
< th> 操作< / th>
< / tr>
< tr th: if = "${#lists.isEmpty(session.fruitList)}" >
< td colspan= "4" > 对不起,库存为空!< / 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}}" > 苹果< / a> < / td> -- >
< td> < a th: text= "${fruit.fname}" th: href= "@{/fruit.do(fid=${fruit.fid},operate='edit')}" > 苹果< / 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: onclick= "'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= "首 页1" class = "btn" th: onclick= "|page(1)|" th: disabled= "${session.pageNo==1}" / >
< input type= "button" value= "上一页" class = "btn" th: onclick= "|page(${session.pageNo-1})|" th: disabled= "${session.pageNo==1}" / >
< input type= "button" value= "下一页" class = "btn" th: onclick= "|page(${session.pageNo+1})|" th: disabled= "${session.pageNo==session.pageCount}" / >
< input type= "button" value= "尾 页" class = "btn" th: onclick= "|page(${session.pageCount})|" th: disabled= "${session.pageNo==session.pageCount}" / >
< / div>
< / div>
< / div>
< / body>
< / html>