(jsp入门&mvc&案例)

一、学习目标

  1. 阐述什么是JSP及其运行原理
  2. 阐述JSP中如何嵌入脚本元素以及软件开发模式的发展历程
  3. 解决开发中的路径问题:相对路径与绝对路径
  4. 阐述请求转发和重定向的区别(面试重点)
  5. 完成案例开发的准备工作:数据库、环境搭建、jar包
  6. 完成登录功能的分析与代码实现(重点)
  7. 完成记录登录成功人数功能分析与代码实现(重点)

JSP的概述

什么是JSP

JSP:Java Server Pages (Java服务器端页面),其实就在HTML中嵌入Java代码。

为什么学习JSP

SUN公司提供了动态网页开发技术:Servlet。Servlet自身有一些缺点,SUN公司发现了这些问题,推出了一个新的动态网页开发技术JSP。

Servlet的缺点:

  • Servlet需要进行配置,不方便维护
  • Servlet很难向网页中输出HTML页面内容

JSP的运行原理

JSP的简单使用

创建一个JSP页面

运行JSP

JSP需要发布到服务器中才可以运行的。

  • 发布项目到Tomcat中
  • 访问JSP页面

JSP的运行原理

JSP文件翻译成Java文件,将这个Java文件编译生成class文件,运行class文件。

JSP的脚本元素

什么是JSP的脚本元素

JSP = HTML + Java代码 + JSP自身东西

JSP的脚本元素就是在JSP中嵌入Java代码。

JSP的脚本元素的分类

声明标签

  • 语法:
    • <%! 变量或方法声明 %>
    • 写在这个脚本中的代码,翻译成Servlet内部的成员变量或成员方法。
  • 用法:

表达式标签

  • 语法:
    • <%= 表达式 %>
    • 写在这个脚本中的代码,翻译成方法内部的out.print();当中的内容。
  • 用法:

程序代码标签

  • 语法:
    • <% 程序代码 %>
    • 写在这个脚本中的代码,翻译成方法内部的局部变量或方法内部代码片段。
  • 用法:

JSP的开发模式之MVC模式

JSP开发模式

动态网页开发模式的发展

开发中的路径问题

路径问题描述

什么时候会遇到路径问题

提供一些页面,在页面中会提供链接或者表单,当点击链接或者表单的时候需要进行提交,提交到Servlet中。从页面向Servlet发送请求的地址(路径)应该如何编写。

路径的分类

相对路径

  • 相对路径的写法:
    • 相对路径不是以 / 开头的。
  • 相对路径的使用:
    • 在跟路径下的页面访问Servlet

demo2.jsp的访问路径:

http://localhost:8080/web02/demo2.jsp

ServletDemo1的访问路径:

http://localhost:8080/web02/ServletDemo1

    • 在某个目录下的页面访问Servlet

demo2.jsp的访问路径:

http://localhost:8080/web02/demo2/demo2.jsp

ServletDemo1的访问路径:

http://localhost:8080/web02/ServletDemo1

绝对路径(通常)

  • 绝对路径的写法:
    • 通常以 / 开始的路径

使用绝对路径,不需要关心当前文件和要请求的文件的相对位置的关系!!!

  • 注意:
    • 绝对路径分成服务器端路径和客户端路径
    • 客户端路径 需要带工程名
    • 服务器端路径 不需要带工程名

案例

案例需求

案例需求描述

提供登录页面,用于用户登录(用户名和密码需要查询数据库)。如果登录失败,需要回到登录页面(给出提示信息)。如果登录成功,页面进行跳转,在成功页面上显示登录成功的总人数。

案例流程分析

Request作为域对象存取数据

Request作为域对象作用范围

Request对象其实就是从客户端浏览器向服务器发送的一次请求信息的封装。那么实质上向Request中所保存的数据有效期也是一次请求范围。

一次请求范围:从客户端浏览器向服务器发送一次请求,服务器针对这次请求对浏览器作出响应。当服务器作出响应之后,请求对象就销毁了,保存在其中的数据就无效了。

请求转发和重定向完成页面跳转

请求转发

请求转发的写法

通过ServletRequest对象获得RequestDispatcher对象。

再根据RequestDispatcher中的方法进行请求转发。

请求转发的代码实现

请求转发的效果

重定向

重定向的写法

通过HttpServletResponse对象中的以下方法实现重定向

重定向的代码实现

重定向的效果

请求转发和重定向区别

请求转发和重定向原理

请求转发和重定向区别总结

  • 请求转发是一次请求一次响应,而重定向是两次请求两次响应。
  • 请求转发地址栏不会变化的,重定向地址栏发生变化。
  • 请求转发路径不带工程名,重定向需要带工程名路径。
  • 请求转发只能在本网站内部,重定向可以定向到任何网站。

代码演示请求转发和重定向区别

  • 注意:

如果需要使用request进行值传递,需要通过请求转发完成。如果页面需要跳转到其他网站上必须使用重定向。

MVC在案例中的应用

案例准备-创建数据库

创建数据库

建表语句

create database web02_login;

use web02_login;

create table user(

uid int primary key auto_increment,

username varchar(20),

password varchar(20),

nickname varchar(20)

);

insert into user values (null,'zs','123','张三');

insert into user values (null,'ls','123','李四');

insert into user values (null,'ww','123','王五');

案例准备项目环境搭建

项目环境搭建

