JavaWeb阶段性项目1:系统的servlet优化5
前置知识
前置准备
知识准备
已掌握JavaSE/MySQL/JDBC+HTML/CSS/JavaScript基础
并已完成了Javaweb前置知识的学习
04-JavaScript基础应用-鼠标悬浮/离开表格格式变化
05-JavaWeb-Tomcat8安装、Servlet初识
06-JavaWeb-Servlet方法/生命周期、HTTP/会话session
09-JavaWeb-阶段性项目1:最简单的后台库存管理系统
10-JavaWeb阶段性项目1:系统的servlet优化1
11-JavaWeb阶段性项目1:系统的servlet优化2
12-JavaWeb阶段性项目1:系统的servlet优化3
13-JavaWeb阶段性项目1:系统的servlet优化4
资源准备
教学资源
https://pan.baidu.com/s/1TS7QJ_a2vHHmXkggAs8RMQ
提取码:yyds
servlet优化的过程5
package com.fancy.fruit.controllers;
import com.fancy.fruit.dao.FruitDAO;
import com.fancy.fruit.dao.impl.FruitDAOImpl;
import com.fancy.fruit.pojo.Fruit;
import com.fancy.myssm.basedao.myspringmvc.ViewBaseServlet;
import com.fancy.myssm.basedao.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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
public class FruitController extends ViewBaseServlet {
private FruitDAO fruitDAO = new FruitDAOImpl();
private String update(Integer fid, String fname, Integer price, Integer fcount, String remark) {
//2.获取参数
//3.执行更新
fruitDAO.updateFruit(new Fruit(fid, fname, price, fcount, remark));
//4.资源跳转
//super.processTemplate("index",req,resp);
//此处需要重定向,目的是重新给IndexServlet发请求,然后覆盖到session中,这样index页面上显示的数据才是最新的
//resp.sendRedirect("fruit.do");//重定向,重新给fruit.do,给session重新给fruit更改后的数据
return "redirect:fruit.do";
}
private String edit(Integer fid, HttpServletRequest req) throws ServletException {
//HTML是模板,thymeleaf是引擎,我们在servlet中调用了引擎并且给了引擎需要的模板和参数
if (fid != null) {
Fruit fruit = fruitDAO.getFruitByFid(fid);
//获取到fruit对象后将之放置在session作用域
req.setAttribute("fruit", fruit);
//thymeleaf的viewBaseServlet中的方法,处理模板数据
//super.processTemplate("edit",req,resp);
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";
}
}
把获取参数的操作交给中央控制器DispatcherController处理
改DispatcherController的service方法,需使用Java8的反射相关新特性,获取运行时类的对象中的方法中的参数名,操作如下:
Java虚拟机在编译时,附带上的形参名称-parameters
设置好后再删掉,out目录下的编译后.class文件
最终改好的DispatcherController的service方法:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
request.setCharacterEncoding("UTF-8");
//假设url是: http://localhost:8080/pro15/hello.do
//那么servletPath是: /hello.do
// 我的思路是:
// 第1步: /hello.do -> hello 或者 /fruit.do -> fruit
// 第2步: hello -> HelloController 或者 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[] methods = controllerBeanObj.getClass().getDeclaredMethods();
for(Method method : methods){
if(operate.equals(method.getName())){
//1.统一获取请求参数
//1-1.获取当前方法的参数,返回参数数组
Parameter[] parameters = method.getParameters();
//1-2.parameterValues 用来承载参数的值
Object[] parameterValues = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
String parameterName = parameter.getName() ;
//如果参数名是request,response,session 那么就不是通过请求中获取参数的方式了
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 ;
}
}
//2.controller组件中的方法调用
method.setAccessible(true);
Object returnObj = method.invoke(controllerBeanObj,parameterValues);
//3.视图处理
String methodReturnStr = (String)returnObj ;
if(methodReturnStr.startsWith("redirect:")){ //比如: redirect:fruit.do
String redirectStr = methodReturnStr.substring("redirect:".length());
response.sendRedirect(redirectStr);
}else{
super.processTemplate(methodReturnStr,request,response); // 比如: "edit"
}
}
}
/*
}else{
throw new RuntimeException("operate值非法!");
}
*/
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
常见错误: IllegalArgumentException: argument type mismatch
点击下一页时出的问题
因为URL= localhost:8080/pro16/fruit.do?pageNo=1 下一页时
因为URL= localhost:8080/pro16/fruit.do?pageNo=2
pageNo获取为2时,parameterValues中存储的是字符串“2”而不是integer的2
所以,需要增加一个判断再赋给parameterObj,才能添加到承载最终参数值数组的parameterValues中
运行
报错原因:request和req的问题,以后项目注意参数名称统一。