Servlet和JSP

Servlet

Servlet/JSP应用架构

servlet无法独立运行,必须运行在Servlet容器中。Servlet容器将用户的请求传递给Servlet应用,并将结果返回给用户。Tomcat和Jetty就是当前最流行的Servlet/JSP容器。


Servlet/JSP应用架构.png
Servlet是一个Java程序
@WebServlet(name = "WxsFirstServlet", urlPatterns = {"/myServlet"})
public class MyServlet implements Servlet {
    private transient ServletConfig servletConfig;

    //保存配置信息,如@WebServlet注解中的属性,仅调用一次
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig = servletConfig;
    }

    //获得上述配置信息对象
    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    //容器会自动调用该方法处理请求,返回响应。
    //容器接到请求后,会自动创建ServletRequest和ServletResponse对象并传给service方法
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        String servletName = servletConfig.getServletName();
        servletResponse.setContentType("text/html");

        System.out.println(servletRequest.getParameter("id"));

        PrintWriter writer = servletResponse.getWriter();
        writer.print("Hello from" + servletName + "");
    }

    @Override
    public String getServletInfo() {
        return "MyServlet";
    }

    @Override
    public void destroy() {

    }
}

运行该程序,只需启动Tomcat并部署后,访问http://localhost:8080/项目名/MyServlet即可,此时,浏览器上将会显示我们返回的HTML页面

GenericServlet

上述实现Servlet的缺点是,有些方法没必要修改,但我们仍要重载。
GenericServlet实现了Servlet和ServletConfig接口,通过继承GenericServlet,只需实现Service方法即可实现Servlet

HttpServlet

主角!最常用!
HttpServlet有两个特性是GenericServlet所不具备的:

  • 不用覆盖Service方法,而是覆盖doGet、doPost、doHead等方法。HttpServlet中的Service方法会根据HTTP请求的Method调用响应的doXXX方法
  • 使用HttpServletRequest和HttpServletResponse,而不是ServletRequest和ServletResponse
处理HTML表单

当用户提交(submit)表单时,在表单元素中输入的值就会被当作请求参数发送到服务器。

HttpServlet&HTML表单示例

一开始HTML页面竟然是这么返回的。。。>_<
该Servlet有两个方法

  • 方法1,返回HTML,包含Form表单,用于填写信息。提交表单后,会调用第二个方法
  • 方法2,返回HTML,显示上面表单所填写的信息
@WebServlet(name="FormServlet", urlPatterns={"/form"})
public class FormServlet extends HttpServlet
{
    //这里是要返回给客户端一个包含Form表格的HTML,用于填写信息
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOExeption
    {
        response.setContentType("text/html");
        Printwriter writer = response.getWriter();
        writer.print("");
        ...
        //
的action属性为默认,表示该表单会被提交给请求它时用的相同的URL,以便提交表格后调用下一个方法 writer.println("") //
等组件 writer.print(""); } //这里是要返回一个HTML,展示用户在上一个方法返回的HTML页面中填写的表格信息 @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.println(""); //
等组件 ... writer.println(""); } }
部署描述符

前面的例子都是利用@WebServlet配置Servlet应用程序,例如用一个路径映射到一个Servlet。本节介绍另一种方法,即部署描述符。部署描述符总是放在WEB-INF目录下,并且总是命名为web.xml

可将第一个例子中的@WebServlet去掉,编辑web.xml如下,可达到同样效果



    
        WxsFirstServlet
        MyServlet
    

    
        WxsFirstServlet
        /myServle3t
    


会话管理

HTTP是无状态的,默认下,Web服务器无法区分一个HTTP请求是否为第一次访问。
例如,一个Web邮件应用要求用户登陆才能查看邮件,因此,当用户输入用户名、密码登陆后,应用应能记住这些用户已经登陆,不应再次提示登陆。
本节将阐述4种不同的状态保持技术:URL重写、隐藏域、cookies和HTTPSession

URL重写

将必要的信息都记录在url中
仅适合与信息仅在少量页面间传递,形式如下
url?key-1=value-1&key-2=value-2&...&key-n=value-n

隐藏域

将必要的信息都记录在表单的隐藏域,表单提交时,隐藏域的值也同时提交到服务器端。
隐藏域技术仅当网页有表单时有效。相对于URL重写的优势在于没有字符数限制,但也不适合跨越多个界面形式如下


Cookies
  • 构造cookie:Cookie cookie = new Cookie(name, value);
  • 将cookie发送到浏览器:httpServletResponse.addCookie(cookie);
  • 服务端获取浏览器提交的cookie:HttpServletRequest接口的getCookies()返回Cookie数组。若要查询某个特定名称cookie,需要遍历cookie数组。

浏览器在访问同一Web服务器时,会将之前收到的cookie一并发送。我试过,浏览器中的cookie默认会保存很久,即使关闭浏览器也不会消除cookie。可控制cookies的有效时间,例如将maxAge设置为0实现消除cookie。
cookies的问题在于用户可以通过改变其浏览器设置来拒绝接受cookies

HttpSession

一个用户有且仅有一个HttpSesison对象
HttpSession对象在用户第一次访问网站的时候自动被创建

