一些基础知识
JSP+JavaBean为早期的JSP Model1模式,MVC为JSP Model2模式
Tomcat服务器目录结构
/bin Tomcat命令文件
/conf Tomcat配置文件
/lib Jar包文件
/log 日志
/temp 临时文件
/webapps 发布的网站
/work 由jsp生成的servlet放此目录
WEB-INF目录结构
/ Web应用目录
/WEB-INF Tomcat会隐藏该文件夹,只有服务器端可以访问
/WEB-INF/web.xml web程序最主要的配置文件
/WEB-INF/classes/ 放class类文件
/WEB-INF/lib/ 放jar文件
Servlet
服务器接收http协议请求文本,封装成HttpServletRequest类型的request对象,同时将输出流封装为HttpServletResponse类型的response对象。服务器把request、response作为参数,调用Servlet的相应方法,如doPost(request, response)和doGet(request, response)。
Servlet设置
一个完整的Servlet包括Servlet类、<servlet>配置、<servlet-mapping>配置。
Servlet类
Servlet是一种实现了javax.servlet.Servlet接口的类。在JDK中javax.servlet.*,javax.servlet.http.*包下提供了对Servlet的支持。编写Servlet时直接继承HTTPServlet,一般只覆盖doGet()和doPost()方法。
<servlet>配置
<servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>servlet.FirstServlet</servlet-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </servlet>
servlet-name,servlet-class必选,其他标签可选
<servlet-mapping>配置
<servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/servlet/FirstServlet</url-pattern> </servlet-mapping>
javaEE5起,<servlet-mapping>标签可以配置多个<url-pattern>
<url-mapping>解析规则:
精确匹配:如/foo.htm,只会匹配foo.htm这个url
路径匹配:如/foo/*会匹配以foo为前缀的url
后缀匹配:如*.htm会匹配所有以.htm为后缀的url
Servlet可以输出文本,图片和其他格式数据,如word,Excel,PDF,MP3等,不同的输出类型只要设定response输出类型及输出流。
Servlet读取web.xml参数
初始化参数init-param
init-param可以配置一个初始化参数,Servlet中使用getServletContext().getInitParam(StringparamName)来取得。getInitParameterName()返回所有的参数名称。
init-param是<servlet>标签里的,只能由这个servlet来读取,并非全局参数。
上下文参数context-param
context-param是所有Servlet都能够读取。
<context-param> <param-name>upload folder</param-name> <param-value>attachment</param-value> </context-param>
ServletContext servletContext =this.getServletConfig().getServletContext();
String uploadFolder =servletContext.getInitParameter("upload folder");
初始化参数与上下文参数只能配置简单的字符串类型参数,如果需要更灵活的参数,推荐写到xml文件或properties文件里。
资源注射(@Resource)
Tomcat在启动时会把web.xml里配置信息主动“注射”到Servlet中。
private @Resource(name="hello") String hello; // 注入的 字符串 private @Resource(name="i") int i; // 注入的 整数 @Resource(name="persons")// 注入更常见的写法 private String persons;
在web.xml中
<env-entry><!--资源配置,注射--> <env-entry-name>hello</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value> Hello, Welcome to the JavaEE Resource Injection. </env-entry-value> </env-entry>
@Resource是从JavaEE5规范、Tomcat6.x开始支持的功能。
工作原理是JNDI(Java Naming and Directory Interface),不用@同样可以通过查找JNDI
Context ctx = new InitialContext()//实例化一个Context对象
String message = (String)ctx.lookup(“message”)//查找资源message
Servlet中不仅可以注射String、Integer等类型的变量,还可以注入自定义的JavaBean以及数据源等复杂类型变量。如:
@Resource(name=”dataBase”)//声明数据源,配置在Tomcat中
javax.sql.DataSource dataSource;
public void getConnection(){
Connection conn = dataSource.getConnection();…}
提交表单
提交信息方式包括GET和POST。HTML中使用form提交数据,当form的method属性设置为get或post,action属性表示将数据提交到哪个url。
GET
get方式,形式为http://servername/someServlet?a=aValue&b=bValue。servlet中HttpServletRequest对象通过getParameter(“a”)获得aValue,getQueryString()获得”a=aValue&b=bValue”。
直接单键链接也视为get方式。
Get提交时URL总长度不能超过255个字符。
POST
取得变量方式同get,只是表单信息不会显示在url中。
文件上传
web文件上传使用post,与post提交表单不同,上传文件需要设置form的enctype属性为multipart/form-data。上传文件要使用文件域<input type=”file”/>。
如:<formaction="servlet/UploadServlet"method="post"enctype="multipart/form-data">
Servlet生命周期
Servlet生命周期由web服务器来维护。
init(ServletConfig conf) | 加载Servlet时运行此方法,如果load-on-startup为0,则客户端第一次请求该Servlet时加载Servlet,如果为1,则容器启动时加载Servlet |
Service(ServletRequest req,ServletResponse res) | 客户端每次请求Servlet都会运行该方法,根据访问类型执行不同操作 |
destroy() | 卸载Servlet时执行该方法,当容器关闭时会先卸载所有Servlet。 |
注解@PostConstruct与@PreDestroy
这两个注解用来修饰一个非静态void方法,且该方法不能抛出异常声明。如:
@PostConstruct
public void someMethod(){…}
或 public @PreDestroyvoid anothedMethod(){…}
被@PostConstruct修饰的方法会在Servlet构造函数之后、init()方法之前运行,并且只会被服务器调用一次。
被@PreDestroy修饰的方法会在destroy()方法之后运行,且只运行一次。
服务器加载Servlet→Servlet构造函数→@PostConstruct修饰的方法→init()→service()→destroy()→@PreDestroy修饰的方法→服务器卸载Servlet
注意:注解会影响服务器启动速度,会遍历WEB-INF/classes下所有class文件和WEB-INF/lib下jar文件,查看是否使用注解。可以在web.xml中设置<web-app>的metadata-complete=”true”以关闭注解检查。
Servlet之间的跳转
转向Forward
通过RequestDispatcher对象的forward(HttpServletRequestreq,HttpServletResponse res)方法来实现,如:
RequestDispatcher dispatcher =request.getRequestDispatcher(“/servlet/otherServlet”);
dispatcher.forward(request,response);
Forward是MVC框架常用一种技术,可以跳转到另一个Servlet,JSP页面,甚至WEB-INF下的文件。
服务端行为,一次请求,forward跳转对客户端浏览器是透明的。
forward是最常用的方式,在Struts等MVC中,都是用Servlet来处理用户请求,把结果通过request.setAttribute()放到request中,然后forward到JSP中显示。
重定向Redirect
重定向是利用服务器返回的状态码来实现的。服务器端通过HTTPServletResponse的setStatus(int status)方法设置状态码。如:
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);//302
response.setHeader(“Location”,http://www.baidu.com);
301表示永久重定向,302表示临时性重定向。
HttpServletResponse把上面代码封装成sendRedirect(Stringlocation),如:
response.sendRedirect(request.getContextPath() + filename);
自动刷新Refresh
response.setHeader(“Refresh”,”1;URL=http://www.example.com”);//1秒
若URL设置为自己,就是自己刷新。若时间设为0,则就是重定向。
Servlet与线程安全
Servlet只有一个实例,多个用户请求同一个Servlet,Tomcat会派生出多条线程执行Servlet代码,Servlet有线程不安全的隐患。多线程并发读写Servlet类属性会导致数据不同步。
Servlet常用接口
Servlet实现相关
Servlet接口
init(),destroy(),service(),getServletConfig();
GenericServlet类
getInitParameter(),getSevletConfig(),getSevletContext(),sevice(),getServetInfo()\
HttpServlet类
doGet, doPost, doPut, doDelet,service()
用户自定义Servlet
通常重写doGet和doPost,必要时init()和destroy()。
Servlet请求和响应接口
javax.servlet.http包中请求对象HttpServletRequest,主要继承了ServletRequest接口,封装了Http的请求。可以读写HTTP头标、属性值、Cookies、Session,获取路径信息、客户端参数。
响应对象HttpServletResponse,可以设置缓冲区的大小、头标信息、国际化信息、写Cookies信息,获取输出流,重定向URL和发送状态信息等。
Servlet环境API接口
ServletConfig对象接收Servlet特定的初始化参数。每一个ServletConfig对象对应着唯一的一个Servlet。如<servlet>标签中设置<init-param>
ServletContext对象接收webapp特定的初始化参数,是整个应用程序的执行上下文环境,为所有的Servlet和JSP所共有。如<web-app>标签中设置<context-param>
Servlet的请求转发接口
RequestDispatcher接口,对象由Servlet容器创建,用于封装一个由路径所标识的服务器资源。该接口定义了两种方法:
forward(),转向,这个方法必须在响应被提交给客户端之前调用,否则抛出IllegalStateException异常。方法调用后,原先响应缓存中没有提交的内容将被自动清除。
include(),用于在响应中包含其他资源(Servlet、jsp、或HTML文件)的内容。与forward区别在于include方法将请求转发给其他Servlet,被调用的Servlet的响应并入原先的Servlet的响应中,原先的Servlet还可以继续输出响应信息。
获取RequestDispatcher对象方式:
1.ServletRequest接口中的getRequestDispatcher(Stringpath)
2.ServletContext接口中的getNamedDispatcher(Sting name)
3.ServletContext接口中的getRequestDispatcher(Stringpath)
Servlet会话跟踪接口
HttpSession接口,封装了会话的信息。最典型应用就是登陆与权限管理。
我们经常把HttpRequest、HttpSession、和ServletContext归为一类,可以把数据(对象)放在这三种对象中,他们之间的差别只是作用域不同。ServletContext对象作用域最大,为整个Web应用,全局共享。HttpSession对象的作用域次之,为整个会话过程,同一个用户一次活动所用。ServletRequest的作用域最小,在同一次请求范围。