MVC

MVC 引入

只使用servlet的短处

在学习Servlet的中,在实现编辑Hero功能的servlet时,需要根据浏览器提交的id,通过HeroDAO找到对应的Hero,然后在servlet中组织html显示出来。
可以看到这个Servlet不仅要准备数据,还要准备html。 尤其是准备html,可读性非常差,维护起来也很麻烦

        int id = Integer.parseInt(request.getParameter("id"));
  
        Hero hero = new HeroDAO().get(id);
  
        StringBuffer format = new StringBuffer();
        response.setContentType("text/html; charset=UTF-8");
  
        format.append("<!DOCTYPE html>");
  
        format.append("<form action='updateHero' method='post'>");
        format.append("名字 : <input type='text' name='name' value='%s' > <br>");
        format.append("血量 : <input type='text' name='hp'  value='%f' > <br>");
        format.append("伤害: <input type='text' name='damage'  value='%d' > <br>");
        format.append("<input type='hidden' name='id' value='%d'>");
        format.append("<input type='submit' value='更新'>");
        format.append("</form>");
  
        String html = String.format(format.toString(), hero.getName(), hero.getHp(), hero.getDamage(), hero.getId());
  
        response.getWriter().write(html);

仅仅使用JSP的短处

因为在Servlet中编写html有这样的短板,所以索性直接在JSP中开发编辑Hero这个功能
==这时会发现,虽然编写html方便了,但是写java代码不如在Servlet中那么方便 ==

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*,bean.*,java.sql.*"%>
 
<%
    int id = Integer.parseInt(request.getParameter("id"));
    Hero hero = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
     
        Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin");
     
        Statement s = c.createStatement();
     
        String sql = "select * from hero where id = " + id;
     
        ResultSet rs = s.executeQuery(sql);
     
        if (rs.next()) {
            hero = new Hero();
            String name = rs.getString(2);
            float hp = rs.getFloat("hp");
            int damage = rs.getInt(4);
            hero.name = name;
            hero.hp = hp;
            hero.damage = damage;
            hero.id = id;
        }
     
        s.close();
     
        c.close();
     
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     
%>
 
<form action='updateHero' method='post'>
    名字 : <input type='text' name='name' value='<%=hero.getName()%>'> <br>
    血量 :<input type='text' name='hp' value='<%=hero.getHp()%>'> <br>
    伤害: <input type='text' name='damage' value='<%=hero.getDamage()%>'> <br>
    <input type='hidden' name='id' value='<%=hero.getId()%>'>
    <input type='submit' value='更新'>
</form>

结合Servlet和JSP

既然Servlet和JSP都有各自的优势和短板,那么为什么不结合起来扬长避短呢?
HeroEditServlet:只用来从数据库中查询Hero对象,然后跳转到JSP页面

request.setAttribute("hero", hero);

在request中设置hero

request.getRequestDispatcher("editHero.jsp").forward(request, response);

服务端跳转到editHero.jsp,因为是服务端跳转,都属于同一次请求,所以可以在editHero.jsp通过request取出来
editHero.jsp: 不做查询数据库的事情,直接获取从HeroEditServlet传过来的Hero对象,通过EL表达式把request中的hero显示出来

'HeroEditServlet:'
package servlet;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import bean.Hero;
import dao.HeroDAO;
 
public class HeroEditServlet extends HttpServlet {
 
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        int id = Integer.parseInt(request.getParameter("id"));
        Hero hero = new HeroDAO().get(id);
        request.setAttribute("hero", hero);
        request.getRequestDispatcher("editHero.jsp").forward(request, response);
    }
}

editHero.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*,bean.*,java.sql.*"%>
 
<form action='updateHero' method='post'>
    名字 : <input type='text' name='name' value='${hero.name}'> <br>
    血量 :<input type='text' name='hp' value='${hero.hp}'> <br>
    伤害: <input type='text' name='damage' value='${hero.damage}'> <br>
    <input type='hidden' name='id' value='${hero.id}'>
    <input type='submit' value='更新'>
</form>

MVC设计模式

上述例子中结合Serlvet和JSP进行数据的显示,就是一种MVC的思想。

M 代表 模型(Model)
V 代表 视图(View)
C 代表 控制器(controller)

模型是什么呢? 模型就是数据,就是dao,bean
视图是什么呢? 就是网页, JSP,用来展示模型中的数据

控制器是什么? 控制器用来把不同的数据,显示在不同的视图上。 在这个例子的,Servlet就是充当控制器的角色,把Hero对象,显示在JSP上。
控制器的作用就是把不同的数据(Model),显示在不同的视图(View)上。
在这里插入图片描述## MVC 查询

准备Hero类,HeroDAO类(和以前相同)

HeroListServlet