常用接口
  • getSession:获得当前Session对象
  • setAttribute:将键值(可以是Serializable的接口)放入HttpSession。
  • getAttribute:取值
  • getAttributeNames:返回所有保存在Session中的值
  • 还有一些设置Session过期的接口,若果Session没过期且容器和应用没有关闭,则一直存放在服务端内存中

注意,所有保存在Session中的值都存储在内存中,并且不会被发送到客户端。Servlet容器为每个HttpSession生成唯一标识发送给浏览器(开发人员无需介入),在后续的请求中,浏览器会将标识提交给服务端,这样服务器可以识别该请求是由哪个用户发起的

JavaServer Pages(JSP)

Servlet的缺点
  • 生成响应报文的方式十分烦琐,writer.println("
  • 文本和HTML标记硬编码,即使表现层需要改变背景颜色,也需要重新编译
  • Servlet解决上述的问题,现代JavaWeb应用会同时使用JSP和Servlet

    JSP概述

    JSP页面本质上是一个Servlet,但更便于开发。JSP是Servlet的补充,并不是取代Servlet技术,倾向于表现层的Servlet可用Servlet来代替
    JSP页面在JSP容器中运行,一个Servlet容器通常也是JSP容器,如Tomcat就是一个Servlet/JSP容器

    当一个JSP页面第一次被请求时,Servlet/JSP容器主要做以下两件事情:

    • 将JSP页面转化为对应的实现了javax.servlet.Servlet子接口实现类,使得每一个页面都是一个Servlet(在Tomcat目录下找到转换后的Servlet后,会发现响应HTML仍然是通过out.write(....)的方式写的)
    • 如果转换成功,容器编译、装载、实例化该Servlet类,像正常Servlet一样执行生命周期操作

    JSP页面不同于Servlet的一个方面是,前者不需要添加注解或在部署描述符中配置映射URL,在应用程序目录中的每一个JSP页面可以直接在浏览器中输入路径页面访问。如:http://localhost:8080/ProjectName/welcome.jsp。添加新的JSP界面后,无须重启Tomcat

    JSP页面可以包含模版数据和语法元素

    • 语法元素:具有特殊意义的JSP转换符,如<%,%>分别代表Java代码的起止符号,<%%>块又被称作scriplet。
    • 模版数据:除去语法元素外的一切是模板数据。模板数据会原样发送给浏览器,如HTML标记和文字
    隐式对象

    Servlet中,通过service方法能够拿到:HttpServletRequest、HttpServletResponse;通过init能够访问ServletConfig;通过HttpServletRequest的getSession访问HttpSession

    在JSP中,可以通过使用如下隐式对象来访问上述对象:
    request、response、config、session
    另外还有

    • application,类型为ServletContext
    • out,类型为JspWriter
    • page,类型为HttpjspPage
    • pageContext,类型为HttpJspPage
    • exception,类型为Throwable

    示例,在JSP中实现从HttpServletRequest对象中获取username的值

    <%String userName = request.getparameter("username"); %>
    
    指令

    指令是JSP语法元素的第一种类型,用于指示JSP转换器如何翻译JSP页面为Servlet。只有page和include最重要

    • page:可以导入包、设置out缓冲区大小、是否使用session等
    • include:将另一个JSP或静态HTML文件嵌入到当前JSP中
    表达式

    <%= xxx%>等价于<% out.print(xxx)%>

    声明

    <%! xxx%>可用与声明或重写函数,声明和重写的函数可以在JSP页面中使用

    禁用脚本元素

    推荐的实践是:在JSP页面中用EL访问服务器端对象且不写Java代码。因此,需要通过在部署描述符中的定义scripting-invalid元素,来禁用脚本元素

    动作

    useBean

    
    <%=today%>
    

    该代码创建一个Java.util.Date实例,并赋值给名为today的脚本变量,然后在表达式中使用

    setProperty和getProperty

    
    
    
    

    forward
    将当前页面转向其它资源

    
        
    
    
    错误处理

    当应用遇到未捕获的异常时,用户将看到一个精心设计的网页解释放生了什么。
    errorHandler.jsp使用Page指令的isErrorPage属性,表示自己是个错误页面

    <%page isErrorPage="true"%>
    

    bug.jsp故意抛出异常, 并且使用errorPage指向错误处理的页面

    <%@page errorPage="erroHandler.jsp"%>
    

    表达式语言

    EL的目的是设计成可以轻松地编写免脚本的JSP页面。也就是说,页面不实用任何JSP声明、表达式或者scriptlet

    EL表达式
    ${expression},返回结果为String
    ${a+b}${c+d},如果a+b=8,c+d=10,则结果为810
    ${object["property"]}或${object.property}可访问object的属性
    

    在JSP页面中,可以利用JSP脚本来访问JSP隐式对象。但是,在免脚本的JSP页面中,则不可能访问这些隐式对象。EL允许通过提供一组它自己的隐式对象来访问不同的对象。不详细说了

    JSTL

    JSTL标准标签库是一个定制标签库的集合,用来解决像遍历Map或集合、条件测试、XML处理,甚至数据库访问和数据操作等常见的问题
    在JSP页面使用JSTL库,必须通过类似以下格式使用taglib指令:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    
              
    

    你可能感兴趣的:(Servlet和JSP)