创建web项目

创建相关的包结构

案例准备引入相关资源

引入相关资源

引入相关的jar包:

  • MySQL数据库驱动包
  • C3P0连接池所需jar包
  • DBUtils开发的jar包

引入C3P0配置文件

将配置文件放到工程的src下即可

<?xml version="1.0" encoding="UTF-8"?><c3p0-config>    <default-config>        <property name="driverClass">com.mysql.jdbc.Driver</property>        <property name="jdbcUrl">jdbc:mysql:///u1</property>        <!--注意数据库表的路径及名称-->        <property name="user">root</property>        <property name="password">123</property>                <property name="initialPoolSize">5</property>        <property name="minPoolSize">5</property>        <property name="maxPoolSize">20</property>    </default-config>     </c3p0-config>

案例准备创建登录页面

创建登录页面

登录页面实现

<form action="/web02_login/LoginServlet" method="post">    <table border="1" width="400">        <tr>            <td>用户名</td>            <td><input type="text" name="username"/></td>        </tr>        <tr>            <td>密码</td>            <td><input type="password" name="password"/></td>        </tr>        <tr>            <td colspan="2"><input type="submit" value="登录"/></td>        </tr>    </table></form>

登录页面效果

引入JDBC开发的工具类

案例代码登录代码实现

登录代码实现

登录代码实现流程

登录页面(login.jsp)登录的Servlet(LoginServlet),在这个Servlet中需要接收数据,将这个数据封装到一个JavaBean中,调用另一个JavaBean处理数据。根据处理结果进行页面跳转。

登录代码实现

  • 第一步:在controller包下创建LoginServlet
  • 第二步:在domain下创建一个User类

  • 第三步:在model包下创建一个UserModel类

在这个类中提供一个login的方法

  • 第四步:根据处理结果进行页面跳转

登录的Servlet的业务代码

/** * 登录的Servlet的编写 */public class LoginServlet extends HttpServlet {    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        try{            // 1.接收数据            // 处理中文乱码            request.setCharacterEncoding("UTF-8");            String username = request.getParameter("username");            String password = request.getParameter("password");            // 2.封装数据            User user = new User();            user.setUsername(username);            user.setPassword(password);            // 3.处理数据            UserModel userModel = new UserModel();            User existUser = userModel.login(user);            // 4.页面跳转            if(existUser == null){                // 登录失败                // 向request域中保存一个错误信息:                request.setAttribute("msg", "用户名或密码错误!");                // 使用请求转发进行页面跳转                request.getRequestDispatcher("/login.jsp").forward(request, response);            }else{                // 登录成功                                this.getServletContext().setAttribute("count", count);                // 重定向到成功页面                response.sendRedirect("/web02_login/success.jsp");            }        }catch(Exception e){            e.printStackTrace();            throw new RuntimeException();        }    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        doGet(request, response);    }}

案例代码登录代码底层代码

登录底层代码

处理数据部分代码

public class UserModel {

/** * 处理用户登录的方法: *  * @param user * @return * @throws SQLException */public User login(User user) throws SQLException {    // 连接数据库:通过传入的用户名和密码去数据库中进行查询    QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());    User existUser = queryRunner.query("select * from user where username = ? and password = ?",            new BeanHandler<User>(User.class), user.getUsername(), user.getPassword());    return existUser;}

案例代码登录代码错误信息的回显

登录代码错误信息回显

错误信息回显代码

<!--注意修改编码--><h1>登录页面</h1><%    /**    * 判断request域中是否有错误信息:(第一次进入登录页面的时候,没有错误信息)    * * 如果有错误信息:显示错误信息    */    String msg = "";    if(request.getAttribute("msg") != null){        // 有错误信息:显示错误信息:        msg = (String)request.getAttribute("msg");    }%><h3><font color="red"><%= msg %></font></h3>

错误信息显示效果

案例代码记录登录成功人数分析

记录登录成功的人数分析

画图分析

案例代码记录登录成人数代码实现

记录登录成功人数的代码

完成初始化操作

  • 在服务器启动的时候初始化一个值为零,将这个值存入到ServletContext域中。

/** * 初始化的Servlet * * 将这个Servlet配置成启动时加载 */public class InitServlet extends HttpServlet {    @Override    /**     * 初始化的方法:     */    public void init() throws ServletException {        // 初始一个值为0。        int count = 0;        // 将这个值存入到ServletContext域中。        this.getServletContext().setAttribute("count", count);    }        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        doGet(request, response);    }}
  • 将这个Servlet配置成启动时加载

 <servlet>    <servlet-name>InitServlet</servlet-name>    <servlet-class>com.itheima.controller.InitServlet</servlet-class>    <!-- 配置启动时加载 -->    <load-on-startup>2</load-on-startup>  </servlet>

记录登录成功的人数

// 记录登录成功的人数:                // 将ServletContext中的值取出 +1                int count = (int) this.getServletContext().getAttribute("count");                // 进行了+1的操作                count++;                // 将+1后的值存回到ServletContext中去。

在登录成功页面上显示总人数

<h1>登录成功的页面!</h1><%    Integer count = 0;    // 判断,如果ServletContext中有值,获取并显示:    if(this.getServletContext().getAttribute("count")!=null){        count = (Integer)this.getServletContext().getAttribute("count");    }%><h3>登录成功的总人数:<%= count %></h3></body></html>