zoukankan      html  css  js  c++  java
  • java学习笔记-JavaWeb篇一

    JavaWEB篇一

    1 Tomcat的安装和配置
    2 JavaWeb开发的目录结构
    3 使用Eclipse开发JavaWeb项目
    4 第一个Servlet程序
    5 Servlet 的配置及生命周期方法
    6 ServletConfig 对象
    7 ServletContext
    8 HTTP 协议_GET&POST请求
    9 ServletRequest
    10 ServletResponse
    11 GenericServlet
    12 HttpServlet
    13小结及练习
    14 JSP 概述
    15 JSP 页面的 9 个隐含对象
    16 JSP语法
    17 域对象的属性操作
    18 请求的重定向和转发
    19 JSP小结(1)
    20 page指令
    21 include指令
    22 JSP 标签
    23 中文乱码问题
    24 JSP 小结(2)
    25 MVC 设计模式
    26 MVC 案例之查询
    27 MVC 案例之删除
    28 MVC案例之架构分析
    29 MVC案例之DAO层设计
    30 MVC案例之DAO层设计
    31 MVC案例之多个请求
    32 MVC案例之(模糊)查
    33 MVC案例之删除操作
    34 MVC案例之小结(1)
    35 MVC案例之新增Customer
    36 MVC案例之修改思路
    37 MVC案例之修改代码
    38 MVC案例之通过配置
    39 MVC案例之小结(2)
    40 Cookie概述
    41 利用Cookie进行自动登录
    42 利用Cookie显示最近浏览的商品
    43 设置Cookie的作用路径
    44 Cookie小结 

    注意:需要使用已安装web插件的EclipseIDE进行学习,本次学习中选用了Eclipse官方的针对J2EE开发的IDE

    遇到的问题1:在Eclipse中成功启动了Tomcat,但是访问http://127.0.0.1:8080不能成功,需要对tomcat进行一些配置,具体可以参考http://blog.csdn.net/wqjsir/article/details/7169838/

    遇到的问题2:开发javaWeb项目需要新建web工程,新建java project时不能在server(即Tomcat)上运行,即不能run on server

    遇到的问题3:使用JDBC时注意事项

    在web工程中,需要再项目目录lib下拷贝进去java驱动包 名称为mysql-connector-java-5.1.38-bin.jar  在mysql官网可以下载到  另外需要注意连接字符串不能写错(com.mysql.jdbc.Driver),否则会提示找不到类

    排查问题可参考:http://wenku.baidu.com/link?url=6lR6qQcCBcueiL34z8Mqco86Kd9tTa08qnWSBgpTwXreBrVqtksg16BY3XCDn8fwKCoK9348KTryqNo_WgICskV89-X_cZVaLHd7VkNaRLi

    1 Tomcat的安装和配置

    1.部署并启动tomcat服务器

    1). 解压tomcat安装包到一个非中文目录下

    2). 配置一个环境变量 java_home(指向jdk安装的根目录)或jre_home

    3). 通过tomcat安装目录bin目录下的startup.bat,启动服务器

    4). 可以在浏览器中输入localhost:8080来检验Tomcat安装是否正确

    5). 若已经启动了一个Tomcat应用,若再启动同一个Tomcat应用,会抛出异常:

    Java.net.BindException:Addresss aleady in use:JVM_Bind:8080

    端口已经被占用

    2.Tomcat:开源的Servlet容器

    3.可以通过修改server.xml文件中的配置信息来修改Tomcat服务器的端口号:

        <Connector port="8080" protocol="HTTP/1.1"

                   connectionTimeout="20000"

                   redirectPort="8443" />

    把port的值修改为其他的端口号即可

    4. 为了可以在任意目录下启动Tomcat服务器

    4.1 把D:Program Filesapache-tomcat-7.0.37in 添加到path下

    添加成功后,若在任意目录下通过startup其中Tomcat服务器,会有提示:

    The catalina_home environment variable is not defined correctly

    This environment variable is needed to run this program

    即:要求设置CATALINA_HOME这个环境变量

    5. 设置CATALINA_HOME环境变量

    5.1 通过阅读stratup.bat批处理文件,可知CATALINA_HOME环境变量下有一个bin目录,而bin目录下又有一个catalina.bat文件,由此可知CATALINA_HOME指向的应该是Tomcat安装的根目录

    于是吧Tomcat的根目录设为CATALINA_HOME环境变量

    此时既可以在任意目录下用过startup.bat shutdown.bat启动、关闭服务器

    6.继续阅读stratup.bat批处理文件,发现启动Tomcat服务器的是catalina.bat文件

    在命令行窗口直接输入catalina,提示如下:

    commands:

      debug             Start Catalina in a debugger

      debug -security   Debug Catalina with a security manager

      jpda start        Start Catalina under JPDA debugger

      run               Start Catalina in the current window

      run -security     Start in the current window with security manager

      start             Start Catalina in a separate window

      start -security   Start in a separate window with security manager

      stop              Stop Catalina

      configtest        Run a basic syntax check on server.xml

      version           What version of tomcat are you running?

    Catalina命名有如上的可选参数

    Run:在catalina同一个命令行窗口下启动服务器

    Start:开启一个新窗口启动服务器

    Stop:关闭服务器

    2 JavaWeb开发的目录结构

    7.第一个WEB应用程序:开发,并部署到Tomcat服务器下运行

    1). 在Eclipse新建一个Java Project

    2). 在Java项目下创建Web开发的目录结构

    -WebContent

          -WEB-INF

               -classes(编译后的class文件必须放在此目录下)

               -lib

               -web.xml(从D:Program Filesapache-tomcat-7.0.37webappsdocsWEB-INF拷贝过来,可以不做修改)

          HTML页面

          JSP页面

          图片…

    3). 在src下新建一个Person类

    Package com.atguigu.test;

    Public class Person{

    Public String getPersonInfo(){

    Return “Person info…”;

    }

    }

    4). 手工把Person类对应的class文件(含包)复制到classes目录下

    可以通过修改默认的输出目录达到自动把编译好的class放到classes目录下

    5). 在webcontent目录下新建一个JSP文件:

    %@page import="com.xxx.test.Person"%

    <%

        Person p = new Person();

        System.out.print(p.getPersonInfo());

     %>

    6). 把WebContent目录复制到Tomcat的webapps目录下,并改名为:helloword

    7). 在浏览器的地址栏中输入:http://localhost:8080/helloworld/hello.jsp即可看到命令行的打印信息

    8). 配置任意目录下的web应用程序:

    在conf目录下依次创建catalinalocalhost目录,然后在localhost目录下为test这个web应用程序建立test.xml文件,编辑这个文件输入以下内容

    <context

    docBase = “E:\Java\source\atguigu\java-1\firstwebapp\webcontent”

    reloadable = “true”/>

    3使用Eclipse开发JavaWeb项目

    1. 使用JavaEE版的Eclipse开发动态的WEB工程(JavaWEB项目)

    1). 把开发选项切换到JavaEE

    2). 可以在Window->Show View 中找到Package Explorer,并把其拖拽到开发区的左边

    3). 在Servers面板中新建Tomcat服务器,一定要关联到Tomcat安装的根目录

    4). 新建一个Dynamic Web Project。其中Target Runtime 需选择Tomcat6.0

    5). 开发JavaWeb应用

    6).可以通过run on server来运行WEB项目

    4第一个Servlet程序

    2. servlet的HelloWorld

    1). 创建一个Servlet接口的实现类

    Public class HelloServlet implements  Servlet

    2). 在web.xml文件中配置和映射这个Servlet

    <!-- 配置和映射servlet -->

     <servlet>

         <!-- Servlet注册的名字 -->

         <servlet-name> HelloServlet </servlet-name>

         <!-- Servlet的全类名 -->

         <servlet-class>com.centfor.test.HelloServlet</servlet-class>

    <servlet-mapping>

         <!-- 需要和某一个Servlet节点servlet-name子节点的节点文本一致 -->

               <servlet-name> HelloServlet </servlet-name>

         <!-- 映射具体的访问路径:/代表当前Web应用的根目录 -->

               <url-pattern>/Hello</url-pattern>

     </servlet-mapping>

     </servlet>

    3. Servlet容器:运行Servlet、JSP、Filter等的软件环境

    1). 可以来创建Servlet,并调用Servlet的相关生命周期方法

    2). JSP、Filter、Listener、Tag……

    5 Servlet 的配置及生命周期方法

    4. Servlet生命周期的方法:以下方法都由Servlet容器负责调用

    1). 构造器:只被调用一次,只有第一次请求Servlet时,创建Servlet的实例

    这说明Servlet是单实例的!

    2). Init方法:只被调用一次,在创建好实例后立即被调用,用于初始化当前Servlet。

    3). Service:被多次调用,每次请求都会调用service方法,实际用于响应请求的

    4). Destroy: 只被调用一次,在当前Servlet所在的Web应用被卸载前调用,用于释放当前Servlet所占的资源

    5. load-on-startup参数:

    1). 配置在Servlet节点中:

    <!-- 配置和映射servlet -->

    <servlet>

         <!-- Servlet注册的名字 -->

         <servlet-name> HelloServlet </servlet-name>

         <!-- Servlet的全类名 -->

         <servlet-class>com.centfor.test.HelloServlet</servlet-class>

    <!-- 可以指定Servlet被创建的时机 -->

         <load-on-startup>-1</load-on-startup>

    </servlet>

    2). Load-on-startup:可以指定Servlet被创建的时机,若为负数,则在第一次请求时被创建。若为0或正数,则在当前Web应用被Servlet容器加载时创建实例,且数值越小越早被创建。

    6. 关于Servlet-mapping:

    1). 同一个Servlet可以被映射到多个URL上,即多个 <servlet-mapping> 元素的 <servlet-name>子元素的设置值可以是同一个Servlet的注册名。

    2). 在Servlet映射到的URL中也可以使用 * 通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头“/*”结尾。

    <servlet-mapping>

                <servlet-name>secondServlet</servlet-name>

    <url-pattern>/*</url-pattern>

    </servlet-mapping>

    OR

    <servlet-mapping>

               <servlet-name>secondServlet</servlet-name>

    <url-pattern>*.do</url-pattern>

    </servlet-mapping>

    注意:以下的既有/又有扩展名的不合法

    <servlet-mapping>

               <servlet-name>secondServlet</servlet-name>

    <url-pattern>/*.action</url-pattern>

    </servlet-mapping>

    6 ServletConfig 对象

    7. ServletConfig:封装了Servlet的配置信息,并且可以获取ServletContext对象

    1). 配置Servlet

    <!-- 配置和映射servlet -->

     <servlet>

         <!-- Servlet注册的名字 -->

         <servlet-name> HelloServlet </servlet-name>

         <!-- Servlet的全类名 -->

         <servlet-class>com.centfor.test.HelloServlet</servlet-class>

         <!-- 配置Servlet的初始化参数,且节点必须在load-on-startup节点的前边-->

         <init-param>

               <!-- 参数名 -->

               <param-name>user</param-name>

               <!-- 参数值 -->

               <param-value>root</param-value>

         </init-param>

         <init-param>

               <param-name>password</param-name>

               <param-value>123456</param-value>

         </init-param>

          <!-- 可以指定Servlet被创建的时机 -->

         <load-on-startup>-1</load-on-startup>

     </servlet>

    2). 获取初始化参数:

    > getinitparameter(String name):获取指定参数的初始化参数

    > getinitParameterNames():获取参数名组成的Enumeration对象

    String user = servletConfig.getInitParameter("user");

               System.out.println("user:" + user);

              

               Enumeration<String> names = servletConfig.getInitParameterNames();

               while(names.hasMoreElements()){

                     String name = names.nextElement();

                     String value = servletConfig.getInitParameter(name);

                     System.out.println("^^" + name + ":" + value);

               }

    3).获取Servlet的配置名称(了解)

           String servletName = servletConfig.getServletName();

               System.out.println(servletName);

    7 ServletContext

    8. ServletContext

    1). 可以由ServletConfig获取

    ServletContext servletContext = servletConfig.getServletContext();

    2). 该对象代表当前Web应用:可以认为ServletContext是当前Web应用的一个大管家,可以从中获取到当前Web应用的各个方面的信息。

    ① 获取当前Web应用的初始化参数:可以为所有的servlet所获取,而servlet的初始化参数只有那个servlet可以获取

    设置初始化参数:

    <!-- 配置当前Web应用的初始化参数 -->

     <context-param>

         <param-name>driver</param-name>

         <param-value>com.mysql.jdbc.Driver</param-value>

     </context-param>

    方法:

    GetinitParameter

    GetinitParameterNames

    代码:

    //获取ServletContext对象

               ServletContext servletContext = servletConfig.getServletContext();

              

               String driver = servletContext.getInitParameter("driver");

               System.out.println("driver:" + driver);

              

               Enumeration<String> names2 = servletContext.getInitParameterNames();

               while(names2.hasMoreElements()){

                     String name = names2.nextElement();

                     String value = servletContext.getInitParameter(name);

                     System.out.println("^^" + name + ":" + value);

               }

    ② 获取当前Web应用的某一个文件在服务器上的绝对路径,而不是部署前的路径

    GetRealPath(String path);

    代码:

               String realPath = servletContext.getRealPath("/note.txt");

               //不是:F:MyEclipse 10day_0509 ote.txt

               System.out.println(realPath);

    ③ 获取当前Web应用的名称:

    GetContextPath();

    代码:

    String contextPath = servletContext.getContextPath();

               System.out.println(contextPath);

    ④ 获取当前Web应用的某一个文件对应的输入流

    GetResourceAsStream(String path):path的/ 为当前Web应用的根目录

    代码:

    InputStream

    is2 =  servletContext.getResourceAsStream("/WEB-INF/classes/jdbc.properties");

    ⑤ 和attribute相关的几个方法:

    8 HTTP 协议_GET&POST请求

    9.GET请求和POST请求

    1). 使用GET方式传递参数:

    ① 在浏览器地址栏中输入某个URL地址或单击网页上的一个超链接时,浏览器发出的HTTP请求消息的请求方式为GET。

    ② 如果网页中的<form>表单元素的method属性被设置为了“GET”,浏览器提交这个FORM表单时生成的HTTP请求消息的请求方式也为GET。

    ③ 使用GET请求方式给WEB服务器传递参数的格式:

    http://www.lamp  brother.net/counter.jsp?name=lc&password=123

    ④ 使用GET方式传送的数据量一般限制在1KB以下。

    2). 使用POST方式传递参数:

    ① POST请求方式主要用于向WEB服务器端程序提交FORM表单中的数据。

    ② POST方式将各个表单字段元素及其数据作为HTTP消息的实体内容发送给WEB服务器,传送的数据量要比使用GET方式传送的数据量大得多。 

    POST /counter.jsp HTTP/1.1

    Referer: http://localhost:8080/Register.html

    Content-type: application/x-www-form-urlencoded

    Host:localhost:43

    Name=zhangsan&password=123           --请求体中传递参数

    9 ServletRequest

    10.如何在Servlet中获取请求信息:

    1). Servlet的service() 方法用于应答请求:因为每次请求都会调用service()方法

    public void service(ServletRequest request, ServletResponse response)

                     throws ServletException, IOException

    ServletRequest:封装了请求信息,可以从中获取到任何的请求信息。

    ServletResponse:封装了响应信息,如果想给用户什么响应,具体可以使用该接口的方法实现。

    这两个接口的实现类都是服务器给予实现的,并在服务器调用service()方法时传入

    2). ServletRequest:

    ① 获取请求参数:

    String  getParameter(String name):根据请求参数的名字,返回参数

    若请求参数有多个值(例如checkbox),该方法只能读取到第一个提交的值

    String[]    getParameterValues(String name) :根据请求参数的名字,返回请求参数对应的字符串数组

    Enumeration<String>   getParameterNames():返回参数名对应的Enumeration对象,类似于ServletConfg(或ServletContext)的getinitParameterNames()方法

    Map<String,String[]>  getParameterMap():返回请求参数的键值对 key:参数名 value:参数值,String数组类型

    ② 获取请求的URL:

     HttpServletRequest httpServletRequest = (HttpServletRequest)request;

    String requestURL = httpServletRequest.getRequestURL();

    System.out.println(requestURL);

    ③ 获取请求方式:

    String method = httpServletRequest.getMethod();

    System.out.println(method);   //GET

    ④ 若是一个GET请求,获取请求参数对应的那个字符串,即 ? 后的那个字符串

    String queryString = httpServletRequest.getQueryString();

    System.out.println(queryString);

    //user=atguigu&password=123456&interesting=party&interesting=shopping&interesting=game/loginServlet

    ⑤ 获取请求的Servlet的映射路径

    String servletPath = httpServletRequest.getservletPath();

    System.out.println(servletPath);   //loginservlet

    ⑥ 和attribute相关的几个方法

    10 ServletResponse

    3). HttpServletRequest:是ServletRequest的子接口。针对于HTTP请求所定义,里边包含了大量获取Http的信息

    4). ServletResponse:封装了响应信息,如果想给用户什么响应,具体可以使用该接口的方法实现。

    ① *getWriter(): 返回PrintWriter对象,调用该对象的print()方法,将把print()中的参数直接打印到客户的浏览器上

    ② 设置响应的内容类型:response.setConfigType(“application/msword”);

    ③ void sendRedirect(String location):请求的重定向(此方法为HttpServletResponse中定义)

    ---------------------------------习题------------------------------------

    在web.xml文件中设置两个WEB应用的初始化参数,user,password。

    定义一个login.html,里边定义两个请求字段:user,password

    再创建一个LoginServlet,在其中获取请求的user,password。比对其和web.xml文件中定义的请求参数是否一致

    若一致,响应Hello:xxx,若不一致,响应Sorry:xxx     其中xxx为user

    11 GenericServlet

    1.GenericServlet(了解)

    1). 是一个Servlet。是Servlet接口和ServletConfig接口的实现类,但是一个抽象类,其中的service方法为抽象方法

    2). 如果新建的Servlet程序直接继承GenericServlet会使开发更简洁些。

    3). 具体实现:

    ① 在GenericServlet中声明了一个ServletConfig类型的成员变量,在Init(ServletConfig)方法中对其进行了初始化

    ② 利用ServletConfig成员变量的方法实现了ServletConfig接口的方法

    ③ 还定义了一个init()方法,在init(ServletConfig)方法中对其进行调用,子类可以直接覆盖Init(),在其中实现对Servlet的初始化

    ④ 不建议直接覆盖init(ServletConfig),因为如果忘记编写super.init(config);而还是利用了ServletConfig接口的方法,则会出现空指针异常

    ⑤ 新建的init(){}并非Servlet的生命周期方法,而init(ServletConfig)是生命周期相关的方法

    12 HttpServlet

    2.HttpServlet

    1). 是一个Servlet,继承自GenericServlet,针对于Http协议所定制

    2). 在service() 中直接把ServletRequest和ServletResponse转为HttpServletRequest和HttpServletResponse,并调用了重载的service(HttpServletRequest, HttpServletResponse)

    在service(HttpServletRequest, HttpServletResponse)获取请求方式:request.getMethod().根据请求方式又创建了doXxx()方法(xxx为具体的请求方式,如doGet,doPost)

    3). 实际开发中,直接继承HttpServlet,并根据请求方式复写doXxx()方法(主要指doGet或doPost)

    4).好处:直接由针对性的覆盖doXxx()方法;直接使用HttpServletRequest和HttpServletResponse,不再需要强转

    13小结及练习

    3.

    -------------------------------------习题-----------------

    在MySql数据库中创建一个test_users数据表,添加3个字段:id,user,password,并录入几条记录

    定义一个login.html,里边定义两个请求字段:user,password 发送请求到loginServlet

    再创建一个LoginServlet(需要继承自HttpServlet,并重写其doPost方法)

    在其中获取请求的user,password

    利用JDBC从test_users中查询有没有和页面输入的user,password对应的记录

    Select count(id) from test_user where user = ? and password = ?

    若有,响应Hello:xxx,若没有,响应Sorry:xxx     其中xxx为user

    14 JSP 概述

    JSP常见问题:

    ① jsp文件首行报错

    JSP页面顶端出现“红色”的报错信息:The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path。原来Javaweb工程类中没有添加Tomcat运行时相关类导致。
    下面是具体的解决方法:
    1、右击web工程-》属性或Build Path-》Java Build Path->Libraries-> Add Libray...->Server Runtime -》Tomcat Server
    2、切换到Java Build Path界面中的Orader and Export,选择Tomcat。

    注意:
    按以上方法操作时,若打开Server Runtime后一片空白,需要设置Apache服务器。设置方法为:window->Preferences->Server->Runtime Environment -> add --> 选择Apache的版本后点Next,再填入你apache服务器软件的安装(解压后)地址。

    4 请求的转发和重定向:

    1). 本质区别: 请求的转发只发出了一次请求,而重定向则发出了两次请求

    具体:

    ① 请求的转发:地址栏是初次发出请求的地址

    请求的重定向:地址栏不再是初次发出的请求地址。地址栏为最后响应的那个地址。

    ② 请求转发:在最终的Servlet中,request对象和中转的那个request是同一个对象

    请求的重定向:在最终的Servlet中,request对象和中转的那个request不是同一个对象

    5. JSP

    1). WHY:

    JSP是简化Servlet编写的一种技术,它将Java代码和HTML语句混合在同一个文件中编写,只对网页中的要动态产生的内容采用Java代码来编写,而对固定不变的静态内容采用普通静态HTML页面的方式编写。

    2). Java Server Page:Java服务器端网页,在HTML页面中编写Java代码的页面

    2). Helloworld:

    新建一个JSP页面,在body节点内的<%  %>即可编写Java代码

    <body>

          <%

               Date date = new Date();

               Syetem.out.print(date);

      %>

    </body>

    3). JSP可以放置在WEB应用程序中的除了WEB-INF及其子目录外的其他任何目录中,JSP页面的访问路径与普通HTML页面的访问路径形式也完全一样。

    4). JSP的运行原理:JSP本质上是一个Servlet

    每个JSP 页面在第一次被访问时,JSP引擎将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器(Servlet引擎)像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序

    15 JSP 页面的 9 个隐含对象

    5). JSP页面的隐含变量:没有声明就可以使用的对象,JSP页面一共有9个隐含对象

    Public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) {

            throws java.io.IOException, javax.servlet.ServletException

    PageContext pageContext = null;

    HttpSession session = null;

    ServletContext application = null;

    ServletConfig config = null;

    JspWriter out = null;

    Object page = this;

    //……………………..

    //使用<% %>编写的代码在此位置,可以用到request,response,pagecontext,session,

    //application,config,out,page这8个隐含对象。(实际上还可以使用一个叫exception的隐含对象)

    }

    request:HttpServletRequest 的一个对象

    ② response:HttpServletResponse 的一个对象(在JSP页面中几乎不会调用任何response的方法)

    ③ pageContext:页面的上下文,是PageContext的一个对象,可以从该对象中获取到其他8个隐含对象。也可以从中获取到当前页面的其他信息。(学习自定义标签时使用它)

    ④ session:代表浏览器和服务器的一次会话,是HttpSession的一个对象。后面详细学习。

    application:代表当前WEB应用。是ServletContext对象。

    ⑥ config:当前JSP对应的Servlet的ServletConfig对象(几乎不使用)。若需要访问当前JSP配置的初始化参数,需要通过映射的地址才可以。

    映射JSP:

    <servlet>

        <servlet-name>hellojsp</servlet-name>

        <jsp-file>/Hello.jsp</jsp-file>

        <init-param>

           <param-name>test</param-name>

           <param-value>123456789</param-value>

        </init-param>

     </servlet>

     

     <servlet-mapping>

        <servlet-name>hellojsp</servlet-name>

        <url-pattern>/hellojsp</url-pattern>

     </servlet-mapping>

    out:JspWriter对象。调用out.println()可以直接把字符串打印在浏览器上。

    page:指向当前JSP对应的Servlet对象的引用,但为Object类型,只能调用Object类的方法(很少使用)

    exception:在声明了page指令的isErrorPage=true”时,才可以使用

    <%@ page isErrorPage = "true" %>

    pageContext,request,session,application(对属性的作用域的范围从小到大)

    out,response,config,page

    exception

    6). JSP模版元素:JSP页面中的静态HTML内容

    7). JSP表达式(expression)提供了将一个java变量或表达式的计算结果输出到客户端的简化方式,它将要输出变量或表达式直接封装在<%= 和%>之中。

    <%

        Date date = new Date();

        Out.print(date);

    %>

    <%= date %>

    8).JSP脚本片段(scriptlet)是指嵌套在<%和%>之中的一条或多条Java代码程序

    多个脚本片段中的代码可以相互访问

    <%

           String ageStr = request.getParameter("age");

           Integer age = Integer.parseInt(ageStr);

          

           if(age >= 18){

        %>

           成年人....

          

        <%

               }else if(age < 18){

        %> 

           未成年人...

        <%    

           }

         %>

    16 JSP语法

    9)JSP声明

    JSP声明将Java代码封装在 <%! 和%>之中,它里面的代码将被插进Servlet的_jspService方法的外面(在JSP页面中几乎不这样使用)

    10)JSP注释的格式,<%--注释--%>  <!--HTML注释-->

    区别:JSP注释可以阻止Java代码的执行

    17 域对象的属性操作

    6.和属性相关的方法:

    1)方法

    Object getAttribute(String name): 设置指定的属性

    Enumeration getAttributeNames(): 获取所有的属性的名字组成的Enumeration对象

    removeAttribute(String name): 移除指定的属性

    void setAttribute(String name,Object o): 设置属性

    2)pageContext,request,session,application对象

    这四个对象也称之为域对象

    pageContext:属性的作用范围仅限于当前JSP页面

    request:属性的作用范围仅限于同一个请求(在有转发的情况下,可以跨页面获取属性值,因为转发是同一个请求)

    session:属性的作用范围限于一次会话:浏览器打开直到关闭称之为一次会话(在此期间会话不失效)

    application:属性的作用范围限于当前WEB应用,是范围最大的属性作用范围,只要在一处设置属性,在其他各处的JSP或Servlet都可以获取到该属性

    18 请求的重定向和转发(非常重要)

    7. JSP中的转发和重定向

    先回顾下Servlet中的转发和重定向

    转发:forward

    @WebServlet("/forwardServlet")
    public class ForwardServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("forwardServlet的doGet()方法...");
            
            //实现请求的转发
            //1.调用HttpServletRequest的getRequestDispatcher()方法获取requestDispatcher对象
            //调用getRequestDispatcher()需要传入要转发的地址
            String path = "testServlet";
            RequestDispatcher requestDispatcher = request.getRequestDispatcher("/" + path);
            
            //2.调用HttpServletRequest的forward(request, response)方法进行请求的转发
            requestDispatcher.forward(request, response);
        }
        
    }

      重定向:redirect

    @WebServlet("/redirectServlet")
    public class RedirectServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {     
            System.out.println("redirectServlet 的 doGet 方法");
            //执行请求的重定向,调用HttpServletResponse response的sendRedirect()方法,需要传入要重定向的地址
            String path = "testServlet";
            response.sendRedirect(path);
            
        }
    }

    请求的转发和重定向:

    1). 本质区别: 请求的转发只发出了一次请求,而重定向则发出了两次请求(注意结合前面讲的属性的作用范围,在这两种情况下属性的访问权限是不同的)

    具体:

    ① 请求的转发:地址栏是初次发出请求的地址

    请求的重定向:地址栏不再是初次发出的请求地址。地址栏为最后响应的那个地址。

    ② 请求转发:在最终的Servlet中,request对象和中转的那个request是同一个对象

    请求的重定向:在最终的Servlet中,request对象和中转的那个request不是同一个对象

    JSP中的转发和重定向:

    在jsp文件中加入如下代码块:

    <%
        request.getRequestDispatcher("/page2.jsp").forward(request, response);
    %>

    <%
        response.sendRedirect("page2.jsp");   //注意这里没有加 / 
    %>

     ③ 请求的转发:只能转发给当前WEB应用的资源

         请求的重定向:可以重定向到任何资源

     ④ 请求的转发:/ 代表的是当前WEB应用的根目录

      请求的重定向:/ 代表的是当前WEB站点的根目录

    19 JSP小结(1)

     重要内容已标红色

    20 page指令

    1. JSP指令:是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分

      在目前的JSP2.0中,定义了page、include和taglib这三种指令

    2. page指令

    1). Page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置

    2). Page指令常用的属性:

    属性名称大小写敏感

    可以有多条page指令

    ① import属性:指定当前JSP页面对应的Servlet需要导入的类

    <%@ page import = “java.text.DateFormat” %>

    session属性:取值为true或false,指定当前页面的session隐藏变量是否可用,也可以说访问当前页面时是否一定要生成HttpSession对象

    <%@ page session = “false” %>

    errorPage 和isErrorPage

    • ErrorPage 指定当前页面出现错误的实际响应页面是什么,其中/表示的是当前Web应用的根目录

    <%@ page errorPage = “/error.jsp” %>

    • 在响应error.jsp时,JSP引擎使用的请求转发的方式。
    • isErrorPage指定当前页面是否为错误处理页面,可以说明当前页面是否可以使用exception隐藏变量。需要注意的是:若指定isErrorPage=’true’,并使用exception的方法了,一般不建议能够直接访问该页面。
    • 如何使客户不能直接访问某一个页面呢?对于Tomcat服务器而言,WEB-INF下的文件是不能通过在浏览器中直接输入地址来访问的。但通过请求的转发是可以的!
    • 还可以在web.xml文件中配置错误页面:

    <error-page>

      <!-- 指定出错的代码:404 没有指定的资源  500内部错误 -->

         <error-code>404</error-code>

         <!-- 指定响应页面的位置 -->

         <location>/WEB-INF/error.jsp</location>

      </error-page>

     

     <error-page>

        <!-- 指定异常的类型 -->

            <exception-type>java.lang.ArithmeticException</exception-type>

        <location>/WEB-INF/error.jsp</location>

     </error-page>

    contenttype:指定当前JSP页面的响应类型,实际调用的是response.setContentType("text/html; charset= UTF-8");通常情况下,对于JSP页面而言其取值均为text/html;charset=UTF-8.charset指定返回的页面的字符编码是什么。通常取值为UTF-8.

    pageEncoding:指定当前JSP页面的字符编码,通常情况下该值和contentType中的charset一致

    ⑥ isELIgnored:指定当前JSP页面是否可以使用EL表达式,通常取值为true。

    21 include指令

     3. include指令

    1)include指令用于通知JSP引擎在翻译当前JSP页面时其他文件中的内容合并及当前JSP页面转换成的servlet源文件中,

    这种在源文件级别进行引入的方式称之为静态引入,当前JSP页面与静态引入的页面紧密结合为一个Servlet

    2)file属性的设置值必须使用相对路径

    3)如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件。推荐使用/的方式,使用绝对路径肯定没有问题,使用相对路径可能会有问题

    例:有a.jsp  b.jsp 在a.jsp中使用include指令

    <h3>AAA Page...</h3>
    <% String str = "hahahah";%>   <!-- 在这里声明一个字符串 a.jsp中没有打印语句,在b.jsp中写一个打印语句,只要a.jsp中使用了
    include指令,运行a.jsp文件即可看到打印输出 -->
    <%@ include file="/include/b.jsp" %>
    <h3>BBB Page...</h3>
    <% out.write(str); %>

    22 JSP 标签

    4. JSP:include标签  

    1)<jsp:include page="b.jsp"></jsp:include>

    2)动态引入:并不是像include指令生成一个Servlet源文件,而是生成两个Servlet源文件,然后通过一个方法的方式把目标页面包含进来(可以去tomcat工作目录:D:Program Filesapache-tomcat-7.0.65-64bitworkCatalinalocalhostHi0427orgapachejspinclude 下去一看究竟) 动态引入的代码是这个样子的:

    org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "b.jsp", out, false);

    而静态引入就是直接粘贴代码过来,所以在a文件include了b文件后,可以执行b中的代码;但是在动态引入中,就不可以。

     include指令和include标签的区别

    1)</jsp:include>标签是在当前JSP页面的执行期间插入被引入资源的输出内容。被动态引入的资源必须是一个能独立被WEB容器调用和执行的资源

    include指令只能引入遵循JSP格式的文件,被引入文件与当前JSP文件共同合成被翻译成一个Servlet的源文件

    5. jsp:forward

    1)

    <jsp:forward page="/include/b.jsp"></jsp:forward>  等同于

    <%
    request.getRequestDispatcher("/include/b.jsp").forward(request, response);
    %>

    2)

    但使用jsp:forward 可以使用jsp:param 子标签向b.jsp传入一些参数,同样可以在jsp:include中放入参数

    <jsp:forward page="/include/b.jsp">
    <jsp:param value="testName" name="valueName"/>
    </jsp:forward>

    在b.jsp页面中通过request.getParameter("valueName")获取参数

    23 中文乱码问题

    6. 关于中文乱码

    1)在JSP页面上输入中文,请求页面后不出现乱码:保证charset和pageencoding的值相同,且都支持中文,通常取值为utf-8

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

    还需保证浏览器的显示的字符编码也和请求的JSP页面的编码一致

    2)获取中文参数值:默认参数在传输过程中使用的编码为ISO-8859-1

    ① 对于post请求:只要在获取请求信息前,调用request.setCharacterEncoding("utf-8")就可以获取到正确的中文

    ② 对于get请求:以上方法不管用 当然可以使用以下解码再编码的方式

    <%
    String str = request.getParameter("username");
    String username = new String(str.getBytes("iso-8859-1"),"UTF-8");
    out.print(username);
    %>

    或者 为了方便(推荐使用)可以通过修改Tomcat的server.xml文件的方式

    具体可参考帮助文档:http://localhost:8080/docs/config/http.html文档的useBodyEncodingForURI属性

    为Connector节点添加useBodyEncodingForURI属性值 设置为true  重启tomcat服务器 对于post和get请求,就都可以获取到正确的中文参数了

    24 JSP 小结(2)

    以上红色部分为重点内容

    25 MVC 设计模式

     model:业务数据和业务逻辑,一个model可以被多个视图提供数据,提交了代码的可重用性

     view:显示数据,接受用户输入,不进行任何实际的业务处理

     controller:  接受用户输入调用模型和视图,接受用户请求

    26 MVC 案例之查询

    MVC案例代码:已上传到【文件】,可以自行下载

     

    需要实现效果:

     写一个html页面,页面上有一个链接,点击链接后,服务器会调用一个servlet来响应

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    <a href="listAllStudents"> click to list all the students</a>
    
    </body>
    </html>

    servlet如下:

    @WebServlet("/listAllStudents")
    public class ListAllStudentsServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            
            StudentDao studentDao = new StudentDao();  //实例化一个StudentDao对象
            request.setAttribute("students", studentDao.getAll());  //调用StudentDao对象的getAll()方法获得从数据库获取到的student列表,并放进request的属性中
            
            request.getRequestDispatcher("/students2.jsp").forward(request, response);  //实现页面转发到students2.jsp
        }
    
    }

     studentDao中实现一个方法利用JDBC实现数据库查询并返回一个Student类型的list,如下:

    public class StudentDao {
        /*
         * getAll()方法返回一个Student类型的list*/
        public List<Student> getAll(){
            List<Student> students = new ArrayList<>();  //这里使用泛型,Student类必须有一个无参构造器
            //JDBC连接初始化
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            
            try {
                String driverClass = "com.mysql.jdbc.Driver";  //连接字符串区分大小写 千万不能写错
                String url = "jdbc:mysql://127.0.0.1:3306/mytest";   //mytest为要连接的数据库名称
                String user="root";
                String password = "119";
                
                Class.forName(driverClass);
                connection = DriverManager.getConnection(url, user, password);
                //查询sql语句
                String sql = "select flow_id,Type,id_card,exam_card,student_name,Location,Grade from examstudent";
                preparedStatement = connection.prepareStatement(sql);
                resultSet = preparedStatement.executeQuery();  //执行查询得到结果集
                //遍历结果集 填进list
                while(resultSet.next()){
                    int flowId = resultSet.getInt(1);
                    int type = resultSet.getInt(2);
                    String idCard = resultSet.getString(3);
                    String examCard = resultSet.getString(4);
                    String studentName = resultSet.getString(5);
                    String location = resultSet.getString(6);
                    int grade = resultSet.getInt(7);
                    Student student = new Student(flowId,type,idCard,examCard,studentName,location,grade);  //利用构造器将Student对象实例化
                    if(students != null){
                    students.add(student);  //填进list
                    }
                }    
                
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    if(connection != null){
                    connection.close();     //关闭connection
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                try {
                    if(preparedStatement != null){
                    preparedStatement.close();   //关闭preparedStatement
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                try {
                    if(resultSet != null){
                    resultSet.close();    //关闭resultSet
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
            return students;   //返回list
            
            
        }
    
    }

     返回数据被填充到页面request元素的一个属性中,可以通过请求转发通过一个jsp页面(要注意jsp页面的编码需要为UTF-8,以免引起一些中文问题)展示出来:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" import="com.test.mvc.Student" import="java.util.List"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Insert title here</title>
    </head>
    <body>
    
    <table>
        <tr>
            <th>flow_id</th>
            <th>type</th>
            <th>id_card</th>
            <th>exam_card</th>
            <th>student_name</th>
            <th>location</th>
            <th>grade</th>
        </tr>
    
        <%
        List<Student> stus = (List<Student>)request.getAttribute("students");  //这里需要进行类型强转
        
        for(Student student:stus){   //遍历打印
        %>
        
        <tr>
            <td><%= student.getFlowId()  %></td>
            <td><%= student.getType()  %></td>
            <td><%= student.getIdCard()  %></td>
            <td><%= student.getExamCard()  %></td>
            <td><%= student.getStudentName()  %></td>
            <td><%= student.getLocation()  %></td>
            <td><%= student.getGrade()  %></td>
        </tr>
        
        <% 
        }
        %>
    </table>
    
    </body>
    </html>

    以上省略了Student类的代码,其中要名称各属性,各属性的get方法,及带参和无参构造器。

    27 MVC 案例之删除

    要完成删除操作,需要在studentDao中新增一个删除方法,还需要增加一个响应删除操作的servlet,另外需要修改学生列表页重定向

    后的JSP页面

    <td><a href="deleteStudent?flowId=<%=student.getFlowId()%>">删除</a></td>
    @WebServlet("/deleteStudent")
    public class DeleteStudentServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        
            
            String flowId = request.getParameter("flowId");
            
            StudentDao studentDao = new StudentDao();    
            studentDao.DeleteStudentByFlowId(Integer.parseInt(flowId));
            
            request.getRequestDispatcher("/success.jsp").forward(request, response);
            
        }
    
    }
    public void DeleteStudentByFlowId(Integer flowId){
                 //JDBC连接初始化
                Connection connection = null;
                PreparedStatement preparedStatement = null;
                
                try {
                    String driverClass = "com.mysql.jdbc.Driver";  //连接字符串区分大小写 千万不能写错
                    String url = "jdbc:mysql://127.0.0.1:3306/mytest";   //mytest为要连接的数据库名称
                    String user="root";
                    String password = "119";
                    
                    Class.forName(driverClass);
                    connection = DriverManager.getConnection(url, user, password);
                    //查询sql语句
                    String sql = "delete from examstudent where flow_id = ?";
                    
                    preparedStatement = connection.prepareStatement(sql);
                    preparedStatement.setInt(1, flowId);
                    preparedStatement.executeUpdate();  //执行查询得到结果            
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    try {
                        if(connection != null){
                        connection.close();     //关闭connection
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    try {
                        if(preparedStatement != null){
                        preparedStatement.close();   //关闭preparedStatement
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
         }

      目前阶段:

     1. 关于MVC

      M:Model 目前仅为Dao

      V:View JSP 在页面上填写Java代码实现显示

      C:Controller:Servlet

        1 受理请求

        2 获取请求参数

        3 调用DAO方法

        4 可能会把DAO方法的返回值放入request中

        5 转发(或重定向)页面

     2. 什么时候转发 什么时候重定向?

      若目标的响应页面不需要从request中读取任何值,则可以使用重定向(还可以防止表单的重复提交)

     3. 不足:

      (1)使用数据库连接池 DBUtils JDBCUtils 工具类 DAO基类

      (2)一个请求一个servlet不好! 一个模块使用一个servlet,即多个请求可以使用一个Servlet

      (3)在页面上加入JQuery提示

    28 MVC案例之架构分析

     写一个案例,实现增删改查

    具体要求:

    —没有业务层,直接由Servlet调用DAO,所以也没有事务操作。所以可以在DAO中直接获取Connection对象

    —采取MVC设计模式

    —使用到的技术:

      :MVC设计模式:JSP、Servlet

      :数据库使用MySQL

      :连接数据库需要使用C3P0数据库连接池

      :JDBC工具采用DBUtils

      :页面上的提示操作采用JQuery

    —技术难点:

      :多个请求如何使用一个servlet

      :模糊查询

      :在创建或修改的情况下验证用户名是否已经被使用,并给出提示

    29 MVC案例之DAO层设计

    步骤如下:

    0)建数据表

    1)加入C3P0数据源

    2)编写DAO、JdbcUtils工具类和CustomerDAO接口

    3)提供CustomerDAO接口的实现类:CustomerDAOJDBCImpl

    其余看代码,代码会在后面的小节集中给出

    C3P0的jar包下载地址:http://cn.jarfire.org/c3p0.html

    DBUtils的jar包下载地址:http://commons.apache.org/proper/commons-dbutils//download_dbutils.cgi

    30 MVC案例之DAO层设计

    主要是写代码,边写边使用Junit编写单元测试

    31 MVC案例之多个请求

    1)多个请求使用一个servlet

    第一种方案:

    可以使用在url中增加请求参数的方法来实现

    <body>
    
    <a href="customerServlet?method=add">添加</a>
    <br>
    <a href="customerServlet?method=update">修改</a>
    <br>
    <a href="customerServlet?method=delete">删除</a>
    <br>
    <a href="customerServlet?method=query">查询</a>
    </body>

     在同一个servlet中,写不同的方法来进行不同的操作处理

    @WebServlet("/customerServlet")
    public class CustomerServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String method = request.getParameter("method");
            
            switch (method) {
            case "add":add(request,response); 
            break;
            case "update":update(request,response); 
            break;
            case "delete":delete(request,response); 
            break;
            case "query":query(request,response); 
            break;    
            }
        }
    
        private void query(HttpServletRequest request, HttpServletResponse response) {
            System.out.println("this is query...");        
        }
    
        private void delete(HttpServletRequest request, HttpServletResponse response) {
            System.out.println("this is delete...");        
        }
    
        private void update(HttpServletRequest request, HttpServletResponse response) {
            System.out.println("this is update...");    
        }
    
        private void add(HttpServletRequest request, HttpServletResponse response) {
            System.out.println("this is add...");    
        }
    }

     以上方法可行,但是存在一些缺点:

    ① 当添加一个请求时吗,需要再servlet中修改两处代码,switch、添加对应的处理方法

    ② url中使用method=xxx暴漏了要调用的方法,不私密,有安全隐患

    第二种方案:需要用到反射(推荐使用)

    请求形式为:http://localhost:8080/Hi20160505/addCustomer.do

    页面代码:

    <a href="addCustomer.do">添加</a>
    <br>
    <a href="updateCustomer.do">修改</a>
    <br>
    <a href="deleteCustomer.do">删除</a>
    <br>
    <a href="queryCustomer.do">查询</a>

     ① 配置映射   由请求中的*.do找到对应的servlet

    <servlet>
      <servlet-name>CustomerServlet</servlet-name>
      <servlet-class>com.test.mvc.servlet.CustomerServlet</servlet-class>
      </servlet>
      
      <servlet-mapping>
      <servlet-name>CustomerServlet</servlet-name>
      <url-pattern>*.do</url-pattern>
      </servlet-mapping>

    接下来步骤可参看下面代码段:

    public class CustomerServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //② 获取servletPath /updateCustomer.do
            String servletPath = request.getServletPath();
            
            //③ 取出/和.do 获得updateCustomer这样的字符串
            String methodName = servletPath.substring(1);
            methodName = methodName.substring(0, methodName.length()-3);
            
            try {
                //④ 利用反射获取methodName对应的方法
                Method method = getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
                //利用反射调用对应的方法
                method.invoke(this, request,response);
            } catch (Exception e) {
                e.printStackTrace();
           //若要调用的方法不存在,响应出错时的错误页面
           request.sendRedirect("error.jsp");
    } }
    private void queryCustomer(HttpServletRequest request, HttpServletResponse response) { System.out.println("this is query..."); } private void deleteCustomer(HttpServletRequest request, HttpServletResponse response) { System.out.println("this is delete..."); } private void updateCustomer(HttpServletRequest request, HttpServletResponse response) { System.out.println("this is update..."); } private void addCustomer(HttpServletRequest request, HttpServletResponse response) { System.out.println("this is add..."); } }

     增加新的请求,只需要在同一个servlet中新增对应的实现方法就可以了

    32 MVC案例之(模糊)查

    查询操作:

    Servlet:

         //1. 调用CustomerDAO的getAll() 得到Customer的集合
            List<Customer> customers = customerDAO.getAll();
            
            //2. 把Customer的集合放入request中
            request.setAttribute("customers", customers);
            
            //3.转发页面到index.jsp(不能使用重定向)
            request.getRequestDispatcher("/index.jsp").forward(request, response);

    JSP:

     —获取request中的customers属性

    —遍历显示

    模糊查询:

    —根据传入的name,address,phone进行模糊查询

    —例子:name:a  address:b  phone:3 对应的sql语句的样子为:

    select id,name,address,phone from customes where name like '%a%' and address like '%b%' and phone like'%3%'

    —需要在CustomerDAO接口中定义一个getForListWithCriteriaCustomer(CritiriaCustomer cc)。其中CriteriaCustomer用于封装查询条件:name,address,phone。因为查询条件很多时候和domain包中的Customer类并不相同,所以要做成一个单独的类

    —拼SQL

     select id,name,address,phone from customers where name like ? and address like ? and phone like ?

     为了正确地填充占位符,,重写了CriteriaCustomer的getter:

    public String getName() {
            if (name == null) {
                name = "%%";
            }else{
                name = "%" + name + "%";
            }
            return name;
        }

    —修改Servlet:获取请求参数,把请求参数封装为CriteriaCustomer对象,再调用getForListWithCriteriaCustomer(cc)方法

            String name = request.getParameter("name");
            String address = request.getParameter("address");
            String phone = request.getParameter("phone");
            
            CriteriaCustomer cc = new CriteriaCustomer(name,address,phone);
            
            //1. 调用CustomerDAO的getAll() 得到Customer的集合
            List<Customer> customers = customerDAO.getForListWithCriteriaCustomer(cc);

     33 MVC案例之删除操作

    删除操作:

    —超链接:delete.do?id=<%= customer.getId() %>

    —Servlet 的 delete方法

      获取id

      调用Dao执行删除

      重定向到queryCustomer.do (若目标页面不需要读取当前请求的request的属性,则可以重定向,显示删除后的Customer的list)

    —JSP上的jQuery提示:

     确定要删除XX的信息吗

    <script type="text/javascript">
        $(function(){
            $(".delete").click(function(){
                var content = $(this).parent().parent().find("td:eq(1)").text();
                var flag = confirm("确定删除" + content + "的信息吗?");
                return flag;
            });
        });
        
    </script>

     34 MVC案例之小结(1)

    1. 整体架构图:

    2. 多个请求使用一个servlet

    见上面的红色部分

    1)配置映射

    2)servlet的doGet()和doPost()方法

    3. 查询: MVC的整个流程

    query.do_doPost_query_JSP

    query方法的代码:

        //1. 调用CustomerDAO的getForListWithCriteriaCustomer 得到Customer的集合
            List<Customer> customers = customerDAO.getForListWithCriteriaCustomer(cc);
            
            //2. 把Customer的集合放入request中
            request.setAttribute("customers", customers);
            
            //3.转发页面到index.jsp(不能使用重定向)
            request.getRequestDispatcher("/index.jsp").forward(request, response);

     JSP:获取request中的customers属性,遍历显示

    <%
        List<Customer> customers = (List<Customer>)request.getAttribute("customers");
        if(customers != null && customers.size() > 0){
    %>
        <table cellpadding="10" border="1" cellspacing="0">
            <tr>
                <th>id</th>
                <th>name</th>
                <th>address</th>
                <th>phone</th>
                <th>操作</th>
            </tr>
            <%
            for(Customer customer:customers){
            %>
                <tr>
                    <td><%= customer.getId() %></td>
                    <td><%= customer.getName() %></td>
                    <td><%= customer.getAddress() %></td>
                    <td><%= customer.getPhone() %></td>
                    <td>
                        <a href="">update</a>
                        <!-- class关联到jquery -->
                         <a href="deleteCustomer.do?customerId=<%= customer.getId() %>" class="delete">delete</a>
                    </td>
                </tr>
            <%        
            }
            %>

     4. 模糊查询

    1)正常的sql

    select id,name,address,phone from customers where name like ? and address like ? and phone like ?

     2)填充占位符的技巧:以name属性为例

    public String getName() {
            if (name == null) {
                name = "%%";
            }else{
                name = "%" + name + "%";
            }
            return name;
        }

     3)把查询条件封装为一个JavaBean

    public class CriteriaCustomer {
        
        private Integer id;
        private String name;
        private String address;
        private String phone;
        ...

     35 MVC案例之新增Customer

    添加的流程:

    —Add New Customer 超链接到 addCustomer.jsp

    —新建addCustomer.jsp

    —重写servlet的addCustomer()方法

    private void addCustomer(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
            //1. 获取表单参数:name,address,phone
            String name = request.getParameter("name");
            String address = request.getParameter("address");
            String phone = request.getParameter("phone");
            
            //2. 检验name是否已经被占用
            //2.1 调用customerDAO的getCountWithName(String name)方法 检查name在数据库中是否存在
            long count = customerDAO.getCountWithName(name);
            //2.2 若返回值大于0 则响应addCustomer.jsp页面
            //通过转发的方式来响应addCustomer.jsp页面
            if (count > 0) {
            //2.2.1 要求在addCustomer.jsp页面提示一个错误消息:用户名已被占用
            //在request中放入一个属性message:用于存放错误消息
            //在页面上通过request.getAttribute("message")的方式来显示
                request.setAttribute("message", "name: " + name + " 已经被占用了,请重新录入");
                request.getRequestDispatcher("addCustomer.jsp").forward(request, response);
            
            //2.2.2 要求在addCustomer.jsp的表单值可以回显
            //value=<%= request.getParameter("name") == null ? "":request.getParameter("name") %>
            //2.2.3 结束方法:return
                return;
            }
            //3. 若验证通过,把表单参数封装为一个Customer对象
            Customer customer = new Customer(name,address,phone);
            
            //4. 调用customerDAO的save()方法
            customerDAO.save(customer);
            
            //5. 重定向到查询页面,使用重定向可以避免表单的重复提交问题;使用转发,会出现重复提交的问题
            response.sendRedirect("queryCustomer.do");    
            
        }

     36 MVC案例之修改思路

    —先显示修改的页面,再进行修改

      —显示修改页面

        update的超链接:updateCustomer.do?customerId=<%= customer.getId() %>

        updateCustomer方法:获取id,调用CustomerDAO中对应的方法根据id获取customer对象

        参考代码注释

        JSP页面:—获取请求域中的customer对象,调用对应的get方法来显示值

              —需要使用隐藏域来保存需要修改customer对象的id值:<input type="hidden" name="id "  value=<%=customer.getId()%>>

              —需要使用隐藏域来保存旧的name

             —关于隐藏域:和其他表单项一样可以提交到服务器,只不过在页面上不显示

      —修改操作

        —获取请求参数:id name address phone oldName

        —对name进行验证

        —问题: addCustomer.jsp和updateCustomer.jsp的页面大部分都一样 是否可以为一个呢?(未解决这个问题)

    37 MVC案例之修改代码

    详见代码

    38 MVC案例之通过配置切换底层数据源

    深入理解面向接口编程:

    在类中调用接口的方法,而不必关心具体的实现,这将有利于代码的解耦,使程序有更好的可移植性和可扩展性

    动态修改Customer的存储方式:通过修改类路径下的switch.properties文件的方式来实现

     具体实现过程如下:

    1、CustomerServlet中不能再通过 private CustomerDAO customerDAO = new CustomerDAOSXMLImpl(); 这样的方式来写死实现类

    2、需要通过一个类的一个方法来获取具体的实现类

    public class CustomerServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        private CustomerDAO customerDAO = CustomerDAOFactory.getInstance().getCustomerDAO();

    创建CustomerServlet时,为customerDAO属性赋值是通过CustomerDAOFactory的getCustomerDAO()方法完成的、此时的type已经在InitServlet中被赋值了。

    当前web应用启动的时候,InitServlet被创建,并由Servlet容器调用其Init()方法

    <servlet>
        <servlet-name>InitServlet</servlet-name>
        <servlet-class>com.test.mvc.servlet.InitServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    1、读取类路径下的switch.properties文件

    2、获取switch.properties的type属性值

    3、赋给了CustomerDAOFactory的type属性值

    public class InitServlet extends HttpServlet {  
        private static final long serialVersionUID = 1L;     
        public void init(){
            CustomerDAOFactory.getInstance().setType("jdbc");        
            InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/switch.properties");      
            Properties properties = new Properties();
            try {
                properties.load(in);
                String type = properties.getProperty("type");
                CustomerDAOFactory.getInstance().setType(type);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    39 MVC案例之小结(2)

    1. 对字段的复杂验证:验证需要通过业务层来完成,一般需要通过数据库服务器

    在后边讲structs时,会接触到一些复杂的验证,目前的去重性验证属于简单的

    2. 提交表单,到Servlet的doPost()方法,doPost再转发回到JSP页面,直接页面加载完成,整个过程只有一个HttpServletRequest对象

    3. 表单的回显问题

    <input type="text" name="name"
            value="<%= request.getAttribute("name") == null ? "":request.getAttribute("name") %>"/>

    4. 修改的流程:先显示页面,修改字段,提交表单,修改

    1)id一般都是用隐藏域 <input type="hidden" name="id" value="<%=id%>"/>

    2)修改中的复杂验证,若某一字段在数据表中不允许重复的解决方案

    ① 在表单中是用隐藏域,保存该字段的原始值

    <input type="hidden" name="oldName" value="<%=oldName%>"/>

    ② 在Servlet中同时获取原始值和新提交的值:比对,若一致,则通过;若不一致,则使用新提交的值去查询数据表

            //2.检验name是否已被占用
            //2.1比较name和oldName是否相同,若相同说明name可用
            if (!oldName.equalsIgnoreCase(name)) {
                //2.2若不相同,调用customerDAO的getCountWithName(String name)获取name在数据库中是否存在
                long count = customerDAO.getCountWithName(name);
                if(count > 0){
                    //2.2.1 在updateCustomer.jsp页面显示一个错误消息:用户名已被占用
                    //在request中放入一个属性message:用户名name已经被占用
                    //在页面上通过request.getAttribute("message")的方式来显示
                    request.setAttribute("message","name: " + name + " 已经被占用了,请重新录入" );
                    
                    //2.2.2 updateCustomer.jsp的表单值可以回显
                    //address,phone显示提交表单的新的值,而name显示为oldName
                    
                    request.getRequestDispatcher("updateCustomer.jsp").forward(request, response);
                    //2.2.3 结束方法:return
                    return;
                }            
            }    
            
            //3. 若验证通过,把表单参数封装为一个Customer对象
            Customer customer = new Customer(name,address,phone);
            customer.setId(Integer.parseInt(idStr));
            
            //4. 调用customerDAO的save()方法
            customerDAO.update(customer);
                        
            //5. 重定向到查询页面
            response.sendRedirect("queryCustomer.do");

    3)在修改状态下,若验证没有通过,表单的回显问题:不允许重复的字段要给与提示,但字段中显示旧值,允许重复的字段显示新值

    通过Ajax会有更好的用户体验(目前还没实现)

    5. response.sendRedirect()方法的副作用可以防止表单的重复提交

    6. 面向接口编程:在类中调用接口,而不必关心接口的实现

    7. 使用配置文件

    40 Cookie概述

    浏览器一般只允许存放300个cookie,每个站点允许有20个cookie,每个cookie的大小限制为4kb

    会话cookie一般不保存在硬盘上而只保存在内存中

    <%
        // 在JavaWeb规范中使用 Cookie类代表cookie
        
        //3.获取cookie
        Cookie [] cookies = request.getCookies();
        if(cookies != null && cookies.length > 1){
            for(Cookie cookie:cookies){
                out.println(cookie.getName() + ": " + cookie.getValue());
            }
        }else{
            out.println("没有一个cookie,正在创建并返回");
            //1.创建一个cookie对象
            Cookie cookie = new Cookie("name","nihao");
            //setMaxAge:设置cookie的最大时效,以秒为单位,若为0,表示立即删除该cookie
            //若为负数,表示不存储该cookie 若为正数 表示该cookie的存储时间
            cookie.setMaxAge(30);
            //2.调用response的一个方法把Cookie传给客户端
            response.addCookie(cookie);
        }
            
    %>

    41 利用Cookie进行自动登录

    自动登录:

    —不需要填写用户名和密码等信息,可以自动登录到系统

     

    <%
            String name = request.getParameter("username");
            if(name != null && ! name.trim().equals("")){
                Cookie cookie = new Cookie("name",name);
                cookie.setMaxAge(30);
                response.addCookie(cookie);
            }else {
                Cookie [] cookies = request.getCookies();
                for(Cookie cookie:cookies){
                    if("name".equals(cookie.getName())){
                        String val = cookie.getValue();
                        name = val;
                    }
                }
            }
            
            if(name!= null && name.trim().equals("")){
                out.println("Hello: " + name);
            }else{
                response.sendRedirect("login.jsp");
            }
      
        %>

    42 利用Cookie显示最近浏览的商品

    没怎么看,讲的乱,没有重点,没耐心看

    43 设置Cookie的作用路径

    cookie.setPath(request.getContextPath())

    44 Cookie小结

    (cookie相关代码是在jsp页面中完成的)

    1. cookie:

    1) 完成会话跟踪的一种机制,采用的是在客户端保持HTTP状态信息的方案

    2)cookie'是在浏览器访问web浏览器的某个资源时,由web服务器在HTTP消息响应头中附带传送给浏览器的一个小的文本文件

    3)一旦web浏览器保存了某个cookie,那么他在以后每次访问该web浏览器是,都会在HTTP请求头中将这个cookie回传给web服务端

    4)底层的原理:web服务器通过在HTTP响应头中增加set-cookie传送给浏览器,浏览器通过在请求头信息中增加cookie回传给服务端

    2. cookie的相关API

    1)向客户端浏览器写入cookie

    Cookie cookie = new Cookie("name","test")

    cookie.setMaxAge(30)

    cookie.setPath(request.getContextPath())

    response.addCookie(cookie)

    2) 从浏览器读取cookie

    Cookie [] cookies = request.getCookies();

    if(cookies != null && cookis.length>0){

      for(Cookie cookie:cookies){

         out.println(cookie.getValue());

         out.println(cookie.getName());

      }

    }

    3. 会话cookie和持久化cookie

    默认情况下,不设置时间时为会话cookie

    设置过期时间后为持久化cookie

    4. 两个应用:自动登录和历史记录(未细听)

    其他内容请前往二篇......

  • 相关阅读:
    SQL Server数据库文件存储目录转移
    窗口管理器 dwm安装
    arch linux 安装
    如何在windows 2003(虚拟主机)上面部署MVC3
    .NET接入微信支付(一)JS API接入 V3
    MongoDB部署实战(一)MongoDB在windows平台分片集群部署
    .NET接入UnionPay银联支付(一)手机wap支付
    cas4.2.7 集群服务搭建
    JAVA计算整数的位数
    JAVA求解质因数
  • 原文地址:https://www.cnblogs.com/hnini/p/5334359.html
Copyright © 2011-2022 走看看