黑马小日子---servlet入门

来源:互联网 发布:淘宝网iphone6s官换机 编辑:程序博客网 时间:2024/04/28 05:52

Servlet入门

4.1. Servlet概述

1、 Servlet

       Servletsun公司提供的用于开发动态web资源的技术。

2、 servlet生命周期

默认情况下,servlet会在第一次被访问的时候被Tomcat实例化,并且驻留内存,然后调用init()方法进行初始化操作,然后调用service方法(“为您服务”),当应用被卸载或者tomcat停掉的时候,释放servlet对象占用的资源(destroy

范例:运行Servlet,查看Servlet的生命周期

//servlet的生命周期

public class ServletDemo01 extends HttpServlet {

//初始化

public void init() throws ServletException {

          System.out.println("init");

}

    //sevice(为客户端的“每次”请求进行服务)

public void service(ServletRequest request,ServletResponse response){

System.out.println("service");

}

    //销毁(释放资源)

public void destroy() {

        System.out.println("destory");

}

}

n 如果想要一个Servlet随着容器的启动而实例化和初始化,那么需要在web.xml中进行配置,如下:

 <servlet>

    <servlet-name>ServletDemo1</servlet-name>

    <servlet-class>com.itheima.ServletDemo1</servlet-class>

    <load-on-startup>1</load-on-startup><!-- 为一个正整数,表明它的启动  顺序 -->

</servlet>

3、 线程安全

针对servlet中可能出现的线程安全问题,尽量将变量声明为局部变量。

4、 ServletConfig

n 作用:获取针对某个Servlet的配置信息

通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

范例:

Web.xml中的初始化参数信息:

   <servlet>

    <servlet-name>ServletDemo3</servlet-name>

    <servlet-class>com.itheima.ServletDemo3</servlet-class>

    <init-param>

    <param-name>encoding</param-name>

    <param-value>UTF-8</param-value>

    </init-param>

    <init-param>

    <param-name>username</param-name>

    <param-value>admin</param-value>

    </init-param>

  </servlet>

编程得到参数化信息:

public class ServletDemo3 extends HttpServlet {

private String defaultCoding = "UTF-8";

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

test2();

}

//获取所有的参数

private void test2() {

Enumeration enumers = getServletConfig().getInitParameterNames();

while (enumers.hasMoreElements()) {

String paramName = (String) enumers.nextElement();

System.out.println(paramName+"="+getServletConfig().getInitParameter(paramName));

}

}

//获取指定参数

private void test1() {

String encoding = getServletConfig().getInitParameter("encoding");

if(encoding==null)

encoding = defaultCoding;

System.out.println(encoding);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

5ServletContext

可以把它看做一个代表,代表当前的整个JavaWeb应用。(某个Web应用的总管家)

Tomcat(WEB容器)在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。

ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯ServletContext对象通常也被称之为context域对象。

作用:

1、多个Servlet之间进行数据共享。整个Web应用数据共享。

2、获取web应用的全局参数

全局参数配置在web.xml的根元素下<context-param>

   得到代表整个web应用的总管家:

public class ServletDemo4 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

ServletContext sc = getServletContext();//得到代表整个web应用的总管家

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

**ServletContext中有一个Map属性

重要:

Object getAttribute(String name):name相当于域Mapkey,返回的是value

void setAttribute(String name,Object obj):

void remove(String name):

Enumeration getAttributeNames():获取Map域中的所有的key

ServletContext的应用:

案例1多个Servlet通过ServletContext对象实现数据共享。

即证明ServletDemo4ServletDemo5共享数据:(Demo4里面设置数据Demo5里面可 以拿到数据)

ServletDemo4里面设置数据:

public class ServletDemo4 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

ServletContext sc = getServletContext();//得到代表整个web应用的总管家

sc.setAttribute("p""pp");

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

在ServletDemo5里面拿到数据:

public class ServletDemo5 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

ServletContext sc = getServletContext();

String value = (String)sc.getAttribute("p");

System.out.println(value);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

案例2:获取WEB应用的全局参数(全局参数配置在web.xml的根元素下<context-param>

//获取全局参数

public class ServletDemo6 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

ServletContext sc = getServletContext();

String value = sc.getInitParameter("encoding");

System.out.println(value);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

案例3:读取各种资源文件的三种方式:

1. ServletContext方式读取配置文件,此方法可以读取web环境中所有的文件

ServletContext context = getServletContext();

String path = context.getRealPath("/cfg.properties"); //得到路径

InputStream in = new FileInputStream(path);    //通过路径读取文件

Properties p = new Properties();    

P.load(in);

p.getProperty("name");        

2.类加载器方法读取配置文件,此方法可以使用在web环境下,也可以使用在非web环境下,但是只能读取加载类下的所有文件

ClassLoad load = Demo1.class.getClassLoad();

URL url = load.getResource("cfg.properties");  //得到URL

InputStream in = new FileInputStream(url);

Properties p = new Properties();

P.load(in);

p.getProperty("name");

3.ResourceBundle方法读取配置文件,此方法读取配置文件非常简单,但是只能读取加载类下的.properties文件

ResourceBundle  rb = ResourceBundle. getBundle("cfg3");  //基名,就是去掉扩展名的

String value = rb.getString();

System.out.print(value);

4.下载文件

String path=getServletContext().getRealPath("/image/科比.jpg");

resp.setHeader("Content-Disposition""attachment;filename="+URLEncoder.encode(path.substring(path.lastIndexOf("//")+1), "UTF-8"));  //设置响应头

InputStream in = new FileInputStream(path);//读取数据

OutputStream out=resp.getOutputStream(); 

int len=0;

byte [] b=new byte[1024];

while((len= in.read(b))!=-1){

out.write(b, 0, len);

}

in.close();

out.close();

请求重定向

特点:

1.浏览器会发送两次请求

2.浏览器地址会发生改变

应用场景:

1.网上购物,使用请求重定向,用户刷新的就只是购物车界面,如果使用转发,那么每次用户刷新,就会添加一次购买

2.用户登录

//设置重定向方法一:

resp.setStatus(302);   //设置响应码

resp.setHander("location","/day05.a.html");  //设置重定向

//设置重定向方法二:

resp.sendRedirect("/day05/a.html");

注意:

servlet,不能同时调用getOutputStream()getWriter()方法,如果同时调用,将会报出getOutputStream() has already been called for this response的错误

Request:

得到客户端向服务端发送的信息

getRequestURL方法返回客户端发出请求时的完整URL

getRequestURI方法返回请求行中的资源名部分。

getQueryString 方法返回请求行中的参数部分。

getRemoteAddr方法返回发出请求的客户机的IP地址

getRemoteHost方法返回发出请求的客户机的完整主机名

getRemotePort方法返回客户机所使用的网络端口号

getLocalAddr方法返回WEB服务器的IP地址。

getLocalName方法返回WEB服务器的主机名

getMethod得到客户机请求方式

获取请求头

getHander();  //获取单一的请求头

getHanderNames(); //获取所有的请求头名称

获取请求参数(客户端提交的请求数据).

用户提交的请求数据,常用的就是GET方式和POST方式,其中

GET方式获取到的就是 "localhost:8080/index?name=admin&password=123 ",中的namepassword.

POST方式获取到的是正文部分.

特别注意:用户所有输入的数据都是String类型

getParameter(name); //得到单一参数的值,相当于getParameterValues的一个特例,如果没有这个name,就返回null,如果用户没有输入,就返回空字符串,如果出现的同名的参数,那么这个方法只能获取第一个.

//得到单一的参数

private void test1(HttpServletRequest req,HttpServletResponse resp) throws Exception {

String value=req.getParameter("username"); //由参数名得到参数值

resp.getOutputStream().write(value.getBytes());

}

getParameterValues(name); //得到同名所有同名参数的值

String[]  values=req.getParameterValues("username");//获取所有参数名问username的值

if(values!=null&&values.length>0){//健壮性判断,html中有这个参数,并且提交的值不为空

for (String value:values) {

resp.getOutputStream().write(value.getBytes());

}

}

getParameterNames(); //获取所有的请求参数名

//得到所有的参数

private void test2(HttpServletRequest req,HttpServletResponse resp) throws Exception {

// TODO Auto-generated method stub

Enumeration es=req.getParameterNames(); //得到所有参数的名称

while(es.hasMoreElements()){    //迭代所有参数名称

String name=(String)es.nextElement(); //通过参数名称得到参数的值

resp.getOutputStream().write(req.getParameter(name).getBytes());

}

}

//getParameterNames()封装数据到对象中

Student stu = new Student();

System.out.println("封装前: "+stu);

Enumeration en=req.getParameterNames();

while(en.hasMoreElements()){

String name=(String)en.nextElement();//得到参数名

try {

PropertyDescriptor pd=new PropertyDescriptor(name, stu.getClass());//操作bean

Method method=pd.getWriteMethod();//通过反射得到set方法

method.invoke(stu, req.getParameter(name));

catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

try {

resp.getOutputStream().write(("封装后 :"+stu).getBytes());

catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

getInputStream();  以流的方式获取正文信息

getParameterMap(); //做框架非常又有,搭配beanUtils

Student stu =new Student();

System.out.println("封装前: "+stu);

Map<String,String[]> map=req.getParameterMap();

BeanUtils bu=new BeanUtils();

try {

bu.populate(stu, map);

catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

catch (InvocationTargetException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

各种表单输入域:

请求参数中的中文乱码:

Request的请求转发和重定向:

请求转发请求地址不会变,浏览器发出了一次请求:两个处理Servlet共享同一个requestresponse.


转发:

发送端:

RequestDispatcher rd=req.getRequestDispatcher("ResquestTest2");//设置转发地址

rd.forward(req, resp);//转发

接收端:

 String value=(String)req.getAttribute(name);

转发和包含:

转发:源组件所有的正文都无效.转发前会清空response对象的缓存,但是不要再转发前刷新缓存.

包含目标组件的所有响应头和响应码都无效,包含前会清空response中的响应头和响应码

javaWeb 中各种路径的写法:

绝对路径如果路径给库护短用,需要加项目名称 /day6 ; 如果是给服务器的路径,就不要骄傲项目名,"/"代表项目名称


原创粉丝点击