禁用Cookie后Session共享数据问题:
解决方案:URL重写
String url = response. encodeRedirectURL(java.lang.String url)
response. sendRedirect(url)
用于对sendRedirect方法后的url地址进行重写。
String url = response.encodeURL(url);
pw.write("<a href='"+url+"'>继续购物</a>");
用于对表单action和超链接的url地址进行重写
防止表单重复提交:
可以在表单提交时候通过设置一个id,在一个servlet中把它存在session中,然后提交的时候在url后面携带一个id参数,在
处理的另一个servlet中取出session中保存的id,判断两个id是否相同,如果相同就把session中的id删除,这样处理的时候,在
提交后后的第二个servlet中刷新的话,session中的id值已经不存在,这时候就提交失败。看下面例子:
第一个servlet:
/** * 用Servlet动态产生表单,且客户端与服务端都有token值 */ public class Demo01A extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { //获取随机值 String token = WebUtil.getToken(); //将随机值绑定到HttpSession域对象中 request.getSession().setAttribute("TOKEN",token); //以下代码是向浏览器输出一个表单 response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.write("<form action='"+request.getContextPath()+"/Demo01B' method='POST'>"); //将随机值绑定在表单隐藏域中 pw.write("<input type='hidden' name='token' value='"+token+"'/>"); pw.write("姓名:<input type='text' name='username'/><br/>"); pw.write("密码:<input type='password' name='password'/><br/>"); pw.write("<input type='submit' value='提交'/>"); pw.write("</form>"); } } /** * 工具类 */ class WebUtil{ private WebUtil(){} public static String getToken(){ //用UUID对象产生唯一的字符串随机值 return UUID.randomUUID().toString(); } }第二个servlet:
/** * 比较客户端和服务端的token值是否相同,相同表示提交成功并删除服务器token值,否则表单重复提交 */ public class Demo01B extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); //获取客户端提交的token值 String tokenClient = request.getParameter("token"); //获取服务端的token值 String tokenServer = (String) request.getSession().getAttribute("TOKEN"); //如果客户端和服务端的token值都存在且相同的话 if(tokenClient!=null && tokenServer!=null && tokenClient.equals(tokenServer)){ //继续再获取姓名和密码 //提交成功 response.getWriter().write("<font style='color:green;font-size:111px'>表单提交成功</font>"); //删除服务端的token值 request.getSession().removeAttribute("TOKEN"); }else{ //表单重复提交 response.getWriter().write("<font style='color:red;font-size:111px'>表单重复提交</font>"); } } }
JSP(Java Server Page)
是原SUN公司开发的一款动态web技术之一
用Servlet来输出表单比较烦麻,难以后期维护,这时就需要一个新的技术来替代Servlet产生表单等UI功能,且又是一种动态
web技术,于是原SUN制定的JSP规则,用于替代Servlet输出UI等相关功能
注意:JSP替代Servlet,JSP和Servlet属于JavaEE规则之一
JSP = HTML(表面) + Servlet(本质)
tomcat/work目录是为jsp定制的,在jsp首次访问时,work目录下会有jsp翻译过来的servlet源码和servlet字节码,从这一点
讲,jsp本质上就是servlet,只是表现形式不一样
jsp翻译成servlet后,依然有与servlet相类似的方法,例如:_jspInit(),_jspService(),_jspDestory()每次访问jsp都执行
_jspService()方法,访问几次,就执行几次。
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
通过JspWriter.write()方法输出到客户端的
通过JspWriter.print()方法输出到客户端的
当jsp翻译成servlet源码时,Web服务器会向_jspService()方法传入若干对象给jsp使用,那么这些对象不需要程序员创建,直
接用即可,我们叫其内置对象或隐式对象,JSP难点在于,它所对应的Servlet源码中的对象,可以在JSP页面直接使用,
这一点容易让初学者头痛
M:普通的Java类,完成业务的业务逻辑,例如:获取用户姓名
V:视图,用JSP技术完成,从域对象中获取数据,并显示在浏览器中
C:控制,用于接收客户端请求,调用业务模型,如果有结果的话,将其绑定到域对象中,转发或重定向于视图进行显示
MVC不限于JavaWeb,其它Web都适用。
MVC也能适用于非Web
1_模版元素,即就是可以在JSP中书写HTML,CSS,JS
2_脚本表达式,即向浏览器输出变量或表达式的值,不能用分号结束,例如:<%= str %>
3_脚本片段,可以书写多行java代码,以分号结束,例如:<%int x = 10;%>
4_JSP声明,如果是变量的话,会翻译成Servlet的实例变量如果是方法的话,会翻译成Servlet的成员方法
5_JSP注释,<%----%>是JSP专用的,JSP引擎在翻译成Servlet时,不会将其 翻译到源码中;但如果你用<!---->的话,会被
翻译到Servlet对应的源码中
你可以将多个类似的业务方法,都写在同一个Servlet中,在doPost或doGet中判断,如果是属于find功能,立刻将请求分发到
处理find功能的业务方法中去这样一来,Servlet数量减少了,代理维护起方便
首先是
package shop.domain; /** * 书本对象类 * @author Jam */ public class Book { private Integer id; //书本id private String title; //书本标题 private String url;//书本图片url private Float price; //书本价格 public Book(Integer id, String title, String url, Float price) { this.id = id; this.title = title; this.url = url; this.price = price; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } }
package shop.domain; import java.util.ArrayList; import java.util.List; /** * 购物车类,自带添加,删除商品条目功能 * @author Jam */ public class ShopCar { private List<ShopCarItem> list = new ArrayList<ShopCarItem>(); private Float totalPrice ; public ShopCar() { } public List<ShopCarItem> getList() { return list; } public void setList(List<ShopCarItem> list) { this.list = list; } public Float getTotalPirce() { Float sum = 0.0f; for(ShopCarItem item : list){ sum += item.getTotalPrice(); } totalPrice = sum; return totalPrice; } public void setTotalPirce(Float totalPirce) { this.totalPrice = totalPirce; } public void addBook(Book b,String count){ Integer c = Integer.parseInt(count); for(ShopCarItem item : list){ if(item.getBook().getId() == b.getId()){ //表示购物车已经有该书本,把书本数量+1 item.setNum(item.getNum()+c); return ; } } //如果购物车中没有该书,添加进去 ShopCarItem item = new ShopCarItem(b.getId(),b,c); list.add(item); } public void clearCar(){ list.clear(); } /* * 移除一类图书 */ public void clearItem(String id){ Integer i = Integer.parseInt(id); for(int j=0;j<list.size();j++){ ShopCarItem item = list.get(j); if(item.getBook().getId() == i) { list.remove(j); return ; } } } }
/** * 购物车条目 */ public class ShopCarItem { private Integer id; //图书id private Book book; //图书 private Integer num; //购买数目 private Float totalPrice; //图书项总价 public ShopCarItem(Integer id, Book book, Integer num) { this.id = id; this.book = book; this.num = num; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Book getBook() { return book; } public void setBook(Book book) { this.book = book; } public Integer getNum() { return num; } public void setNum(Integer num) { this.num = num; } public Float getTotalPrice() { totalPrice = book.getPrice() * num; return totalPrice; } }下面是业务逻辑处理对象:
package shop.service; import java.util.List; import shop.domain.Book; import shop.domain.ShopCar; /** * 处理购物车的业务逻辑类 * @author Jam * */ public class BookService { DBService dbService = new DBService(); public BookService(){ } public List<Book> getBookList(){ return dbService.getBookList(); } public void addBook(String id ,ShopCar car,String count){ int id1 = Integer.parseInt(id); //查找出数据库中对应这个id的书 for(Book b: getBookList()){ if(id1 == b.getId()){ car.addBook(b,count); return ; } } } public void clearShopCar(ShopCar car){ car.clearCar(); } public void clearItem(String id,ShopCar car){ car.clearItem(id); } }
package shop.service; import java.util.List; import shop.domain.Book; import shop.domain.ShopCar; /** * 处理购物车的业务逻辑类 * @author Jam * */ public class BookService { DBService dbService = new DBService(); public BookService(){ } public List<Book> getBookList(){ return dbService.getBookList(); } public void addBook(String id ,ShopCar car,String count){ int id1 = Integer.parseInt(id); //查找出数据库中对应这个id的书 for(Book b: getBookList()){ if(id1 == b.getId()){ car.addBook(b,count); return ; } } } public void clearShopCar(ShopCar car){ car.clearCar(); } public void clearItem(String id,ShopCar car){ car.clearItem(id); } }
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ page import="shop.domain.*" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>书本商品列表信息</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link type="text/css" rel="stylesheet" href="css/style.css" /> </head> <body> <h1>欢迎购买</h1> <div class="contain-list"> <% List<Book> list = (List<Book>)request.getAttribute("BOOKLIST"); %> <%for(Book b : list){ %> <div class="list"> <ul> <li><img src="<%=b.getUrl()%>"/></li> <li><%=b.getTitle()%></li> <li><span>数量:</span><input class="count" maxlength="3" type="text" value="1" id="<%=b.getId()+"input"%>"/><span>单价:<%=b.getPrice()%></span></li> <% String url = request.getContextPath()+"/BookServlet?action=addBook&id="+b.getId(); url = response.encodeURL(url); %> <li class="buy"><a id="<%=b.getId()%>" href="<%=url%>">立即购买</a></li> </ul> </div> <%}%> </div> <script type="text/javascript"> <%for(Book b : list){%> document.getElementById("<%=b.getId()%>").onclick = function(){ var inputElement = document.getElementById("<%=b.getId()+"input"%>"); if(inputElement.value.length>0){ if(/[0-9]+/.test(inputElement.value)){ this.href = this.href+"&count="+inputElement.value; } else{ alert("请填入数字"); return false; } }else{ alert("数量不能为空"); return false; } } <%}%> </script> </body> </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <%@ page import="shop.domain.ShopCar" %> <%@ page import="shop.domain.ShopCarItem" %> <%@ page import="java.util.*" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>购物车</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link type="text/css" rel="stylesheet" href="css/style.css" /> </head> <body> <% ShopCar car = (ShopCar) request.getSession().getAttribute("SHOPCAR"); %> <h1>购物车列表</h1> <div class="head"> <% String url = request.getContextPath()+"/BookServlet?action=list"; String urlClear = request.getContextPath()+"/BookServlet?action=clear"; %> <a class="car" href="<%=urlClear%>">清空购物车</a><a class="car" href="<%=url%>">继续购物</a><span>总价:<%=car.getTotalPirce() %></span> </div> <div class="contain-list"> <% for(ShopCarItem item : car.getList()){ %> <div class="list"> <ul> <li><img src="<%=item.getBook().getUrl()%>"/></li> <li><%=item.getBook().getTitle()%></li> <li><span>数量:<%=item.getNum() %></span></li> <li><span>总价:<%=item.getTotalPrice().intValue()%></span></li> <% int bookId = item.getBook().getId(); String removeItemUrl = request.getContextPath()+"/BookServlet?action=clearItem&id="+bookId; %> <li><li class="buy"><a href="<%=removeItemUrl%>">移出购物车</a></li></li> </ul> </div> <%}%> </div> </body> </html>
上面的工程实现了使用session和servlet和jsp结合展示购物列表和购物车页面。