前篇
分页-pagination
// 查询指定页码的列表信息,每页显示5条信息
List<Fruit> getAll(Integer pageNo);
@Override
public List<Fruit> getAll(Integer pageNo) {
String sql = "select * from t_fruit limit ?,5";
List<Fruit> list = super.QueryList(sql,(pageNo - 1) * 5);
return list;
}
Integer pageNo = 1;
String pageNoStr = req.getParameter("pageNo");
if (StringUtil.isNotEmpty(pageNoStr)){
pageNo= Integer.parseInt(pageNoStr);
}
HttpSession session = req.getSession();
session.setAttribute("pageNo",pageNo);
function page(pageNo){
window.location.href = "fruit?pageNo="+pageNo;
}
// 获取所有的条数
Integer getCount();
@Override
public Integer getCount() {
String sql = "select count(*) from t_fruit";
return ((Long)super.getValue(sql)).intValue();
}
Integer pageCount = fruitService.getCount();
Integer pageNum = (pageCount + 5 - 1) / 5;
session.setAttribute("pageNum",pageNum);
/*
一页显示5条数据
* 总记录条数 页数
* 1 1
* 5 1
* 6 2
* 10 2
* 11 3
* 15 3
* 16 4
* pageCount (pageCount + 5 - 1) / 5
* */
// 转发
super.processTemplate("index",req,resp);
<table>
<tr>
<th>名称</th>
<th>单价</th>
<th>数量</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 th:text="${fruit.fname}">苹果</td>
<td th:text="${fruit.price}">12</td>
<td th:text="${fruit.fcount}">3</td>
<td>
<div class="opBtn">
<input type="button" value="删除"/>
<input type="button" value="修改" >
</div>
</td>
</tr>
</table>
</div>
<div class="pageBtn">
<input type="button" value="首 页" th:onclick="page(1)" th:disabled="${session.pageNo==1}">
<input type="button" value="上一页" th:onclick="|page(${session.pageNo-1})|" th:disabled="${session.pageNo==1}">
<input type="button" value="下一页" th:onclick="|page(${session.pageNo+1})|" th:disabled="${session.pageNo==session.pageNum}">
<input type="button" value="尾 页" th:onclick="|page(${session.pageNum})|" th:disabled="${session.pageNo==session.pageNum}">
</div>
关键字查询-keyword
<form th:action="@{/index.do}" method="post">
<input type="hidden" name="oper" value="search">
请输入关键字:<input type="text" name="keyword" th:value="${session.keyword}">
<input type="submit" value="查询">
</form>
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String oper = req.getParameter("oper");
// 如果oper != null,则表示有关键字
// 如果oper == null,则表示没有关键字
HttpSession session = req.getSession();
String keyword = null;
Integer pageNo = 1;
if (StringUtil.isNotEmpty(oper) && "search".equals(oper)){
// 说明是点击表单过来的,要进行关键字查询
// 此时pageNo还原为1,keyword应该从请求参数中获取
pageNo = 1;
keyword = req.getParameter("keyword");
if (keyword.isEmpty()){
keyword = "";
}
session.setAttribute("keyword",keyword);
}else{
// 说明此处不是点击表单查询发送过来的请求(比如点击下面的下一页,上一页,或者直接在地址栏输入网址)
// 此时keyword应该从session作用域获取
String pageNoStr = req.getParameter("pageNo");
if (StringUtil.isNotEmpty(pageNoStr)){
pageNo= Integer.parseInt(pageNoStr);
}
Object keywordStr = session.getAttribute("keyword");
if (keywordStr != null){
keyword = (String) keywordStr;
}else{
keyword = "";
}
}
session.setAttribute("pageNo",pageNo);
List<Fruit> fruitList = fruitService.getAll(pageNo,keyword);
fruitList.forEach(System.out::println);
session.setAttribute("fruitList",fruitList);
Integer pageCount = fruitService.getCount(keyword);
Integer pageNum = (pageCount + 5 - 1) / 5;
session.setAttribute("pageNum",pageNum);
/*
一页显示5条数据
* 总记录条数 页数
* 1 1
* 5 1
* 6 2
* 10 2
* 11 3
* 15 3
* 16 4
* pageCount (pageCount + 5 - 1) / 5
* */
// 转发
super.processTemplate("index",req,resp);
}
// 查询指定页码的列表信息,每页显示5条信息
List<Fruit> getAll(Integer pageNo,String keyword);
// 获取所有的条数
Integer getCount(String keyword);
@Override
public List<Fruit> getAll(Integer pageNo,String keyword) {
String sql = "select * from t_fruit where fname like ? or remark like ? limit ?,5";
List<Fruit> list = super.QueryList(sql,"%"+keyword+"%","%"+keyword+"%",(pageNo - 1) * 5);
return list;
}
@Override
public Integer getCount(String keyword) {
String sql = "select count(*) from t_fruit where fname like ? or remark like ?";
return ((Long)super.getValue(sql,"%"+keyword+"%","%"+keyword+"%")).intValue();
}
MVC的演变
优化一:
将多个Servlet根据前端参数operate合并为一个Servlet,根据分支结构选出参数对应的方法。
/**
* @author crystal
* @create 2023-01-12 18:36
*/
@WebServlet("/fruit.do")
public class FruitServlet extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
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;
default:
throw new RuntimeException("operate值非法!");
}
}
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() ;
Integer pageNo = 1 ;
String oper = request.getParameter("oper");
//如果oper!=null 说明 通过表单的查询按钮点击过来的
//如果oper是空的,说明 不是通过表单的查询按钮点击过来的
String keyword = null ;
if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//说明是点击表单查询发送过来的请求
//此时,pageNo应该还原为1 , keyword应该从请求参数中获取
pageNo = 1 ;
keyword = request.getParameter("keyword");
if(StringUtil.isEmpty(keyword)){
keyword = "" ;
}
session.setAttribute("keyword",keyword);
}else{
//说明此处不是点击表单查询发送过来的请求(比如点击下面的上一页下一页或者直接在地址栏输入网址)
//此时keyword应该从session作用域获取
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);
//总记录条数
int fruitCount = fruitDAO.getFruitCount(keyword);
//总页数
int pageCount = (fruitCount+5-1)/5 ;
/*
总记录条数 总页数
1 1
5 1
6 2
10 2
11 3
fruitCount (fruitCount+5-1)/5
*/
session.setAttribute("pageCount",pageCount);
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
super.processTemplate("index",request,response);
}
}
前端请求 (代码片段):
<td><a th:text="${fruit.fname}" th:href="@{/fruit.do(fid=${fruit.fid},operate='edit')}">苹果</a></td>
<form th:action="@{/fruit.do}" method="post" style="float:left;width:60%;margin-left:20%;">
<input type="hidden" name="oper" value="search"/>
function delFruit(fid){
if(confirm('是否确认删除?')){
window.location.href='fruit.do?fid='+fid+'&operate=del';
}
}
function page(pageNo){
window.location.href="fruit.do?pageNo="+pageNo;
}
<form th:action="@{/fruit.do}" method="post" th:object="${fruit}">
<input type="hidden" name="operate" value="update">
<form action="fruit.do" method="post">
<input type="hidden" name="operate" value="add">
优化二(reflect):
/**
* @author crystal
* @create 2023-01-12 18:36
*/
@WebServlet("/fruit.do")
public class FruitServlet extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String operate = request.getParameter("operate");
if (StringUtil.isEmpty(operate)){
operate = "index";
}
// 通过反射获取当前类中的所有方法
Method[] methods = this.getClass().getDeclaredMethods();
for(Method method : methods){
String methodName = method.getName();
if (operate.equals(methodName)){
try {
method.invoke(this,request,response);
return;
} catch (Exception e) {
e.printStackTrace();
}
}
}
throw new RuntimeException("operate值非法!");
}
private void update(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("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() ;
Integer pageNo = 1 ;
String oper = request.getParameter("oper");
//如果oper!=null 说明 通过表单的查询按钮点击过来的
//如果oper是空的,说明 不是通过表单的查询按钮点击过来的
String keyword = null ;
if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//说明是点击表单查询发送过来的请求
//此时,pageNo应该还原为1 , keyword应该从请求参数中获取
pageNo = 1 ;
keyword = request.getParameter("keyword");
if(StringUtil.isEmpty(keyword)){
keyword = "" ;
}
session.setAttribute("keyword",keyword);
}else{
//说明此处不是点击表单查询发送过来的请求(比如点击下面的上一页下一页或者直接在地址栏输入网址)
//此时keyword应该从session作用域获取
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);
//总记录条数
int fruitCount = fruitDAO.getFruitCount(keyword);
//总页数
int pageCount = (fruitCount+5-1)/5 ;
/*
总记录条数 总页数
1 1
5 1
6 2
10 2
11 3
fruitCount (fruitCount+5-1)/5
*/
session.setAttribute("pageCount",pageCount);
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
super.processTemplate("index",request,response);
}
}
优化三(DispatcherServlet):
part 01
/**
* @author crystal
* @create 2023-01-12 22:33
*/
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
// 获取请求的url:http://localhost:8080/pro/hello.do
// 第一步:getServletPath() 获取/hello.do
String servletPath = request.getServletPath();
// 第二步:从/hello.do获取hello.do
servletPath = servletPath.substring(1);
// 获取.do的索引
int lastDotIndexOf = servletPath.lastIndexOf(".do");
servletPath = servletPath.substring(0,lastDotIndexOf);
// 第三步:将获取到的hello ——> HelloController
}
}
applicationContext.xml
<?xml version="1.0" encoding="utf-8" ?>
<beans>
<bean id = "fruit" class = "com.atguigu.fruit.controllers.FruitController"></bean>
</beans>
/**
* @author crystal
* @create 2023-01-12 18:36
*/
//@WebServlet("/fruit.do")
public class FruitController extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String operate = request.getParameter("operate");
if (StringUtil.isEmpty(operate)){
operate = "index";
}
// 通过反射获取当前类中的所有方法
Method[] methods = this.getClass().getDeclaredMethods();
for(Method method : methods){
String methodName = method.getName();
if (operate.equals(methodName)){
try {
method.invoke(this,request,response);
return;
} catch (Exception e) {
e.printStackTrace();
}
}
}
throw new RuntimeException("operate值非法!");
}
private void update(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("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() ;
Integer pageNo = 1 ;
String oper = request.getParameter("oper");
//如果oper!=null 说明 通过表单的查询按钮点击过来的
//如果oper是空的,说明 不是通过表单的查询按钮点击过来的
String keyword = null ;
if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//说明是点击表单查询发送过来的请求
//此时,pageNo应该还原为1 , keyword应该从请求参数中获取
pageNo = 1 ;
keyword = request.getParameter("keyword");
if(StringUtil.isEmpty(keyword)){
keyword = "" ;
}
session.setAttribute("keyword",keyword);
}else{
//说明此处不是点击表单查询发送过来的请求(比如点击下面的上一页下一页或者直接在地址栏输入网址)
//此时keyword应该从session作用域获取
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);
//总记录条数
int fruitCount = fruitDAO.getFruitCount(keyword);
//总页数
int pageCount = (fruitCount+5-1)/5 ;
/*
总记录条数 总页数
1 1
5 1
6 2
10 2
11 3
fruitCount (fruitCount+5-1)/5
*/
session.setAttribute("pageCount",pageCount);
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
super.processTemplate("index",request,response);
}
}
part02
/**
* @author crystal
* @create 2023-01-12 22:33
*/
@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {
Map<String,Object> beanMap = new HashMap<>();
public void init(ServletConfig servletConfig){
try {
// 读取配置文件,将实例装进map集合
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 id = beanElement.getAttribute("id");
String className = beanElement.getAttribute("class");
Class<?> clazz = Class.forName(className);
Object classObj = clazz.newInstance();
beanMap.put(id,classObj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
// 获取请求的url:http://localhost:8080/pro/hello.do
// 第一步:getServletPath() 获取/hello.do
String servletPath = request.getServletPath();
// 第二步:从/hello.do获取hello.do
servletPath = servletPath.substring(1);
// 获取.do的索引
int lastDotIndexOf = servletPath.lastIndexOf(".do");
servletPath = servletPath.substring(0,lastDotIndexOf);
// 第三步:将获取到的hello ——> HelloController
Object beanObj = beanMap.get(servletPath);
// 获取前端的参数operate
String operate = request.getParameter("operate");
if (operate == null){
operate = "index";
}
// 根据反射调用方法
try {
Method method = beanObj.getClass().getDeclaredMethod(operate, HttpServletRequest.class, HttpServletResponse.class);
if (method != null){
method.setAccessible(true);
method.invoke(beanObj,request,response);
}else{
throw new RuntimeException("operate的值非法!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
part03(视图处理)
/**
* @author crystal
* @create 2023-01-12 22:33
*/
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {
Map<String,Object> beanMap = new HashMap<>();
public DispatcherServlet(){
}
public void init() throws ServletException {
super.init();
try {
// 读取配置文件,将实例装进map集合
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 id = beanElement.getAttribute("id");
String className = beanElement.getAttribute("class");
Class<?> clazz = Class.forName(className);
Object classObj = clazz.newInstance();
beanMap.put(id,classObj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
// 获取请求的url:http://localhost:8080/pro/hello.do
// 第一步:getServletPath() 获取/hello.do
String servletPath = request.getServletPath();
// 第二步:从/hello.do获取hello.do
servletPath = servletPath.substring(1);
// 获取.do的索引
int lastDotIndexOf = servletPath.lastIndexOf(".do");
servletPath = servletPath.substring(0,lastDotIndexOf);
// 第三步:将获取到的hello ——> HelloController
Object beanObj = beanMap.get(servletPath);
// 获取前端的参数operate
String operate = request.getParameter("operate");
if (operate == null){
operate = "index";
}
// 根据反射调用方法
try {
Method method = beanObj.getClass().getDeclaredMethod(operate, HttpServletRequest.class);
if (method != null){
// 调用controller中对应的方法
method.setAccessible(true);
Object ObjStr = method.invoke(beanObj,request);
// 视图处理
String returnStr = (String) ObjStr;
if (returnStr.startsWith("redirect:")){
String redirectVal = returnStr.substring("redirect:".length());
response.sendRedirect(redirectVal);
}else{
super.processTemplate(returnStr,request,response);
}
}else{
throw new RuntimeException("operate的值非法!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* @author crystal
* @create 2023-01-12 18:36
*/
public class FruitController{
private FruitDAO fruitDAO = new FruitDAOImpl();
private String update(HttpServletRequest request) throws ServletException {
//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("fruit.do");
return "redirect:fruit.do";
}
private String edit(HttpServletRequest request )throws IOException {
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);
return "edit";
}
return "error";
}
private String del(HttpServletRequest request)throws IOException {
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");
return "redirect:fruit.do";
}
return "error";
}
private String add(HttpServletRequest request) throws ServletException {
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");
return "redirect:fruit.do";
}
private String index(HttpServletRequest request)throws IOException {
HttpSession session = request.getSession() ;
Integer pageNo = 1 ;
String oper = request.getParameter("oper");
//如果oper!=null 说明 通过表单的查询按钮点击过来的
//如果oper是空的,说明 不是通过表单的查询按钮点击过来的
String keyword = null ;
if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//说明是点击表单查询发送过来的请求
//此时,pageNo应该还原为1 , keyword应该从请求参数中获取
pageNo = 1 ;
keyword = request.getParameter("keyword");
if(StringUtil.isEmpty(keyword)){
keyword = "" ;
}
session.setAttribute("keyword",keyword);
}else{
//说明此处不是点击表单查询发送过来的请求(比如点击下面的上一页下一页或者直接在地址栏输入网址)
//此时keyword应该从session作用域获取
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);
//总记录条数
int fruitCount = fruitDAO.getFruitCount(keyword);
//总页数
int pageCount = (fruitCount+5-1)/5 ;
/*
总记录条数 总页数
1 1
5 1
6 2
10 2
11 3
fruitCount (fruitCount+5-1)/5
*/
session.setAttribute("pageCount",pageCount);
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
// super.processTemplate("index",request,response);
return "index";
}
}
part04(参数提取)
/**
* @author crystal
* @create 2023-01-12 22:33
*/
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {
Map<String,Object> beanMap = new HashMap<>();
public DispatcherServlet(){
}
public void init() throws ServletException {
super.init();
try {
// 读取配置文件,将实例装进map集合
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 id = beanElement.getAttribute("id");
String className = beanElement.getAttribute("class");
Class<?> clazz = Class.forName(className);
Object classObj = clazz.newInstance();
beanMap.put(id,classObj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
// 获取请求的url:http://localhost:8080/pro/hello.do
// 第一步:getServletPath() 获取/hello.do
String servletPath = request.getServletPath();
// 第二步:从/hello.do获取hello.do
servletPath = servletPath.substring(1);
// 获取.do的索引
int lastDotIndexOf = servletPath.lastIndexOf(".do");
servletPath = servletPath.substring(0,lastDotIndexOf);
// 第三步:将获取到的hello ——> HelloController
Object beanObj = beanMap.get(servletPath);
// 获取前端的参数operate
String operate = request.getParameter("operate");
if (operate == null){
operate = "index";
}
// 根据反射调用方法
try {
// 1. 统一获取请求参数
Method[] methods = beanObj.getClass().getDeclaredMethods();
for (Method method : methods){
if(operate.equals(method.getName())){
Parameter[] parameters = method.getParameters();
// 创建数组,用来承载方法中参数的值
Object[] parameterVals = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
String parameterName = parameter.getName();
if ("request".equals(parameterName)){
parameterVals[i] = "request";
}else if("response".equals(parameterName)){
parameterVals[i] = "response";
}else if ("session".equals(parameterName)){
parameterVals[i] = request.getSession();
}else{
String parameterValue = request.getParameter(parameterName);
Class<?> typeName = parameter.getType();
parameterVals[i] = parameterValue;
Object parameterObj = parameterVals[i];
if (parameterObj != null){
if ("iava.lang.Integer".equals(typeName)){
parameterObj = Integer.parseInt(parameterValue);
}
parameterVals[i] = parameterObj;
}
}
}
// 调用controller中对应的方法
method.setAccessible(true);
Object ObjStr = method.invoke(beanObj,parameterVals);
// 视图处理
String returnStr = (String) ObjStr;
if (returnStr.startsWith("redirect:")){
String redirectVal = returnStr.substring("redirect:".length());
response.sendRedirect(redirectVal);
}else{
super.processTemplate(returnStr,request,response);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* @author crystal
* @create 2023-01-12 18:36
*/
public class FruitController{
private FruitDAO fruitDAO = new FruitDAOImpl();
private String update(Integer fid,String fname,Integer price,Integer fcount,String 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("fruit.do");
return "redirect:fruit.do";
}
private String edit(Integer fid ,HttpServletRequest request) {
if(fid != null){
Fruit fruit = fruitDAO.getFruitByFid(fid);
request.setAttribute("fruit",fruit);
// super.processTemplate("edit",request,response);
return "edit";
}
return "error";
}
private String del(Integer fid)throws IOException {
if(fid != null){
fruitDAO.delFruit(fid);
//super.processTemplate("index",request,response);
// response.sendRedirect("fruit.do");
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);
// response.sendRedirect("fruit.do");
return "redirect:fruit.do";
}
private String index(String oper,String keyword,Integer pageNo,HttpServletRequest request) {
HttpSession session = request.getSession() ;
//如果oper!=null 说明 通过表单的查询按钮点击过来的
//如果oper是空的,说明 不是通过表单的查询按钮点击过来的
if (pageNo == null){
pageNo = 1;
}
if(StringUtil.isNotEmpty(oper) && "search".equals(oper)){
//说明是点击表单查询发送过来的请求
//此时,pageNo应该还原为1 , keyword应该从请求参数中获取
pageNo = 1 ;
if(StringUtil.isEmpty(keyword)){
keyword = "" ;
}
session.setAttribute("keyword",keyword);
}else{
//说明此处不是点击表单查询发送过来的请求(比如点击下面的上一页下一页或者直接在地址栏输入网址)
//此时keyword应该从session作用域获取
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 ;
/*
总记录条数 总页数
1 1
5 1
6 2
10 2
11 3
fruitCount (fruitCount+5-1)/5
*/
session.setAttribute("pageCount",pageCount);
//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称 : index
//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是: / index .html
// super.processTemplate("index",request,response);
return "index";
}
}