猿进化系列9——一文学会java web开发基础

昨天猿人工厂君像你安利了web开发的一些套路,其中最大的套路就算是思考了,因为猿人的一生都是一个不停思考的过程,你也可以回头再看看,顺藤摸瓜,学到很多知识噢。在快速进化变身为猿人的过程中,学会使用特定的工具,去解决特定场景的问题,也是一个快速进化的不二法宝。

猿人进化是一个原创系列文章,帮助你从一只小白快速进化为一个猿人,更多精彩内容,敬请大家关注公主号猿人工厂,点击猿人养成获取

从今天开始,猿人工厂君就带着我们的小猿猿,走上web开发的路子,废话不多说——

 

重要的事情说三遍,我们常常提到的xxx服务器,在绝大多数情况下,都是只得某一款软件,而不是数据中心机柜里看上去很高大上的东西!所谓web服务器,其实是指web服务器软件,比如apahce,nginx,lightHttpd等等。简单的来讲,只要实现了http协议的软件都可以叫做web服务器。

当我们使用浏览器向服务器请求资源,我们在浏览器中输入一个地址,实际上是让浏览器把请求发给服务器请求获取服务器的相关资源,服务器接收到请求之后,会将浏览器请求的资源响应给浏览器。比如html、css、javascipt、图片等等。那么服务器的作用是什么?服务器的作用是,接受客户端请求,返回客户端请求资源!服务器返回给客户端的资源,大体可以可以分为两类:静态资源和动态资源。

静态资源:不需要开发人员做相关的程序处理(其实做到最后也有处理,先这样理解就好),直接返回给浏览器的资源,比如html、css、javascipt、静态图片等等。

动态资源:动态的提供给浏览器的资源,根据浏览器请求的不同,进行相关的程序处理,动态生成数据返回给浏览器,浏览器的请求不同,返回的内容也会不同,比如servlet,jsp,vm等等。

通俗点说,web服务器只是处理简单的http请求,返回静态资源共客户端浏览,而对动态资源的响应是委托给了应用服务器的。

那什么又是应用服务器呢?应用服务器是为特定应用程序提供了运行环境的服务器,比如JAVA应用服务器,就是为java应用提供了运行环境,通常来讲,需要实现JavaEE相关规范为组件提供服务。

      Servlet是运行在web服务器中的程序,可以接收和响应http请求。从本质上讲,以后你所做的java web层面的一切努力,都必然和它放生关系。它是应用程序的入口,是应用服务器提供给你的程序入口,离开了它,你必须面对整个http协议!使用servlet有两个步骤:

1.编写一个java类,实现javax.servlet.Servlet接口。

2.将编写的java类部署在web服务器中。

打开你的idea,一次点击file->New Project,勾选项如下图所示,点击next.

 

 

项目使用了maven进行搭建,为什么要使用maven进行搭建呢?maven是一个很好用的项目依赖管理工具,是构建java项目的主流工具,猿人进化讲述的是快速的转型,对于maven的安装和使用,自行百度下,很快就能上手,下面直接给你pom:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.pz.web.demo</groupId>
  <artifactId>pz-web-demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>pz-web-demo Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <!--servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>pz-web-demo</finalName>
    <pluginManagement>
      <plugins>
        <!--tomcat插件-->
        <plugin>
          <groupId>org.apache.tomcat.maven</groupId>
          <!-- tomcat7的插件, 不同tomcat版本这个也不一样 -->
          <artifactId>tomcat7-maven-plugin</artifactId>
          <version>2.1</version>
          <configuration>
            <!-- 通过maven tomcat7:run运行项目时,访问项目的端口号 -->
            <port>80</port>
            <!-- 项目访问路径-->
            <path>/</path>
            <uriEncoding>UTF-8</uriEncoding>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

 

 

 

第一个servlet就运行起来了。

 

 

   Servlet的生命周期,是指servlet加载、创建servlet对象、初始化(执行init()方法),调用service方法()、销毁的整个过程。servlet的整个生命周期都有servlet容器(web服务器)管理,不需要猿人的参与噢:

1.当服务器启动或者是第一个请求到来时(看配置如果load-on-startup设置为0则为第一次请求访问时,如果为1则为服务器启动时,默认为0),加载servlet类->创建servlet对象->执行init方法,init永远只会执行一次。

2.执行service方法(每个请求都会执行一次)。

3.容器关闭时,执行destory方法。

我们写个代码验证下:

package com.pz.web.demo;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LifeCycleServlet extends HttpServlet {



    public void init() throws ServletException {
        System.out.println("我是init...我被执行了。。");
    }

    public void destroy() {
        System.out.println("我是destroy...我被执行了。。");
    }
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
             System.out.println("我是service...我被执行了。。");
        super.service(req, res);
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        resp.setDateHeader("Expires", 0);
        resp.setContentType("text/html;charset=utf-8");
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("Pragma", "no-cache");
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().write("为什么我会被执行?看看HttpServlet源码找答案");
        resp.getWriter().flush();
    }


}

 

 

 

输入命令 mvn tomcat7:run回车,然后等待应用启动,打开浏览器访问一下:

http://127.0.0.1/LifeCycle

 

插件方式启动不易演示destory,有兴趣的同学可以自己安装tomcat部署运行看看。

 

HttpServletRequest封装了客户端的http请求信息,当客户端通过http请求访问时,http请求头的所有信息都被封装在这个对象中,通过该对象提供的方法可以获取http请求提供的信息。功能上大体可以分为以下几类:

 