作为控制器的HeroListServlet,其作用就是通过dao获取所有的heros对象,然后放在request中,跳转到listHero.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
 
<table align='center' border='1' cellspacing='0'>
    <tr>
        <td>id</td>
        <td>name</td>
        <td>hp</td>
        <td>damage</td>
        <td>edit</td>
        <td>delete</td>
    </tr>
    <c:forEach items="${heros}" var="hero" varStatus="st">
        <tr>
            <td>${hero.id}</td>
            <td>${hero.name}</td>
            <td>${hero.hp}</td>
            <td>${hero.damage}</td>
            <td><a href="editHero?id=${hero.id}">edit</a></td>
            <td><a href="deleteHero?id=${hero.id}">delete</a></td>
        </tr>
    </c:forEach>
</table>

MVC 分页

准备DAO

在DAO中提供方法分页查询方法:(还是用以前的HeroDAO)

public List<Hero> list(int start, int count) 

start表示开始的个数,count表示取多少条
比如 list(0, 5) , 即表示第一页,每页有5条数据
比如 list(5, 5) , 即表示第二页,每页有5条数据

只显示5条数据

修改HeroListServlet

int start = 0;
int count = 5;
List<Hero> heros = new HeroDAO().list(start, count);

即表示只获取5条数据

下一页 /上一页

HeroListServlet :
下一页:
通过参数获取start,如果浏览器没有传递参数,就设置为0。
根据start,计算next. next的值就是start+count.
然后把next传递给listHero.jsp
上一页:
根据start,计算pre. pre的值就是start-count.
然后把pre传递给listHero.jsp
listHero.jsp
在最后面增加超链

<a href="?start=${next}">[下一页]</a>
<a href="?start=${pre}">[上一页]</a>

start=${pre}//start=${next}从服务器传递过来的pre/next值
通过设置属性pre和next,传给jsp界面

        request.setAttribute("next", next);
        request.setAttribute("pre", pre);
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=UTF-8");
 
        int start = 0;
        int count = 5;
        //当浏览器传递参数时,获取start
        try {
            start = Integer.parseInt(request.getParameter("start"));
        } catch (NumberFormatException e) {
            // 当浏览器没有传参数start时
        }
 
        int next = start + count;
        int pre = start - count;
        request.setAttribute("next", next);
        request.setAttribute("pre", pre);
 
        List<Hero> heros = new HeroDAO().list(start, count);
        request.setAttribute("heros", heros);      request.getRequestDispatcher("listHero.jsp").forward(request, response);
 
    }

listHero.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
 
<table align='center' border='1' cellspacing='0'>
    <tr>
        <td>id</td>
        <td>name</td>
        <td>hp</td>
        <td>damage</td>
        <td>edit</td>
        <td>delete</td>
    </tr>
    <c:forEach items="${heros}" var="hero" varStatus="st">
        <tr>
            <td>${hero.id}</td>
            <td>${hero.name}</td>
            <td>${hero.hp}</td>
            <td>${hero.damage}</td>
            <td><a href="editHero?id=${hero.id}">edit</a></td>
            <td><a href="deleteHero?id=${hero.id}">delete</a></td>
        </tr>
    </c:forEach>
    <tr>
        <td colspan="6" align="center">
            <a href="?start=${pre}">[上一页]</a>
            <a href="?start=${next}">[下一页]</a>
        </td>
    </tr>
</table>

首页/末页

首页只需要修改listHero.jsp:

<a href="?start=0">[首  页]</a>

末页需要在HeroListServlet中计算last,
last需要根据总数total和每页有多少条数据count来计算得出。
同时,还要看total是否能够整除count
假设总数是50,是能够被5整除的,那么最后一页的开始就是45

if (0 == total % count)
  last = total - count;

修改listHero.jsp,在下一页后增加一个超链

<a href="?start=${last}">[末 页]</a>

start=${last} 从服务器传递过来的last值

'listHero.jsp'
    <tr>
        <td colspan="6" align="center">
            <a href="?start=0">[首  页]</a>
            <a href="?start=${pre}">[上一页]</a>
            <a href="?start=${next}">[下一页]</a>
            <a href="?start=${last}">[末 页]</a>
        </td>
    </tr>
'HeroListServlet.java:'
       int start = 0;
        int count = 5;
 
        try {
            start = Integer.parseInt(request.getParameter("start"));
        } catch (NumberFormatException e) {
            // 当浏览器没有传参数start时
        }
 
        int next = start + count;
        int pre = start - count;
 
        int total = new HeroDAO().getTotal();
 
        int last;
        // 假设总数是50,是能够被5整除的,那么最后一页的开始就是45
        if (0 == total % count)
            last = total - count;
        // 假设总数是51,不能够被5整除的,那么最后一页的开始就是50
        else
            last = total - total % count;
 
        request.setAttribute("next", next);
        request.setAttribute("pre", pre);
        request.setAttribute("last", last);
 
        List<Hero> heros = new HeroDAO().list(start, count);
        request.setAttribute("heros", heros);
 
        request.getRequestDispatcher("listHero.jsp").forward(request, response);

