水果系统项目分析pro10-fruit1.5-thymeleaf
水果系统项目分析pro10-fruit1.5-thymeleaf
基本架构
增加
- 增加水果
- 删除水果
- 渲染页面
- 更新库存
如上面所示的功能
indexServlet
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从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();
//保存到session作用域
HttpSession session = request.getSession() ;
session.setAttribute("fruitList",fruitList);
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
super.processTemplate("index",request,response);
}
}
和上一个版本一样没什么太大的变化主要还是是去渲染html页面
DelServlet
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");
}
}
}
使用了注解/del.do当页面进入del.do的时候执行这个Servlet从写了doget方法当点击删除的时候将会给DelServlet发送请求,这时候我们可以获取到想要删除的水果的fidStr,当fidStr不为null或者不为空串的时候,将其转数字fid,然后盗用delFruit()方法在数据库中将这条记录删除.执行完成之后客户端冲定向到index页面
AddServlet
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");
}
}
当add.do点击增加按钮的时候的时候执行这个Servlet方法.
- 先设置编码为utf-8防止乱码
- 获取输入框中水果的全部信息.
- 将水果信息封装为一个fruit对象
- 调用addFruit()方法将这个friut对象放入数据库
- 客户端从定向为index页面
EditServlet
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);
}
}
}
这个方法是给edit.do页面做渲染使用的
- 当用户点击了某个数据,将该数据的fidStr获取出来
- 当fidStr不为空的时候,将其转化为数字fid
- 然后通过fruit.DAO()方法将这个对象获取出来,并且保存到request作用域里面.
- 然后将也面交给thymeleaf渲染到edit.html页面上面
UpdateServlet
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.设置编码
request.setCharacterEncoding("utf-8");
//2.获取参数
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.执行更新
fruitDAO.updateFruit(new Fruit(fid,fname, price ,fcount ,remark ));
//4.资源跳转
//super.processTemplate("index",request,response);
//request.getRequestDispatcher("index.html").forward(request,response);
//此处需要重定向,目的是重新给IndexServlet发请求,重新获取furitList,然后覆盖到session中,这样index.html页面上显示的session中的数据才是最新的
response.sendRedirect("index");
}
}
// java.lang.NumberFormatException: For input string: ""
当进入edit页面修改完信息并且点击完提交按钮之后执行这里面的Servlet方法
- 先设置编码
- 获取修改完之后的水果信息并且封装成对象放入updateFruit()方法里面进行更新.
- 将页面重新定向到index页面上面.
FruitDAO
package com.atguigu.fruit.dao;
import com.atguigu.fruit.pojo.Fruit;
import java.util.List;
public interface FruitDAO {
//获取所有的库存列表信息
List<Fruit> getFruitList();
//根据fid获取特定的水果库存信息
Fruit getFruitByFid(Integer fid);
//修改指定的库存记录
void updateFruit(Fruit fruit);
//根据fid删除指定的库存记录
void delFruit(Integer fid);
//添加新库存记录
void addFruit(Fruit fruit);
}
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() {
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());
}
}
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 ;
}
}
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">新增库存信息2</p>
<!--<form action="add.do" method="post">-->
<form action="add.do" method="post">
<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>
这是增加库存的页面,我们填好信息然后点击添加就会交给add.do处理.
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="@{/update.do}" method="post" th:object="${fruit}">
<!-- 隐藏域 : 功能类似于文本框 , 它的值会随着表单的发送也会发送给服务器,但是界面上用户看不到 -->
<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>
这个页面会通过thymeleaf该fid的数据信息,同时还有一个隐藏的fid发送过来便于后面的操作.当我们点击修改的时候又会把数据发送给update.do Servlet来更新这些信息.
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;">
<a th:href="@{/add.html}" style="border:0px solid blue;margin-bottom:4px;">添加新库存记录</a>
</div>
<table id="tbl_fruit">
<tr>
<th class="w20">名称1</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="@{/edit.do(fid=${fruit.fid})}">苹果</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>
</div>
</body>
</html>
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: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:"黑体";
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;
}
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:"黑体";
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:"黑体";
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.js
function delFruit(fid){
if(confirm('是否确认删除?')){
window.location.href='del.do?fid='+fid;
}
}
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">
<!-- 配置上下文参数 -->
<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>
StringUtil
package com.atguigu.myssm.util;
public class StringUtil {
//判断字符串是否为null或者""
public static boolean isEmpty(String str){
return str==null || "".equals(str);
}
public static boolean isNotEmpty(String str){
return !isEmpty(str);
}
}
BaseDAO
2package 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 ;
//T的Class对象
private Class entityClass ;
public BaseDAO(){
//getClass() 获取Class对象,当前我们执行的是new FruitDAOImpl() , 创建的是FruitDAOImpl的实例
//那么子类构造方法内部首先会调用父类(BaseDAO)的无参构造方法
//因此此处的getClass()会被执行,但是getClass获取的是FruitDAOImpl的Class
//所以getGenericSuperclass()获取到的是BaseDAO的Class
Type genericType = getClass().getGenericSuperclass();
//ParameterizedType 参数化类型
Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
//获取到的<T>中的T的真实的类型
Type actualType = actualTypeArguments[0];
try {
entityClass = Class.forName(actualType.getTypeName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
protected Connection getConn(){
try {
//1.加载驱动
Class.forName(DRIVER);
//2.通过驱动管理器获取连接对象
return DriverManager.getConnection(URL, USER, PWD);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return null ;
}
protected void close(ResultSet rs , PreparedStatement psmt , Connection conn){
try {
if (rs != null) {
rs.close();
}
if(psmt!=null){
psmt.close();
}
if(conn!=null && !conn.isClosed()){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//给预处理命令对象设置参数
private void setParams(PreparedStatement psmt , Object... params) throws SQLException {
if(params!=null && params.length>0){
for (int i = 0; i < params.length; i++) {
psmt.setObject(i+1,params[i]);
}
}
}
//执行更新,返回影响行数
protected int executeUpdate(String sql , Object... params){
boolean insertFlag = false ;
insertFlag = sql.trim().toUpperCase().startsWith("INSERT");
try {
conn = getConn();
if(insertFlag){
psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
}else {
psmt = conn.prepareStatement(sql);
}
setParams(psmt,params);
int count = psmt.executeUpdate() ;
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;
}
//通过反射技术给obj对象的property属性赋propertyValue值
private void setValue(Object obj , String property , Object propertyValue){
Class clazz = obj.getClass();
try {
//获取property这个字符串对应的属性名 , 比如 "fid" 去找 obj对象中的 fid 属性
Field field = clazz.getDeclaredField(property);
if(field!=null){
field.setAccessible(true);
field.set(obj,propertyValue);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
//执行复杂查询,返回例如统计结果
protected Object[] executeComplexQuery(String sql , Object... params){
try {
conn = getConn() ;
psmt = conn.prepareStatement(sql);
setParams(psmt,params);
rs = psmt.executeQuery();
//通过rs可以获取结果集的元数据
//元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等
ResultSetMetaData rsmd = rs.getMetaData();
//获取结果集的列数
int columnCount = rsmd.getColumnCount();
Object[] columnValueArr = new Object[columnCount];
//6.解析rs
if(rs.next()){
for(int i = 0 ; i<columnCount;i++){
Object columnValue = rs.getObject(i+1); //33 苹果 5
columnValueArr[i]=columnValue;
}
return columnValueArr ;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(rs,psmt,conn);
}
return null ;
}
//执行查询,返回单个实体对象
protected T load(String sql , Object... params){
try {
conn = getConn() ;
psmt = conn.prepareStatement(sql);
setParams(psmt,params);
rs = psmt.executeQuery();
//通过rs可以获取结果集的元数据
//元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等
ResultSetMetaData rsmd = rs.getMetaData();
//获取结果集的列数
int columnCount = rsmd.getColumnCount();
//6.解析rs
if(rs.next()){
T entity = (T)entityClass.newInstance();
for(int i = 0 ; i<columnCount;i++){
String columnName = rsmd.getColumnName(i+1); //fid fname price
Object columnValue = rs.getObject(i+1); //33 苹果 5
setValue(entity,columnName,columnValue);
}
return entity ;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} finally {
close(rs,psmt,conn);
}
return null ;
}
//执行查询,返回List
protected List<T> executeQuery(String sql , Object... params){
List<T> list = new ArrayList<>();
try {
conn = getConn() ;
psmt = conn.prepareStatement(sql);
setParams(psmt,params);
rs = psmt.executeQuery();
//通过rs可以获取结果集的元数据
//元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等
ResultSetMetaData rsmd = rs.getMetaData();
//获取结果集的列数
int columnCount = rsmd.getColumnCount();
//6.解析rs
while(rs.next()){
T entity = (T)entityClass.newInstance();
for(int i = 0 ; i<columnCount;i++){
String columnName = rsmd.getColumnName(i+1); //fid fname price
Object columnValue = rs.getObject(i+1); //33 苹果 5
setValue(entity,columnName,columnValue);
}
list.add(entity);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} finally {
close(rs,psmt,conn);
}
return list ;
}
}
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 {
// 1.获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 2.创建Thymeleaf解析器对象
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// 3.给解析器对象设置参数
// ①HTML是默认模式,明确设置是为了代码更容易理解
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");
// 4.创建模板引擎对象
templateEngine = new TemplateEngine();
// 5.给模板引擎对象设置模板解析器
templateEngine.setTemplateResolver(templateResolver);
}
protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1.设置响应体内容类型和字符集
resp.setContentType("text/html;charset=UTF-8");
// 2.创建WebContext对象
WebContext webContext = new WebContext(req, resp, getServletContext());
// 3.处理模板数据
templateEngine.process(templateName, webContext, resp.getWriter());
}
}