参考《JavaWeb开发实战经典》
MVC是核心,是最重要的基础!
“有不少人一直问,是不是应该把框架(Struts、Spring、Hibernate等成为开发框架)开发作为学习重点,其实:框架只是一种很简单的应用,而整个JavaEE的核心并不在框架上,更多的是在MVC设计模式的应用上”。
所谓“基础不牢,地动山摇”,只要真正掌握了内部核心原理(本质:MVC),再去学习任何一门框架都能很快上手!有兴趣的可以去看下这本书,个人感觉这本书入门JavaWeb相当不错!
进入正题,以下对书中的一个MVC登陆实例进行讲解。
在讲解实例前先简单介绍下web开发模式,在web开发模式中主要有两种:Mode1与ModeII (MVC)。
Mode1
Mode1就是指在开发模式中将显示层、控制层、数据层的操作统一交给JSP或JavaBean来处理。类似于JSP+DAO的开发模式(优缺点这里就不说了,网上有很多资料啦)。
ModeII:Model-View-Control
在ModeII中所有的开发都是以Servlet为主体展开的,由Servlet接收所有的客户端请求,然后根据请求调用相应的JavaBean,并将所有的显示结果交给JSP完成,也就是俗称的MVC设计模式。
MVC是一个设计模式,它强制性地使应用程序的输入、处理和输出分开。
显示层(View):主要负责接收Servlet传递的内容,并且调用JavaBean,将内容显示给用户。
控制层(Controller): 主要负责所有的用户请求参数,判断请求参数是否合法,根据请求的类型调用JavaBean执行操作并将最终的处理结果交由显示层进行显示。
模型层(Model): 完成一个独立的业务操作组件,一般都是以JavaBean或者EJB的形式进行定义的。
下面进行MVC登陆实例讲解(环境:Tomcat+MySQL)
1.在数据库中创建user表
User表结构
数据库创建脚本如下:
/*======================= 使用MLDN数据库 =======================*/
USE mldn ;
/*======================= 删除user数据表 =======================*/
DROP TABLE IF EXISTS user ;
/*======================= 创建user数据表 =======================*/
CREATE TABLE user(
userid VARCHAR(30) PRIMARY KEY ,
name VARCHAR(30) NOT NULL ,
password VARCHAR(32) NOT NULL
) ;
/*======================= 插入测试数据 =======================*/
INSERT INTO user (userid,name,password) VALUES ('admin','administrator','admin') ;
2.定义VO类——User.java
定义登陆所需属性:userid、name、password,并设置相应setting与getting方法
package org.lxh.mvcdemo.vo ;
public class User {
private String userid ;
private String name ;
private String password ;
public void setUserid(String userid){
this.userid = userid ;
}
public void setName(String name){
this.name = name ;
}
public void setPassword(String password){
this.password = password ;
}
public String getUserid(){
return this.userid ;
}
public String getName(){
return this.name ;
}
public String getPassword(){
return this.password ;
}
}
3.定义JDBC数据库操作类——DatabaseConnection.java
提供数据库的连接与关闭操作
package org.lxh.mvcdemo.dbc ;
import java.sql.* ;
public class DatabaseConnection {
private static final String DBDRIVER = "org.gjt.mm.mysql.Driver" ;
private static final String DBURL = "jdbc:mysql://localhost:3306/mldn" ;
private static final String DBUSER = "root" ;
private static final String DBPASSWORD = "mysqladmin" ;
private Connection conn = null ;
public DatabaseConnection() throws Exception{
try{
Class.forName(DBDRIVER) ;
this.conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD) ;
}catch(Exception e){
throw e ;
}
}
public Connection getConnection(){
return this.conn ;
}
public void close() throws Exception{
if(this.conn != null){
try{
this.conn.close() ;
}catch(Exception e){
throw e ;
}
}
}
}
4.定义DAO接口——IUserDAO.java
由于本程序的核心功能只是用户的登陆验证,所以在定义DAO接口时,只需定义一个登陆验证方法即可findLogin(),当然需要扩展只需在此接口定义相应方法即可(CRUD)。
package org.lxh.mvcdemo.dao ;
import org.lxh.mvcdemo.vo.User ;
public interface IUserDAO {
// 现在完成的是登陆验证,那么登陆操作只有两种返回结果
public boolean findLogin(User user) throws Exception ;
}
现在的方法主要是用来查询操作,并且采用findXxx()的命名形式,下面分别定义实现类(真实主题类)和代理类。
5.定义DAO实现类——UserDAOImpl.java
实现DAO接口的findLogin方法,对数据库的操作
package org.lxh.mvcdemo.dao.impl ;
import org.lxh.mvcdemo.vo.User ;
import org.lxh.mvcdemo.dbc.* ;
import org.lxh.mvcdemo.dao.* ;
import java.sql.* ;
public class UserDAOImpl implements IUserDAO {
private Connection conn = null ;
private PreparedStatement pstmt = null ;
public UserDAOImpl(Connection conn){
this.conn = conn ;
}
public boolean findLogin(User user) throws Exception{
boolean flag = false ;
String sql = "SELECT name FROM user WHERE userid=? AND password=?" ;
this.pstmt = this.conn.prepareStatement(sql) ;
this.pstmt.setString(1,user.getUserid()) ;
this.pstmt.setString(2,user.getPassword()) ;
ResultSet rs = this.pstmt.executeQuery() ;
if(rs.next()){
user.setName(rs.getString(1)) ; // 取出一个用户的真实姓名
flag = true ;
}
this.pstmt.close() ;
return flag ;
}
}
6.定义DAO代理操作类——UserProxy.java
取得数据库连接,调用真实主题类
package org.lxh.mvcdemo.dao.proxy ;
import org.lxh.mvcdemo.vo.User ;
import org.lxh.mvcdemo.dbc.* ;
import org.lxh.mvcdemo.dao.* ;
import org.lxh.mvcdemo.dao.impl.* ;
import java.sql.* ;
public class UserDAOProxy implements IUserDAO {
private DatabaseConnection dbc = null ;
private IUserDAO dao = null ;
public UserDAOProxy(){
try{
this.dbc = new DatabaseConnection() ;
}catch(Exception e){
e.printStackTrace() ;
}
this.dao = new UserDAOImpl(dbc.getConnection()) ;
}
public boolean findLogin(User user) throws Exception{
boolean flag = false ;
try{
flag = this.dao.findLogin(user) ; // 调用真实主题,完成操作
}catch(Exception e){
throw e ;
}finally{
this.dbc.close() ;
}
return flag ;
}
}
7.定义工厂类——DAOFactory.java
调用DAO接口,返回代理类
package org.lxh.mvcdemo.factory ;
import org.lxh.mvcdemo.dao.* ;
import org.lxh.mvcdemo.dao.proxy.* ;
public class DAOFactory {
public static IUserDAO getIUserDAOInstance(){
return new UserDAOProxy() ;
}
}
DAO的操作完成只是数据层的操作,下面需要编写Servlet类(控制层),在Servlet中接收客户端发来的输入数据,同时需要调用DAO,并且根据DAO的结果返回相应的信息。
8.定义Servlet——LoginServlet.java
(1)通过request.getParameter()方法接收用户请求发送过来的userid与userpass两个参数
(2)对两个参数进行非空验证,若为空,则在info类集对象中添加相应错误信息;当验证通过后,程序将调用DAO进行数据层的验证,并根据DAO的返回结果来决定返回给客户端的信息;
(3)使用反射机制通过工厂类取得代理类实例,然后调用真实主题类的findLogin()方法,进行数据库的验证(判断登录用户是否数据库user表中的用户id与密码一致),并将相应成功或错误信息添加到info对象中;
(4)通过req.setAttribute(“info”,info) ;将最终响应信息request范围中;
(5)通过forward()方法跳转回相应的JSP(String path = “login.jsp” ;)进行显示
package org.lxh.mvcdemo.servlet ;
import java.io.* ;
import java.util.* ;
import javax.servlet.* ;
import javax.servlet.http.* ;
import org.lxh.mvcdemo.factory.* ;
import org.lxh.mvcdemo.vo.* ;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
String path = "login.jsp" ;
String userid = req.getParameter("userid") ;
String userpass = req.getParameter("userpass") ;
List info = new ArrayList() ; // 收集错误
if(userid==null || "".equals(userid)){
info.add("用户id不能为空!") ;
}
if(userpass==null || "".equals(userpass)){
info.add("密码不能为空!") ;
}
if(info.size()==0){ // 里面没有记录任何的错误
User user = new User() ;
user.setUserid(userid) ;
user.setPassword(userpass) ;
try{
if(DAOFactory.getIUserDAOInstance().findLogin(user)){
info.add("用户登陆成功,欢迎" + user.getName() + "光临!") ;
} else {
info.add("用户登陆失败,错误的用户名和密码!") ;
}
}catch(Exception e){
e.printStackTrace() ;
}
}
req.setAttribute("info",info) ;
req.getRequestDispatcher(path).forward(req,resp) ;
}
public void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
this.doGet(req,resp) ;
}
}
9.Servlet配置文件web.xml
Welcome to Tomcat
Welcome to Tomcat
login
org.lxh.mvcdemo.servlet.LoginServlet
login
/mvclogin/LoginServlet
10.显示层JSP——login.jsp
用户登录界面以及接收响应信息
<%@ page contentType="text/html" pageEncoding="GBK"%>
<%@ page import="java.util.*"%>
www.mldnjava.cn,MLDN高端Java培训
<%
request.setCharacterEncoding("GBK") ;
%>
<%
List info = (List) request.getAttribute("info") ;
if(info != null){ // 有信息返回
Iterator iter = info.iterator() ;
while(iter.hasNext()){
%>
<%=iter.next()%>
<%
}
}
%>
11.配置web.xml
Welcome to Tomcat
Welcome to Tomcat
login
org.lxh.mvcdemo.servlet.LoginServlet
login
/mvclogin/LoginServlet
最终运行结果如下:
注:通过本MVC程序,与最初JSP开发(如JSP+JDBC或JSP+DAO)相比,现在的JSP页面中的代码减少了很多,只是简单地完成了输出,实际上在开发中,读者一定要记住JSP中最好只包含以下3中类型的代码(可以对照上面login.jsp代码):
1)接收属性:接收从Servlet传递过来的属性;
2)判断语句:判断传递到JSP中的属性是否存在;
3)输出内容:使用迭代或者VO进行输出。
而且要记住一点:在JSP页面中唯一允许导入的包只能是java.util包,只要把握这一点,即可开发出一个简洁、清晰的JSP页面。
完整代码.rar