边界处理

上一页,下一页有一个问题,
如果在第一页点击上一页,就会看不到数据了,因为在第一页的时候,pre=-5,也就导致传递到serlvet的start=-5;
同样的在最后一页的时候,点击下一页,也有类似的问题。
解决办法是进行边界处理:

pre = pre < 0 ? 0 : pre;

如果pre是负数了,就使用0

next = next > last ? last : next;

如果next大于last,就使用last

'完整HeroListServlet.java'
package servlet;
 
import java.io.IOException;
import java.util.List;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import bean.Hero;
import dao.HeroDAO;
 
public class HeroListServlet extends HttpServlet {
 
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=UTF-8");
 
        int start = 0;
        int count = 5;
 
        try {
            start = Integer.parseInt(request.getParameter("start"));
        } catch (NumberFormatException e) {
            // 当浏览器没有传参数start时
        }
 
        int next = start + count;
        int pre = start - count;
 
        int total = new HeroDAO().getTotal();
 
        int last;
        if (0 == total % count)
            last = total - count;
        else
            last = total - total % count;
 
        pre = pre < 0 ? 0 : pre;
        next = next > last ? last : next;
 
        request.setAttribute("next", next);
        request.setAttribute("pre", pre);
        request.setAttribute("last", last);
 
        List<Hero> heros = new HeroDAO().list(start, count);
        request.setAttribute("heros", heros);
 
        request.getRequestDispatcher("listHero.jsp").forward(request, response);
 
    }
}

套上Bootstrap

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE html>
<script src="https://how2j.cn/study/js/jquery/2.0.0/jquery.min.js"></script>
<link href="https://how2j.cn/study/css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="https://how2j.cn/study/js/bootstrap/3.3.6/bootstrap.min.js"></script>
     
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
 
<script>
$(function(){
    $("a").addClass("btn btn-default btn-xs");
     
});
 
</script>
<table style="width:500px; margin:44px auto" class="table table-striped table-bordered table-hover  table-condensed" align='center' border='1' cellspacing='0'>
    <tr>
        <td>id</td>
        <td>name</td>
        <td>hp</td>
        <td>damage</td>
        <td>edit</td>
        <td>delete</td>
    </tr>
    <c:forEach items="${heros}" var="hero" varStatus="st">
        <tr>
            <td>${hero.id}</td>
            <td>${hero.name}</td>
            <td>${hero.hp}</td>
            <td>${hero.damage}</td>
            <td><a href="editHero?id=${hero.id}">编辑</a></td>
            <td><a href="deleteHero?id=${hero.id}">删除</a></td>
        </tr>
    </c:forEach>
 
</table>
        <nav>
          <ul class="pager">
 
            <li><a href="?start=0">首  页</a></li>
            <li><a href="?start=${pre}">上一页</a></li>
            <li><a href="?start=${next}">下一页</a></li>
            <li><a href="?start=${last}">末  页</a></li>
          </ul>           
        </nav>

MVC 用户是否登录

比如网站提供Hero查询服务,但是前提是用户要登录过才能使用。
如果用户登陆过了,访问listHero,就让用户正常访问,否则就跳转到登陆界面。
这是非常常见的场景,通过使用 session 来实现这个功能。
在处理登录的loginServlet 中使用将用户名保存在session中。
在HeroListServlet 中查看session中是否为空。如果为空,就表示用户没有登陆过,就跳转到登陆页面

在LoginServlet 把验证成功的用户加入到 Session

如果用户输入正确的账号密码,就跳转到 listHero,并且把用户名以"userName"放进session
如果用户输入错误的账号密码,就跳转到 login.html,让用户重新登陆

//添加session
request.getSession().setAttribute("userName", name);
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class LoginServlet extends HttpServlet {
 
    private static final long serialVersionUID = 1L;
 
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String name = request.getParameter("name");
        String password = request.getParameter("password");
 
        if ("admin".equals(name) && "123".equals(password)) {
        //添加session
            request.getSession().setAttribute("userName", name);
            response.sendRedirect("listHero");
        } else {
            response.sendRedirect("login.html");
        }
 
    }
}

在HeroListServlet判断Session中是否有数据

'HeroListServlet.java'里加入以下代码,并且要放在前面,用于检测用户是否登录
String userName = (String) request.getSession().getAttribute("userName");
   if (null == userName) {
   response.sendRedirect("login.html");
   return;
}

从session中取出userName,如果是空,就表示用户没有登录,或者登录已经超过了30分钟。 客户端跳转到login.html,让用户重新登陆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值