Servlet 3

来源:互联网 发布:炒美股用什么软件 知乎 编辑:程序博客网 时间:2024/05/17 23:53

Servlet 程序开发   ———— WEB开发模式: Mode I 与 Mode II

掌握Model I的开发原理

掌握Mode II 的开发原理

两种开发模式为整个WEB 的核心操作,其中以模式二 最为重要,可以这么说,如果可以将模式而 彻底的掌握了。

Mode I

1、Mode I 就是指在开发中讲显示层、控制层、数据层的操作统一交给JSP 或者是JavaBean来进行处理

 

客户端       [ (<——response )(request ——>)]  <————> JSP  <————>JavaBean <————>数据库  

之前的的JavaB的DAO设计模式,实际上在这道程序中可以发现,DAO负责完成数据层的操作,而JSP 负责显示,一个典型的JSP + JavaBean 的开发模式

客户端现在通过访问的Jsp , 调用里面的JavaBean, 而通过JavaBean调用数据库

     在JavaBean 中就包含了有专门负责处理数据的操作,数据层主要是以DAO为主,除了数据之外还包含了业务的处理。

    在整个的开发中本身就存在了一个问题,现在的程序肯定是需要JSP + JavaBean 一起开发完成后才可以使用,此时就可能出现推诿的问题,例如: 美工同志说了,程序必须先写成,我再作美工,程序员说了,你必须先做美工我再写程序,所以,这种的开发本身只适合与较快速的开发,但是后期维护困难,可以发现这种开发之后的代码在JSP文件之中的, Scriptlet代码非常多。


Mode II:  Model - View -Controller (mvc)

   在Mode II 中所以的开发都是以Servlet为主体展开的,由Servlet 接收所有的客户端请求,之后根据请求调用相应的JavaBean, 并将所有的显示结果交给JSP完成,也就是俗称的MVC设计模式

















       Servlet特点: 可以接收用户的请求参数,环科院调用 java程序,而且由于本身就是以java 程序运行的,所以肯定要比JSP性能高很多的,而且安全性也高

       最终Servlet 所以操作的内容都要交给JSP进行显示,这样一来,Servlet 的缺点就避免了

       JavaBean 完成具体的单个的功能: JSP完成显示的功能,而Servlet负责连接JSP和JavaBean

                JSP  ————>  Servlet ————>  JavaBean 。  这种设计非常适合于大型的项目开发,而且维护方便


    MVC有自己的处理流程,实际上最重要的就是输出和跳转的问题了

    而且一定要再次强调,由于所有的内容都是要交给JSP进行显示,那么这个时候最方便的属性范围就是request 属性范围,例如: 以一个雇员列表操作为例,可以发现,JSP中只是负责显示一次即可,而且Servlet 应该负责将所有的一次显示的内容交给JSP 完成,那么最合适的属性范围就是request 范围了,因为之前强调过,能用page(pageContext) 就不要使用request ,能用request 就不要使用session ,能使用session 就不要使用application

     从实际的开发来讲, session 属性范围用于登录验证上使用较多,而request 范围主要的功能就是在MVC 设计模式上,将Servlet 的内容交给JSP显示,而且这种显示在另外一次提交之后属性就消失了。


本章目标

掌握MVC 在实际开发中的应用

掌握MVC完成一个用户登录程序的开发

内容

     登录程序之前已经学习过,是使用JSP + JDBC完成的开发操作, 但是之前的登录程序开发中可以发现有很多问题,就是一个JSP 文件中代码过多了,即便是使用了JSP + JavaBean 的开发模式,其本身也存在JSP 中代码过多的问题

    现在就可以利用MVC设计模式来彻底解决掉这些代码过多的问题了





















在本程序中用户登录信息提交给Servlet 进行接收,Servlet 接收到请求内容后首先对其合法性进行校验(例如: 输入的内容是否为空或者长度是否满足要求等),如果验证失败,则将错误信息传递给登录页显示,如果数据合法,则调用DAO 层完成数据库的验证,根据验证的结构跳转到“登录成功” 或登录失败的页面,在本程序中,为了操作便捷,将登录成功或失败的显示页都统一设置成登录页。

use mydata;drop table user;create table user(userid varchar(30) primary key,name varchar(30) not null,password varchar(30) not null);insert into user(userid,name,password) values ('admin','tom','admin');

只要有异常一定要交给被调用处进行处理

       数据库创建脚本完成之后,那么下面就开始进行程序的开发操作了

       DAO的操作注意是完成数据层的操作,但是下面在MVC设计模式之中,还有Servlet 也很重要,建立一个LoginServlet.java的操作类

     

      在MVC开发中注意,客户端验证和服务器端的验证都需要进行处理的操作

     而且从这道程序中,读者也可以发现这样一个问题,以前的jsp 页面中的代码实在是太多了,但是现在的代码明显比以前少很多,实际上对于一个jsp 页面应该只包含如下的代码

