应用MVC架构实现项目
目录
-如何保证不添加重复商品到购物车?我们需要重写默认的判断规则。
-获取Servlet的初始化参数
1.获取初始化参数
1>在web.xml中配置Servlet时,可以配置一些初始化参数。而在Servlet中可以通过ServletConfig接口提供的方法来取得这些参数。
<servlet>
<init-param>
<param-name>password</param-name>
<param-value>12345</param-vlaue>
<init-param>
</servlet>
2>在index.jsp中改<a href="servlet/GetInitParameterServlet">获取初始化参数Servlet</a>
3>建一个Servlet,在web.xml中设置初始化参数
4>private String username;
private String password;封装一下
5>在public void init() throws ServletException{
this.setUsername( this.getInitParameter("username"));
this.setPassword( this.getInitParameter("username"));
6>在body中输出设置的名字和密码
this.getUername();
this.getPassword();
Index.jsp
<h1>获取初
始化参数演示案例</h1>
<hr>
<a href="servlet/GetInitParameterServlet">获取初始化参数Servlet</a>
GetInitParameterServlet.java
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GetInitParameterServlet extends HttpServlet {
private String username;//用户名
private String password; //密码
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
/**
* Constructor of the object.
*/
public GetInitParameterServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void init() throws ServletException {
// Put your code here
this.setUsername(this.getInitParameter("username"));
this.setPassword(this.getInitParameter("password"));
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h2>"+"用户名:"+this.getUsername()+"</h2>");
out.println("<h2>"+"密码:"+this.getPassword()+"</h2>");
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
}
Web.xml
<init-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
404错误一般出现在web配置文件上。检查下应用路径是否定义正确,检查url-pattern是否全类名。检查浏览器地址栏是否输入正确。仔细检查大小写单词字母是否不统一。
将 <url-pattern>GetInitParameterServlet</url-pattern>改成
<url-pattern>/servlet/GetInitParameterServlet</url-pattern>
-MVC模式
(Controller,Moderl,View):是软件开发过程中比较流行的设计思想。旨在分离模型、控制、视图。是一种分层思想的体现。浏览器发出一个请求->被控制器(Servlet)所接收->由servlet去实例化一个模型层(通常是javabean层,由javabean层调用数据库层)的对象->由模型层访问数据库层得到的结果可以返回给控制层或者说界面层也可以访问(保存在session中); 控制层获得模型层的反馈结果之后,选择合适的视图给用户呈现 最终给用户一个响应
-Model2模式
大致分为三层
充当模型层的是JavaBean,充当控制层的是Servlet,充当视图层的是JSP。
然后要访问的数据就在数据库层。
工作原理:
首先由JSP页面向控制层提交请求,然后由控制层Servlet实例化一个模型层的对象,或者说是调用一些模型层的功能,然后由模型层访问数据库层(读取数据库),模型层得到结果后再反馈给控制层,控制层根据得到的结果选择给用户呈现不同的页面(跳转到不同的JSP页面)。
-Model1基础:
https://blog.csdn.net/RayMa0305/article/details/81604371
-Model2演示:
-购物车的设计思路:
1. 购买商品的集合,因为含有商品信息和对应的购买数量,应采取“键值对”的集合来存储,所以选择Map. 这里写作 private HashMap<Items,Integer> goods;
2. 添加商品到购物车的方法:Map提供了put()方法来添加键值对,这里写作:goods.put(item, number);
3. 删除购物车内的商品:使用Map的remove()方法,写作:goods.remove(item);
4. 统计购物车的总金额,核心是对Map的遍历。
--->要遍历Map集合,首先要获得关键字Items的集合:Set<Items> keys = goods.keySet();
--->Set集合无法使用for循环来遍历,所以需要迭代器来遍历 :Iterator<Items> it = keys.iterator();
while(it.hasNext())
{
Items i = it.next();
sum+=i.getPrice() * goods.get(i);
}
--->什么时候计算总金额?calTotalprice();当然是添加和删除购物车商品的时候!每一次添加或删除都需要重新计算。
-如何保证不添加重复商品到购物车?我们需要重写默认的判断规则。
1,所有Java类都继承自Object类
2,Object类中有
public int hashCode(){}
public boolean equals(Object obj){}
这两个方法及其他的方法。
在Object类中,equls()方法和==的本质是相同的,都是判断两个引用是否指向同一对象。
String类继承自Object类,但String类重写了equals()方法,
使得:equals()方法的作用是比较两个字符串的内容是否相等;==的作用是比较两个引用是否指向同一个对象;
很多类都重写了equals方法,供自己产生新的定义。
3,在本程序中:Items类继承自Object类,并且重写了equals()方法,不按照父类的比较方法来比较两个对象,使得该方法能够按照程序员自己的意愿来比较两个对象
- 重写Items的hashCode()方法:
return this.getId()+this.getName().hashCode();
如何确定相同商品的返回的hashCose相同?首先,getId()是一个整数,然后getName()是一个字符串,相同字符串的hashCode也相同,所以返回的是相同的值。
- 重写Items的equals()方法。
java中判断两个对象是否相等的规则:
首先,判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等
如果相等,则判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等
我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率。
equals()相等的两个对象,hashcode()一定相等;
equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。
if(this==obj) {
return true;
}
if(obj instanceof Items) {
Items i=(Items)obj;
if(this.getId()==i.getId()&&this.getName().equals(i.getName())) {
return true;
}else {
return false;
}
}else {
return false;
}
3. 重写上述两个方法以后,还要修改addGoodsInCart()方法,不然新添加的重复商品会直接覆盖原有的商品,而数量并没有累加。
if(goods.containsKey(item)) {//如果添加的商品已经存在,则只要对数量进行累加
goods.put(item,goods.get(item)+number);
}else {
goods.put(item, number);
}
-添加商品到购物车的步骤
首先在CartServlet编写两个私有属性String action/ItemsDao idao。
private String action ; //表示购物车的动作 ,add,show,delete
//商品业务逻辑类的对象
private ItemsDAO idao = new ItemsDAO();
idao表示商品要用到的业务逻辑层的对象,比如根据一个编号获取一个商品。
让doGet()做doPost()方法。
在doPost()中,首先判断action的动作,如果不等于空,再判断是否是add,若是,则调用addToCart()方法。
if(request.getParameter("action")!=null)
action表示购物车的动作,包含三种动作:add、show、delete;
接着我们要判断action传的是哪个动作。
this.action = request.getParameter("action");
if(action.equals("add")) //如果是添加商品进购物车
{
if(addToCart(request,response))
{ request.getRequestDispatcher("/success.jsp").forward(request, response); }
else
{ request.getRequestDispatcher("/failure.jsp").forward(request, response);
}在addToCart()方法中,首先获得request传递的商品编号和商品数量,由编号获得商品对象。然后判断是否是第一次给购物车添加商品,若是,则创建新的购物车对象到Session中;如果不是,则从Session直接获取现有的购物车对象,然后调用该对象的addGoodsInCart()方法,如果方法返回为true,则addToCart()也返回true,并在doPost()中跳转到成功的页面,否则跳转到失败的页面。
//添加商品进购物车的方法
private boolean addToCart(HttpServletRequest request, HttpServletResponse response)
{
String id = request.getParameter("id");
String number = request.getParameter("num");
Items item = idao.getItemsById(Integer.parseInt(id));
//是否是第一次给购物车添加商品,需要给session中创建一个新的购物车对象
if(request.getSession().getAttribute("cart")==null)
{
Cart cart = new Cart();
request.getSession().setAttribute("cart",cart);
}
Cart cart = (Cart)request.getSession().getAttribute("cart");
if(cart.addGoodsInCart(item, Integer.parseInt(number)))
{
return true;
}
else
{
return false;
}
js框架lhgdialog,来显示对话框。
<script type="text/javascript" src="js/lhgcore.js"></script>
<script type="text/javascript" src="js/lhgdialog.js"></script>
在detail.jsp中
function selflog_show(id)
{
var num = document.getElementById("number").value;
J.dialog.get({id: 'haoyue_creat',title: '购物成功',width: 600,height:400, link: '<%=path%>/servlet/CartServlet?id='+id+'&num='+num+'&action=add', cover:true});
}
<div id="cart">
<img src="images/buy_now.png"><a href="javascript:selflog_show(<%=item.getId()%>)"><img src="images/in_cart.png"></a><a href="servlet/CartServlet?action=show"><img src="images/view_cart.jpg"/></a>
</div>
-显示购物车
此时如果是显示购物车,则跳转到cart.jsp页面
if(action.equals("show"))//如果是显示购物车
{
request.getRequestDispatcher("/cart.jsp").forward(request, response);
}
在cart.jsp页面需要导入需要的Java类
<%@ page import="entity.Cart" %>
<%@ page import="entity.Items" %>
还有写显示购物车的JSP页面
<%
//首先判断session中是否有购物车对象
if(request.getSession().getAttribute("cart")!=null)
{
%>
<!-- 循环的开始 -->
<%
Cart cart = (Cart)request.getSession().getAttribute("cart");
HashMap<Items,Integer> goods = cart.getGoods();
Set<Items> items = goods.keySet();
Iterator<Items> it = items.iterator();
while(it.hasNext())
{
Items i = it.next();
%>
<tr name="products" id="product_id_1">
<td class="thumb"><img src="images/<%=i.getPicture()%>" /><a href=""><%=i.getName()%></a></td>
<td class="number"><%=i.getPrice() %></td>
<td class="price" id="price_id_1">
<span><%=i.getPrice()*goods.get(i) %></span>
<input type="hidden" value="" />
</td>
<td class="number">
<%=goods.get(i)%>
</td>
<td class="delete">
<a href="servlet/CartServlet?action=delete&id=<%=i.getId()%>" onclick="delcfm();">删除</a>
</td>
</tr>
<%
}
%>
<!--循环的结束-->
</table>
<div class="total"><span id="total">总计:<%=cart.getTotalprice() %>¥</span></div>
<%
}
%>
-实现购物数量的增减按钮
在details.jsp中
<script type="text/javascript">
function selflog_show(id)
{
var num = document.getElementById("number").value;
J.dialog.get({id: 'haoyue_creat',title: '购物成功',width: 600,height:400, link: '<%=path%>/servlet/CartServlet?id='+id+'&num='+num+'&action=add', cover:true});
}
对应上方脚本后下方的调用,写add()和sub()的方法
function add()
{
var num = parseInt(document.getElementById("number").value);
if(num<100)
{
document.getElementById("number").value = ++num;
}
}
function sub()
{
var num = parseInt(document.getElementById("number").value);
if(num>1)
{
document.getElementById("number").value = --num;
}
}
调用οnclick="sub();οnclick="add();
</script>
<td>购买数量:<span id="sub" onclick="sub();">-</span><input type="text" id="number" name="number" value="1" size="2"/><span id="add" onclick="add();">+</span></td>
</tr>
}
-删除购物车
@1.CartServlet.java
public void doPost(){
if(action.equals("delete")) //如果是执行删除购物车中的商品
{
if(deleteFromCart(request,response))
{
request.getRequestDispatcher("/cart.jsp").forward(request, response);
}
else
{
request.getRequestDispatcher("/cart.jsp").forward(request, response);
}
}
}
//从购物车中删除商品
private boolean deleteFromCart()
{
String id = request.getParameter("id");
Cart cart = (Cart)request.getSession().getAttribute("cart");
Items item = idao.getItemsById(Integer.parseInt(id));
if(cart.removeGoodsFromCart(item))
{
return true;
}
else
{
return false;
}
}
@2.cart.jsp
<a href="servlet/CartServlet?action=delete&id=<%=i.getId()%>" οnclick="delcfm();">删除</a>
防止误删操作
<a>标签的的onclick事件是先于跳转之前执行的,同时onclick事件得到一个false就不会跳转了,因此可以作为取消跳转的行为。 window.event.returnValue =false
<script language="javascript">
function delcfm() {
if (!confirm("确认要删除?")) {
window.event.returnValue = false;
}
}
</script>