获取请求参数相关信息(最常用)

方法

功能

String getParameter(String name)

根据参数名获取参数,如果由多个同名参数,返回的是一个参数的值,最常用

String[] getParameterValues(String name)

根据参数名获取所有参数值(通常用于处理复选框提交的参数),常用

Map getParameterMap()

以Map的方式返回参数的key-value关系,编写框架时常常用到

Enumeration getParameterNames()

获取所有的参数名称,编写框架时常常用到

 

方法

功能

getRequestURL()

返回客户端发起请求的完整url

getRequestURI()

返回客户端发起请求的资源部分名称

getQueryString

返回客户端发起请求的请求行上的参数部分

getRemoteAddr()

返回客户端ip地址

getRemoteHost

返回客户端主机名

getRemotePort

返回客户端使用的端口

getLocalAddr

返回服务器ip地址

getLocalName

返回服务器主机名

getPathInfo()

返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以"/"开头。

 

方法

功能

getHeader(string name)

根据header中的key获取对应的value值。不常用

 

 

HttpServletResponse封装了服务端返回个客户端的响应信息。通过HttpServletResponse一般做以下几个事情:

response.setStatus(302);//设置响应状态码

response.setHeader("refresh", "3;url=http://www.baidu.com");//通知客户端3秒后跳转

response.setHeader("Cache-Control", "no-cache");//通知客户端不需要缓存

response.setHeader("Pragma", "no-cache");

response.setContentType("text/html;charset=utf-8"); //通知客户端以text/html方式返回数据,编码格式utf-8

response.getWriter().write("为什么我会被执行?");//向客户端设置响应体

response.sendRedirect("/Hello");//通知客户端重新发起请求到/Hello这个uri,试试某个你所知道的url?

HttpSession封装了会话信息,由于http协议是一个无状态协议,服务端为了识别客户端信息,当第一次使用HttpServletRequest的getHttpSession方法时,服务端会给客户端分配一个特殊的标识——sessionId,同时在内存种开辟一个空间给会话使用,并且将sessionID存储在客户端的cookie当中,这是一种特殊的cookie,有效期等于浏览器的关闭时间,浏览器一旦关闭,session也就失效了。但是,由于浏览器关闭时,并不会通知到服务端,所以实际上服务端的session仍然是存活的,一般来讲,应用服务器会给每个session分配一个默认的有效时间,比如tomcat,默认是30分钟。

服务端的session,可以理解为一个容器,你可以在session种存放任何,你需要的信息,但是服务端的内存其实是很宝贵的,一定要慎用。下面是一些列子:

 

 

 

 

在讲这个之前有个对象可以你需要先了解一下——ServletContext,又叫做servlet上下文。应用服务器会为每一个应用创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以又叫全局应用程序共享对象。

ServletContext在应用启动的时候创建,应用关闭的时候销毁,ServletContext中的对象是整个应用共享的,适合存放一些全局的信息,注意噢——全局,代表是大家的东西,不能随意修改噢。

 

 

我们先看看Listener——从名字上看,就是监听者的意思,既然叫监听者,那肯定是关注自己感兴趣的东西。Servlet提供了8种类型的监听者,用于监控你所感兴趣的东西。这8种监听者都是接口,如果要使用的话,需要开发者自己实现——当对应的事件发生时,容器来通知对应的监听者,监听者收到自己感兴趣的事件后,可以做自己想做的任何事情。

 

 

 

 

当然,如果要使用它,还是需要在web.xml中配置的:

<!--自定义监听器 -->
<listener>
  <listener-class>com.pz.web.demo.OnlineSessionListener</listener-class>
</listener>

 

 

在程序开发的过程中,慢慢地,你会发现有很多需要统一处理的事情,比如统一请求的字符集编码。这一类事情,可以考虑使用filter来进行处理。

    

 

为什么是filters?因为你可以定义不同的filter来处理不同的事情。那如果有多个的话filter的执行顺序是什么样的呢?如果有多个的话会按照web.xml中的声明顺序来执行。每个Filter的创建和销毁由应用服务器负责,一个Filter在应用中只有一个实例。应用启动时,应用服务器将创建Filter 的实例对象,并调用其init方法,完成对象的初始化功能,filter对象只会创建一次,init方法也只会执行一次。destroy方法在Filter的生命周期中仅执行一次。当应用关闭时,destroy方法会被执行,在destroy方法中,可以释放过滤器使用的资源。程序的口子有了,想做什么事情,还不是你说了算?

接下来猿人工厂君免费送一个统一字符集编码的办法:

package com.pz.web.demo;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class CharsetFilter implements Filter {

    private String encoding;
    private String contentType;

    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        this.contentType = filterConfig.getInitParameter("contentType");
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp =(HttpServletResponse) response;
        req.setCharacterEncoding(encoding);
        resp.setCharacterEncoding(encoding);
        resp.setContentType(contentType);
        //注意噢,这一句不能少噢,这样才会给
        chain.doFilter(req, resp);
    }

}

 

<!-- 编码过滤器 -->
<filter>
  <filter-name>CharsetFilter</filter-name>
  <filter-class>com.pz.web.demo.CharsetFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
  <init-param>
    <param-name>contentType</param-name>
    <param-value>text/html;charset=UTF-8</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>CharsetFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<display-name>Archetype Created Web Application</display-name>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值