1、通过本MVC程序,读者可以清楚的感觉到,与最初的JSP 开发(例如JSP+JDBC 或者是 JSP+DAO) 相比,现在的JSP 页面中的代码已经减少了很多,只是简单的完成了输出,实际上在开发中,JSP中最好只包含以下三种类型的代码:

       接收属性: 接收从Servlet 传递过来的属性

       判定语句: 判定传递到JSP 中的属性是否存在

       输出内容: 使用迭代或者是VO进行输出

       一定要记住一点, 在JSP 页面中唯一允许导入的包只能是java.util 包,只要能把握住这一点,就可以开发出一 个简洁、清晰的JSP 页面

      一 个好的页面应该不导入任何一个开发包


      明白MVC的实际开发作用,以及:JSP 、Servlet、DAO的各个组成部分的作用。DAO只是负责实际的操作,JSP只是负责显示,Servlet只是负责接收数据,调用JavaBean ,并进行跳转的功能

以下是整个页面程序的代码

package org.gz.mvc.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 password;}}

package org.gz.mvc.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/mydata";private static final String DBUSER = "root";private static final String DBPASSWORD = "root";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(conn != null) {try{conn.close();}catch (Exception e){ throw e;}}}}

package org.gz.mvc.dao;import org.gz.mvc.vo.*;public interface UserDao {//现在完成的的登录验证,那么登录操作只有两种返回结果 (成功|失败)public boolean findLogin(User user) throws Exception ;}

package org.gz.mvc.dao.imp;import org.gz.mvc.vo.*;import org.gz.mvc.dao.*;import org.gz.mvc.dbc.*;import java.sql.*;public class UserDaoImp implements UserDao {private Connection conn = null;private PreparedStatement pstm = null;public UserDaoImp (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.pstm = this.conn.prepareStatement(sql);this.pstm.setString(1,user.getUserid());this.pstm.setString(2,user.getPassword());ResultSet rs = pstm.executeQuery();if(rs.next()) {user.setName(rs.getString(1));   //取出一个用户名的真实姓名flag = true;}this.pstm.close();return flag;}}

package org.gz.mvc.dao.proxy;import org.gz.mvc.vo.*;import org.gz.mvc.dao.*;import org.gz.mvc.dao.imp.*;import org.gz.mvc.dbc.*;import java.sql.*;// 代理类的主要功能是负责关闭public class UserDaoProxy implements UserDao {private DatabaseConnection  dbc = null;private UserDao dao = null;public UserDaoProxy () {try{this.dbc = new DatabaseConnection();}catch (Exception e){e.printStackTrace();}this.dao = new UserDaoImp(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;}}

package org.gz.mvc.factory;import org.gz.mvc.dao.*;import org.gz.mvc.dao.proxy.*;public class UserDaoFactory {public static UserDao getUserDaoInstance() {return new UserDaoProxy();}}

package org.gz.mvc.servlet;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.gz.mvc.factory.*;import org.gz.mvc.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<String> info = new ArrayList<String>();   //收集错误信息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(UserDaoFactory.getUserDaoInstance().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);}}

<%@ page contentType="text/html" pageEncoding="GBK"%><%@ page import="java.util.*"%><html><head> <title>欢迎光临</title></head><body><script language="javascript">function validate(f) {if(!(/^\w[5,15]$/.test(f.userid.value)))  {alert("用户ID必须是5~15!");f.userid.focus();return false;}if(/^\w[5,15]$/.test(f.userpass.value)) {alert("密码必须是5~15!");f.userpass.focus();return false;}}</script><%request.setCharacterEncoding("GBK");%><%List<String> info = (List<String>) request.getAttribute("info");if(info != null) {Iterator<String> iter = info.iterator();while(iter.hasNext()) {%><h3><%=iter.next()%></h3><%}}%><form action="LoginServlet" method="post" onSubmit="return validate(this)">用户ID: <input type="text" name="userid"><br>密  码: <input type="password" name="userpass"><br><input type="submit" value="登录"><input type="reset" value="重置"></form></body></html>

   Servlet and JSP Examples.    </description><servlet><servlet-name>login</servlet-name><servlet-class>org.gz.mvc.servlet.LoginServlet</servlet-class></servlet><servlet-mapping><servlet-name>login</servlet-name><url-pattern>/servletdemo/LoginServlet</url-pattern></servlet-mapping>