Java EE三层架构
分层目的是为了解耦,降低代码的耦合度。方便后期的维护和升级
建包:
项目编写顺序:
1.创建数据库和所需要的表
2.编写数据库对应的Javabean对象
3.编写JdbcUtils类
4.编写BaseDao
5.编写dao和测试
6.编写Service和测试
7.编写web层
web层编写servlet来处理service请求
调用service层方法来处理
注:web阶段使用 base 标签 加相对路径
框架阶段使用绝对路径
优化代码:
1 页面jsp动态化:将所有的html页面转为jsp页面
2 抽取页面中相同的部分
head中的 css、jQuery、base标签 (base标签要改为动态获取的)
每个页面的页脚
登录成功后的菜单
manager模块的菜单
3 登录 注册错误提示及表单回显
Servlet 程序端需要添加回显信息到 Request 域中
4 BaseServlet 的抽取
在实际的项目开发中,一个模块,一般只使用一个 Servlet 程序
如图 实现请求分发的功能
#使用反射优化大量 else if 对于方法的判断
//原来
if("login".equals(action)){
login(request, response);
}else if("regist".equals(action)){
regist(request, response);
}
//现在
try {
Method method = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this, request, response);
} catch (Exception e) {
e.printStackTrace();
}
5 数据的封装和抽取 BeanUtils 的使用
BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavaBean 中。 BeanUtils 工具类,经常用于把 Map 中的值注入到 JavaBean 中,或者是对象属性值的拷贝操作。
//导包 commons-beanutils /commons-logging
//编写工具类
public static void fillBean(Object obj, Map map){
try {
BeanUtils.populate(obj, map);
} catch (Exception e) {
e.printStackTrace();
}
}
//调用
webUtils.fillBean(user,request.getParameterMap());
6 使用 EL 表达式修改表单回显
MVC 概念
MVC 全称:Model 模型、 View 视图、 Controller 控制器。
MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 Web 层的代码如何有效分离,单独工作。
View 视图:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作—— JSP/HTML。
Controller 控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个“调度者”的角色——Servlet。 转到某个页面。或者是重定向到某个页面。
Model 模型:将与业务逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂任何与数据处理相关的代码—— JavaBean/domain/entity/pojo
MVC 是一种思想 MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了降低耦合度)
标签 发起是一个 get 请求
tips:如果访问jsp无法直接获取数据 那么可以让程序先访问servlet程序 再转发
- 添加图书功能实现:
表单重复提交: 当用户提交完请求,浏览器会记录下最后一次请求的全部信息。当用户按下功能键 F5,就会发起浏览器记录的最后一次请求。所以添加图书要用请求重定向(发起的是两次请求)
- 删除图书功能的实现:
```javascript
//删除图书时 需要绑定单机事件 confirm 表示是否确认删除
$(function (){
$(“a.delclass”).click(function (){
}); });/**
* confirm 是确认提示框函数
* 参数是它的提示内容
* 它有两个按钮,一个是确认,一个是取消
* 返回true表示点击确认 返回false表示点击取消
*/
return confirm("确定要删除该图书吗?");
- **修改图书功能的实现:**
![image.png](https://cdn.nlark.com/yuque/0/2021/png/1605477/1625923717995-927e3e87-3979-4fcf-b237-e8fb8e6c6968.png#height=468&id=H1hLq&margin=%5Bobject%20Object%5D&name=image.png&originHeight=842&originWidth=1756&originalType=binary&ratio=1&size=1091400&status=done&style=none&width=975)
**动态修改隐藏域**:(既可以实现添加 又可以实现修改操作)<br />法一:可以在请求发起时,附带上当前要操作的值,并注入到隐藏域中<br />法二:通过判断当前参数中是否包含id参数。来判断是修改(有参数)还是添加(无参数)<br />法三:可以通过判断request域中是否包含有修改的图书实验对象
<a name="Xpg24"></a>
### 分页模块
![image.png](https://cdn.nlark.com/yuque/0/2021/png/1605477/1625983373623-b780770f-8c2b-441b-a38b-99c8d34d68af.png#height=421&id=zeFJn&margin=%5Bobject%20Object%5D&name=image.png&originHeight=622&originWidth=1508&originalType=binary&ratio=1&size=1058482&status=done&style=none&width=1021)<br />**先分析出需要的对象模型(page),**再做业务需求。
分页条跳到指定页数
```javascript
$(function (){
$("#searchPageBtn").click(function (){
var pageNo = $("#pn_input").val();
//js语言中提供了一个 location 地址栏对象
//它有一个属性 href ,它可以获取浏览器地址栏中的地址;
//href属性 可读,可写
location.href="manager/bookManager?action=page&pageNo="+pageNo;
});
});
注:再pageNo 注入之前要进行数据边界的检查(在bean对象set方法时设置)
//数据边界的有效检查
if(pageNo<1){
pageNo=1;
}
if(pageNo>pageTotal){
pageNo=pageTotal;
}
#分页条码的输出:
需求:显示 5 个连续的页码,而且当前页码在中间。除了当前页码之外,每个页码都可以点击跳到指定页。
- 情况 1:如果总页码小于等于 5 的情况,页码的范围是:1-总页码
1 页 1
2 页 1,2
3 页 1,2,3
4 页 1,2,3,4
5 页 1,2,3,4,5
- 情况 2:总页码大于 5 的情况。假设一共 10 页
- 小情况 1:当前页码为前面 3 个:1,2,3 的情况,页码范围是:1-5.
【1】2,3,4,5
1,【2】3,4,5
1,2,【3】4,5
- 小情况 2:当前页码为最后 3 个,8,9,10,页码范围是:总页码减 4 - 总页码
6,7【8】9,10
6,7,8【9】10
6,7,8,9【10】
- 小情况 3:4,5,6,7,页码范围是:当前页码减 2 - 当前页码加 2
2,3,【4】,5,6
3,4,【5】,6,7
4,5,【6】,7,8
5,6,【7】,8,9
//分页条的编写
<div id="page_nav">
<c:if test="${requestScope.page.pageNo>1}">
<a href="${requestScope.page.url}&pageNo=${requestScope.page.pageNo-1}">上一页</a>
</c:if>
<%--页码输出的开始--%>
<c:choose>
<c:when test="${ requestScope.page.pageTotal <= 5 }">
<c:set var="begin" value="1"/>
<c:set var="end" value="${requestScope.page.pageTotal}"/>
</c:when>
<c:when test="${requestScope.page.pageTotal > 5}">
<c:choose>
<c:when test="${requestScope.page.pageNo <= 3}">
<c:set var="begin" value="1"/>
<c:set var="end" value="5"/>
</c:when>
<c:when test="${requestScope.page.pageNo > requestScope.page.pageTotal-3}">
<c:set var="begin" value="${requestScope.page.pageTotal-4}"/>
<c:set var="end" value="${requestScope.page.pageTotal}"/>
</c:when>
<c:otherwise>
<c:set var="begin" value="${requestScope.page.pageNo-2}"/>
<c:set var="end" value="${requestScope.page.pageNo+2}"/>
</c:otherwise>
</c:choose>
</c:when>
</c:choose>
<c:forEach begin="${begin}" end="${end}" var="i">
<c:if test="${i == requestScope.page.pageNo}">
【${i}】
</c:if>
<c:if test="${i != requestScope.page.pageNo}">
<a href="${requestScope.page.url}&pageNo=${i}">${i}</a>
</c:if>
</c:forEach>
<%--页码输出的结束--%>
<c:if test="${requestScope.page.pageNo<requestScope.page.pageTotal}">
<a href="${requestScope.page.url}&pageNo=${requestScope.page.pageNo+1}">下一页</a>
</c:if>
,共${requestScope.page.pageTotal}页,${requestScope.page.pageTotalCount}条记录, 跳至第<input value="${requestScope.page.pageNo}" name="pn" id="pn_input"/>页
<input id="searchPageBtn" type="button" value="确定">
</div>
价格搜索区间:
用户登录的信息保存在sessionScope域中
注销用户:
1 销毁session中的用户登录信息
2 重定向会首页或者登录页面
//1 销毁session中的用户登录信息
request.getSession().invalidate();
//2 重定向会首页或者登录页面
response.sendRedirect(request.getContextPath());
表单重复提交
表单重复提交有三种常见的情况:
1 提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键F5,就会发起最后一次的请求。造成表单重复提交问题
解决方法:使用重定向来进行跳转
2 用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候多点几次提交操作,也会造成表单重复提交
3 用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复提交
谷歌 kaptcha 图片验证码的使用
//配置xml文件
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/Kaptcha.jpg</url-pattern>
</servlet-mapping>
//在表单中img标签去显示验证码并使用
<img id="code_img" alt="" src="Kaptcha.jpg">
#验证码的切换
//给验证码的图片 绑定单击事件
$(function (){
$("#code_img").click(function (){
//this 对象,表示当前正在响应事件的dom对象
//src 属性表示验证码 img 标签的图片路径。它可读,可写
this.src="${path}Kaptcha.jpg?d="+new Date();
});
});
购物车模块实现(使用session保存)
使用Filter过滤器实现后台的权限管理
<filter>
<filter-name>managerFilter</filter-name>
<filter-class>com.book.filter.managerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>managerFilter</filter-name>
<url-pattern>/pages/manager/*</url-pattern>
<url-pattern>/manager/bookServlet</url-pattern>
</filter-mapping>
error 标签配置错误页面
<error-page>
<error-code>404</error-code>
<location>/pages/error/error_404.jsp</location>
</error-page>
注:再收到异常后,要继续把异常往外抛,tomcat服务器收到异常后就会处理相应的错误代码页面