1.整体的架构
2.多个请求对应一个 Servlet
1).Servlet 映射为 *.do:可以接收一切 .do 结尾的请求
@WebServlet("*.do")
public class CustomerServlet extends HttpServlet
2).在 Servlet 的 doGet() 和 doPost() 中
//1. 获取ServletPath:/edit4.do或者 /addCustomer.do
String servletPath = request.getServletPath();
//2. 去除 / 和 .do,得到类似于 edit 或者 addCustomer 这样的字符串
String methodName = servletPath.substring(1, servletPath.length()-3);
try {
//3. 利用反射获取 methodName 对应的方法
Method method = getClass().getDeclaredMethod(methodName,
HttpServletRequest.class, HttpServletResponse.class);
//4. 调动反射对应的方法
method.invoke(this, request, response);
} catch (Exception e) {
//若要调用的方法不存在,响应 erro.jsp
request.sendRedirect("/WEB-INF/erro.jsp");
}
3.查询:MVC的整个流程
query.do -> doPost -> query
query方法的代码
List<Customer> customers = customerDao.getListWithCriteria(cc);
request.setAttribute("customers", customers);
request.getRequestDispatcher("/index.jsp").forward(request, response);
jsp:获取 request 中的 customers 属性,遍历显示
<%
List<Customer> customers = (List<Customer>) request.getAttribute("customers");
if(customers != null && customers.size() > 0){
%>
<%
for(Customer customer:customers){
%>
<tr>
<td><%=customer.getId()%></td>
<td><%=customer.getName()%></td>
<td><%=customer.getAddress()%></td>
<td><%=customer.getPhone()%></td>
<td>
<a href = "edit.do?id=<%= customer.getId()%>">UPDATE </a>
<a href = "delete.do?id=<%= customer.getId() %>" class = "delete">DELETE</a>
</td>
</tr>
<%
}
4.模糊查询
1).正常的SQL:
String sql = “SELECT id, name, address, phone FROM customers WHERE id = ?”;
2).填充占位符的技巧:以 name 属性为例
public String getName() {
if(name == null)
name = "%%";
else
name = "%"+name+"%";
return name;
}
3).把查询条件封装为一个 JavaBean
public class CriteriaCustomer {
private String name;
private String address;
private String phone;
//....
}
5.对表单的复杂验证:验证需要通过业务层来完成,一般需要通过数据库服务器
6.提交表单,到 Servlet 的 doPost() 方法,doPost() 再转发回原来的 jsp 页面,直到该页面加载完成,整个过程只有一个 HttpservletRequest 对象。
上面一共有两个请求:
①.加载页面的请求,发出请求到页面加载完成,request 结束
②.点击提交按钮,到 Servlet 发出一个 request,Servlet 转发到 newcustomer.jsp 直到页面加载完成,整个过程是一个 request
7.表单的回显问题(了解)
<input type = "text" name = "name"
value = "<%=request.getParameter("name")==null?"":request.getParameter("name") %>"/>
8.修改的流程:先显示页面,修改字段,提交表单,修改
1). id 一般都使用隐藏域
<input type = 'hidden' name = "id" value = "<%=id%>"/>
2).修改中的复杂验证,若某一字段在数据表中不允许重复的解决方案
①.在表单中使用隐藏域,保存表单中最原始的值
<input type = "hidden" name = "oldName" value = "<%=oldName%>"/>
②.在 Servlet 中获取原始值和提交的值,比对,若一致则通过,若不一致,则使用新提交的值区查询数据表
//2. 检验 name 是否已经被占用
//2.1 比较 name 和 oldName 是否相同,若相同 name 可用
//2.2 若不相同,则调用 CustomerDao 的 getCountWithName(String name) 获取name是否存在
if(!oldName.equalsIgnoreCase(name)) {
long count = customerDao.getCountWithName(name);
//2.2 若返回值 > 0 ,则响应 updatecustomer.jsp 界面
//通过转发的方式来响应 updatecustomer.jsp
if(count > 0) {
//2.2.1 要求在 updatecustomer.jsp 页面提示一个错误消息:MIKE5 用户名已经被占用
//在 request 中放入一个属性 message:用户名 name 已经被占用。
//在页面上通过 request.getAttribute("message") 的方式来显示
request.setAttribute("message", "用户名"+name+"已经被注册,请重新选择");
//2.2.2 updatecustomer.jsp 的表单值可以回显
//address, phone, 显示提交表单新的值,而 name 显示 oldName, 而不是新提交的 name
//2.2.3 结束方法, return
request.getRequestDispatcher("/updatecustomer.jsp").forward(request, response);
return;
}
}
3).在修改状态下,若验证没有通过,表单的回显问题,不允许重复的提交要给与提示,在字段中显示旧的字段的值,允许修改的修改为新值,通过 ajax 会有更好的用户体验。
- response.sendRedirect()方法的副作用可以防止表单的重复提交。
- 面向接口编程:
private CustomerDAO customerDao = new CustomerDAOJdbcImpl();