Web项目系列文章推荐: |
---|
JavaWeb企业实战项目(一):环境搭建-用户注册-邮件发送 |
JavaWeb企业实战项目(三):商品模块 |
JavaWeb企业实战项目(四):订单模块 |
JavaWeb企业实战项目(五):后台模块1 |
JavaWeb企业实战项目(六):后台模块2 |
待更新 |
1_用户激活
2_登录,
3_退出,
4_抽取公共页面
5_查询所有分类
6_首页热门商品_最新商品显示
7_商品详情显示
8_基础分页操作
9_首页分类商品带分页查询
开发通用步骤: 1_准备工作 2_Servlet 3_service 4_Dao 5_jsp页面
原理如下:
步骤实现:
1、准备工作(忽略)
用户点击邮箱中的激活链接,向服务端发送method=active&code=234123adf22234
2、UserServlet___>active
获取到激活码
调用service功能,对账户进行激活操作
进行信息提示(成功,失败)
public String active(HttpServletRequest request, HttpServletResponse response) throws Exception{
//获取验证码
request.setCharacterEncoding("utf-8");
String code = request.getParameter("code");
//调用业务层的激活功能
UserService service = new UserServiceImpl();
boolean flag = service.activeUser(code);
//进行激活信息提示
if(flag){
//用户激活成功,向request放入提示信息,调到login页面
request.setAttribute("msg", "用户激活成功,请登录!");
return "/jsp/login.jsp";
}else{
//用户激活失败,向request放入提示信息,调到info页面
request.setAttribute("msg", "用户激活失败,请重新激活!");
return "/jsp/info.jsp";
}
}
3、service_dao
//UserServiceImpl
@Override
public boolean activeUser(String code) throws SQLException {
//实现激活功能
UserDao dao = new UserDaoImpl();
User user = dao.activeUser(code);
if(user!=null){
//如果存在user,则说明code存在
//修改激活状态,删除激活码
user.setState(1);
user.setCode(null);
//对数据库执行一次真实的更新操作
dao.updateUser(user);
return true;
}else{
//不可根据激活码查到一个用户
return false;
}
}
//UserDaoImpl
@Override
public void updateUser(User user) throws SQLException {
String sql = "update user set username = ?,password = ?,name = ?,email = ?,telephone = ?,birthday = ?,sex = ?,state = ?,code = ? where uid = ?";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
Object[] params = {user.getUsername(),user.getPassword(),user.getName(),user.getEmail(),user.getTelephone(),user.getBirthday(),user.getSex(),user.getState(),user.getCode(),user.getUid()};
System.out.println("code="+user.getUid());
qr.update(sql, params);
}
@Override
public User activeUser(String code) throws SQLException {
String sql = "select * from user where code=?";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql,new BeanHandler<User>(User.class),code);
}
4、/jsp/login.jsp
获取到注册成功的提示信息
USER LOGIN加:
<div><label style="color: red;">${msg }</label></div>
5、由于info.jsp已经实现过,不需要再设置info.jsp中内容
原理如下:
实现登录前,要先修改Index中登录功能的请求路径:
*_ /jsp/index.jsp 修改登录链接
登录
*UserServlet__>loginUI
return “/jsp/login.jsp”;
步骤实现:
1、准备工作 /jsp/login.jsp
设置form标签action,method
设置表单下input标签的name属性
2、User_userLogin
*获取数据
*调用业务层功能
*成功,session存放用户信息,重定向到首页
*失败,request放入失败信息,转发到登录页面
//UserServlet
public String userLogin(HttpServletRequest request, HttpServletResponse response) throws Exception{
//获取用户的账号密码并设置用户数据
request.setCharacterEncoding("utf-8");
User user = new User();
MyBeanUtils.populate(user, request.getParameterMap());
//调用业务层的登录功能
UserService service = new UserServiceImpl();
User user02 = null;
try {
user02 = service.userLogin(user);
//用户登录成功,将用户信息放入session
request.getSession().setAttribute("userinfo", user02);
response.sendRedirect("index.jsp");
return null;
} catch (Exception e) {
//用户登录失败,弹出失败信息
String msg = e.getMessage();
System.out.println(msg);
//向request中放入失败的信息
request.setAttribute("msg", msg);
return "/jsp/login.jsp";
}
}
3、service_dao
PS: service:自定义异常向servlet传递2种数据(密码不存在,用户未激活)
//UserServiceImpl
@Override
public User userLogin(User user) throws SQLException {
//实现登录功能,可以利用异常在模块之间传递数据
UserDao dao = new UserDaoImpl();
User uu = dao.userLogin(user);
if(uu==null){
throw new RuntimeException("密码有误!");
}else if(uu.getState()==0){
throw new RuntimeException("用户未激活!");
}else{
return uu;
}
}
//UserDaoImpl
@Override
public User userLogin(User user) throws SQLException {
String sql = "select * from user where username = ? and password = ?";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql, new BeanHandler<User>(User.class),user.getUsername(),user.getPassword());
}
4、/jsp/index.jsp 获取到了用户信息
<c:if test="${empty userinfo}">
<li><a href="${pageContext.request.contextPath}/UserServlet?method=loginUI">登录</a></li>
<li><a href="${pageContext.request.contextPath}/UserServlet?method=registUI">注册</a></li>
</c:if>
<c:if test="${not empty userinfo}">
<li>欢迎:${userinfo.username} </li>
<li><a href="${pageContext.request.contextPath}/UserServlet?method=logOut">退出</a></li>
<li><a href="${pageContext.request.contextPath}/jsp/cart.jsp">购物车</a></li>
<li><a href="${pageContext.request.contextPath}/jsp/order_list.jsp">我的订单</a></li>
</c:if>
原理如下:
步骤实现:
1、准备工作
/jsp/index.jsp 修改连接
退出
2、UserServlet___>logOut
清除session
重新定向到首页
return null;
//UserServlet
public String logOut(HttpServletRequest request, HttpServletResponse response) throws Exception{
//清楚Session
request.getSession().invalidate();
//重定向到首页
response.sendRedirect("index.jsp");
return null;
}
步骤实现:
1、复制info.jsp___>header.jsp
2、打开/jsp/index.jsp,将页面部分的导航和菜单区域复制到header.jsp
在header.jsp通过tag导入标签库
3、打开其他的所有页面进行替换
4、打开/jsp/index.jsp,将页面部分的底部复制到footer.jsp
5、打开其他的所有页面进行替换
导入代码:
<%@ include file="/jsp/header.jsp" %>
<%@ include file="/jsp/footer.jsp" %>
原理如下:
步骤实现:
1、准备工作(忽略) http://localhost:8080/store_v5/
2、webContent/index.jsp
3、创建分类模块的相关程序
CategoryServlet CategoryService CategoryServiceImp CategoryDao
CategoryDaoImp Category
4、创建IndexServlet
调用业务层获取全部分类数据
将全部分类信息放入request
转发到真实的首页/jsp/index.jsp
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//调用业务层的功能,获取全部的分类信息,返回集合
CategoryService service = new CategoryServiceImpl();
List<Category> cats;
try {
cats = service.getAllCats();
//将集合放入request里,转发到真实的页面
request.setAttribute("category", cats);
} catch (SQLException e) {
e.printStackTrace();
}
return "/jsp/index.jsp";
}
5、CategoryService
@Override
public List<Category> getAllCats() throws SQLException{
CategoryDao dao = new CategoryDaoImpl();
return dao.getAllCats();
}
6、CategoryDao
@Override
public List<Category> getAllCats() throws SQLException {
String sql = "select * from category";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql, new BeanListHandler<Category>(Category.class));
}
7、/jsp/header.jsp 获取全部分类信息,header.jsp中
<c:forEach items="${category }" var="c">
<li><a href="#">${c.cname }</a></li>
</c:forEach>
PS: 由于获取分类要遍历数据,需要用到c:forEach标签,需要导入标签库
弊端:当访问首页是可以看到全部分类信息,但是如果访问其它页面,看不到分类信息
原理如下:
步骤实现:
1、/jsp/header.jsp
当页面加载完毕之后,向服务端发起Ajax请求,服务端经过处理
将所有分类信息以JSON格式的数据返回,客户端获取到返回的所有分类
绑定在页面的显示分类区域
页面底部添加script代码
$.post(url,{},function(data){},”json”){}
2、CategoryServlet -> getAllCats
//调用业务层获取全部分类
//将全部分类转换为JSON格式的数据
//将全部分类信息响应到客户端
//CategoryServlet中
public String getAllCats(HttpServletRequest request, HttpServletResponse response) throws Exception {
//调用业务层的功能,获取全部的分类信息,返回集合
CategoryService service = new CategoryServiceImpl();
List<Category> cats = service.getAllCats();
//将全部分类转换为JSON格式的数据
String json = JSONArray.fromObject(cats).toString();
System.out.println(json); //测试输出
/*将全部分类信息相应到客户端
告诉浏览器本次响应的数据是JSON格式的字符串*/
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(json);
return null;
}
3、调试
观察本次请求,响应网络传输情况
目的:排除2端错误(若网页没接收到数据可能是客户端有误,若接收到的数据有错可能是服务端有误)
4、实现/jsp/header.jsp中AJAX代码的剩余部分(先把ul加一个ID,不然取不到)
弊端:如果用户频繁的访问包含分类信息的页面,每次都要去DB中取获取分类信息,影响性能
<script>
$(function(){
/* 向服务器CategoryServlet->getAllCats发起ajax请求,服务器经过处理,
将所有分类信息以JSON格式的数据返回,获取到返回的所有分类绑定在页面的显示分类区域 */
var url = "/store_v5/CategoryServlet"; //为什么这里要store_v5
var obj = {"method":"getAllCats"};
$.post(url,obj,function(data){
//alert(data); 测试输出
$.each(data, function(i, value) {
$("#cats").append("" +value.cname+"");
});
},"json");
});
</script>
原理如下:
步骤实现:
1、导入jar包(两个jedis关联包)
2、导入JedisUtils工具类(修改参数127.0.0.1)
3、启动windows版本的redis
4、修改CategoryServlet -> findAllCats
*_在redis中获取全部分类信息
*_如果无法获取分类信息,
查询DB中的分类,转换为JSON格式字符串,
将JSON格式字符串向redis缓存一份,之后将JSON格式数据响应到客户端
*_如果可以获取到分类信息
直接响应即可
//CategoryServlet中
public String getAllCats(HttpServletRequest request, HttpServletResponse response) throws Exception {
Jedis jedis = JedisUtils.getJedis();
String json = jedis.get("allCats");
if(null==json){
//调用业务层的功能,获取全部的分类信息,返回集合
CategoryService service = new CategoryServiceImpl();
List<Category> cats = service.getAllCats();
//将全部分类转换为JSON格式的数据
json = JSONArray.fromObject(cats).toString();
jedis.set("allCats", json);
System.out.println(json); //测试输出
System.out.println("Linux服务器中无数据!"); //测试输出
}else{
System.out.println("Linux服务器中有数据!"); //测试输出
}
JedisUtils.closeJedis(jedis);
/*将全部分类信息相应到客户端
告诉浏览器本次响应的数据是JSON格式的字符串*/
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(json);
return null;
}
SQL代码分析:
#查询商品表中最新的9件商品信息
SELECT * FROM product WHERE pflag=0 ORDER BY pdate DESC LIMIT 0 ,9
#查询商品表中最热,最新的9件商品信息
SELECT * FROM product WHERE pflag=0 AND is_hot=1 ORDER BY pdate DESC LIMIT 0 ,9
原理如下:
步骤实现:
1、准备工作(忽略)
2、IndexServlet___>execute
//调用业务层查询最新商品,查询最热商品,返回2个集合
//将2个集合放入到request
//转发到真实的首页
//修改IndexServlet中的代码
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//调用业务层的功能,获取全部的分类信息,返回集合
ProductService service = new ProductServiceImpl();
try {
List<Product> hots = service.getHots();
List<Product> news = service.getNews();
request.setAttribute("hots", hots);
request.setAttribute("news", news);
} catch (SQLException e) {
e.printStackTrace();
}
return "/jsp/index.jsp";
}
3、建立商品模块相关程序
ProductServlet ProductService ProductServiceImp
ProductDao ProductDaoImp Product
//ProductDaoImpl
@Override
public List<Product> getHots() throws SQLException {
String sql = "select * from product where pflag = 0 and is_hot=1 order by pdate desc limit 0,9";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql, new BeanListHandler<Product>(Product.class));
}
@Override
public List<Product> getNews() throws SQLException {
String sql = "select * from product where pflag = 0 order by pdate desc limit 0,9";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql, new BeanListHandler<Product>(Product.class));
}
//ProductServiceImpl
ProductDao dao = new ProductDaoImpl();
@Override
public List<Product> getHots() throws SQLException{
List<Product> hots = dao.getHots();
return hots;
}
@Override
public List<Product> getNews() throws SQLException{
List<Product> news = dao.getNews();
return news;
}
4、调用service,dao
5、/jsp/index.jsp 获取最新/最热9件商品信息
修改index.jsp中热门商品与最新商品的div内容
//热门商品
<c:forEach items="${hots }" var="h">
<div class="col-md-2" style="text-align:center;height:200px;padding:10px 0px;">
<a href="product_info.jsp">
<img src="${h.pimage }" width="130" height="130" style="display: inline-block;"></a>
<p>
<a href="product_info.jsp" style='color:#666'>${h.pname }</a></p>
<p>
<font color="#E4393C" style="font-size:16px">¥${h.shop_price }</font></p>
</div>
</c:forEach>
//最新商品
<c:forEach items="${news }" var="n">
<div class="col-md-2" style="text-align:center;height:200px;padding:10px 0px;">
<a href="product_info.jsp">
<img src="${n.pimage }" width="130" height="130" style="display: inline-block;"></a>
<p>
<a href="product_info.jsp" style='color:#666'>${n.pname }</a></p>
<p>
<font color="#E4393C" style="font-size:16px">¥${n.shop_price }</font></p>
</div>
</c:forEach>
原理如下:
步骤实现:
1、准备工作 /jsp/index.jsp修改连接
修改index.jsp中有关商品图片或者商品名跳转的超链接
2、ProductServlet___>findProductByPid
//获取商品pid
//根据商品pid查询商品信息
//将获取到的商品放入request
//转发到/jsp/product_info.jsp
public String findProductByPid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取传递过来的参数(商品pid)
String pid = request.getParameter("pid");
//调用业务层的方法(根据pid查信息)
ProductService service = new ProductServiceImpl();
Product product;
try {
product = service.findProductByPid(pid);
//System.out.println(product); 测试输出
//将获取到的商品放入request
request.setAttribute("product", product);
} catch (SQLException e) {
e.printStackTrace();
}
//转发到/jsp/product_info.jsp
return "/jsp/product_info.jsp";
}
3、ProductService -> ProductDao
//ProductDaoImpl添加方法
@Override
public Product findProductByPid(String pid) throws SQLException {
String sql = "select * from product where pid = ?";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql, new BeanHandler<Product>(Product.class),pid);
}
//ProductServiceImpl添加方法
@Override
public Product findProductByPid(String pid) throws SQLException {
return dao.findProductByPid(pid);
}
4、/jsp/product_info.jsp
修改顶部标签、商品(图片、编号、价格、描述)
Web项目基础中基础: CRUD、ajax、分页、下载、上传
SQL代码分析:
SELECT * FROM product
#约定 每页显示5条数据
SELECT * FROM product LIMIT 0 , 5
SELECT * FROM product LIMIT 5 , 5
SELECT * FROM product LIMIT 10 , 5
SELECT * FROM product LIMIT 15 , 5
第几天页(当前页) 起始值 每页数据大小
1 0 5
2 5 5
…
结论:
1、(当前页-1)*(每页数量)=起始值
2、要想实现分页,向服务端发起请求的时候,必须传递当前页
原理如下:
步骤实现:
1、创建Page类对象
public class Page {
private List<Product> list;
private int curPage,totalPage,maxNum;
public int getMaxNum() {
return maxNum;
}
public void setMaxNum(int maxNum) {
this.maxNum = maxNum;
}
public List<Product> getList() {
return list;
}
public void setList(List<Product> list) {
this.list = list;
}
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
@Override
public String toString() {
return "Page [list=" + list + ", curPage=" + curPage
+ ", totalPage=" + totalPage + "]";
}
public Page() {
}
public Page(List<Product> list, int startPage, int endPage, int curPage, int totalPage) {
super();
this.list = list;
this.curPage = curPage;
this.totalPage = totalPage;
}
}
2、ProductServlet中添加findAllProduct方法
这里的curPage第一次可能为空,所以要判断
public String findAllProduct(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取参数(当前页面)
System.out.println("调用到了这里");
String curPage = request.getParameter("curPage");
if(curPage==null)curPage="1"; //设置一个默认值
System.out.println(curPage);
int cpage = Integer.parseInt(curPage);
//调用业务层的方法(根据pid查信息)
ProductService service = new ProductServiceImpl();
Page page = null;
try {
page = service.findAllProduct(cpage);
//System.out.println(product); 测试输出
//将获取到的商品放入request
request.setAttribute("page", page);
} catch (SQLException e) {
e.printStackTrace();
}
return "/jsp/product_list_COPY.jsp";
}
3、ProductServiceImpl、ProductDaoImpl分别添加对应方法
//ProductServiceImpl
@Override
public Page findAllProduct(int cpage) throws SQLException {
Page page = new Page();
int maxNum = dao.getMaxNum();
page.setMaxNum(maxNum);
int totalPage = (maxNum/12)+1;
if(maxNum%12==0)totalPage-=1;
page.setTotalPage(totalPage);
page.setCurPage(cpage);
page.setList(dao.findAllProduct((cpage-1)*12));
return page;
}
//ProductDaoImpl
@Override
public int getMaxNum() throws SQLException {
String sql = "select count(*) from product";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
Long num = (Long) qr.query(sql, new ScalarHandler());
return num.intValue();
}
@Override
public List<Product> findAllProduct(int num) throws SQLException {
String sql = "select * from product limit ?,12";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql, new BeanListHandler<Product>(Product.class),num);
}
4、header.jsp中把首页的超链接改成ProductServlet
首页
5、实现product_list_COPY.jsp中的分页功能
//显示分页商品信息
<c:forEach items="${page.list }" var="p">
<div class="col-md-2">
<a href="ProductServlet?method=findProductByPid&pid=${p.pid}">
<img src="${pageContext.request.contextPath}/${p.pimage}" width="170" height="170" style="display: inline-block;">
</a>
<p><a href="ProductServlet?method=findProductByPid&pid=${p.pid}" style='color:green'>${p.pname}</a></p>
<p><font color="#FF0000">商城价:¥${p.shop_price}</font></p>
</div>
</c:forEach>
//实现分页功能
<c:if test="${page.curPage!=1 }">
<li><a href="${pageContext.request.contextPath}/ProductServlet?method=findAllProduct&curPage=${page.curPage-1}" aria-label="Previous"><span aria-hidden="true">«</span></a></li>
</c:if>
<c:forEach begin="1" end="${page.totalPage }" var="i">
<c:if test="${page.curPage== i }">
<li><a>${i }</a></li>
</c:if>
<c:if test="${page.curPage!= i }">
<li><a href="${pageContext.request.contextPath}/ProductServlet?method=findAllProduct&curPage=${i }">${i }</a></li>
</c:if>
</c:forEach>
<c:if test="${page.curPage!=page.totalPage }">
<li>
<a href="${pageContext.request.contextPath}/ProductServlet?method=findAllProduct&curPage=${page.curPage+1}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</c:if>
实现小结:
1、第一次进入页面的时候不会有curPage的参数,所以要判断null的情况
2、Page对象中的List专门存储了查询的Product对象
3、分页查询的代码要掌握,Limit x,y(x都是从0开始)
4、若query方法返回的不是类对象,整形数据用ScalarHandler,先转为Long类型,再用intValue获取int值
5、若想使用Ajax来调用Servlet的request存值并返回页面取值。这是不可能的,因为Ajax函数一般是在页面加载完成后再调用,所以要借助index.jsp来间接跳转
6、分页功能的JSTL代码要熟练书写