http请求的参数和属性
练习搭建和使用SSH框架的时候,遇到一个http方面很简单的问题。一个form的表单登录请求,表单为最基本的html表单内容,代码如下
在struts的action中需要获取输入的用户名和密码,最开始我采用的代码如下
但是在运行的时候,一直在user.setUserName(request.getAttribute("user_name").toString());这里报空指针异常,后来改成
user.setUserName(request.getParameter("user_name"));之后就可以正常运行了。
还是上面的SSH项目,为了了解这其中的区别,我将parameters和attributes都打印出来,结果如下
the actual type for request org.apache.struts2.dispatcher.StrutsRequestWrapper
attribute:< __cleanup_recursion_counter,1>
attribute:< struts.actionMapping,org.apache.struts2.dispatcher.mapper.ActionMapping@19a4e8e>
attribute:< struts.valueStack,com.opensymphony.xwork2.ognl.OgnlValueStack@19b7b9d>
parameter:<passwd,sdfg>
parameter:<user_name,lynn>
由此可见,表单传递请求的方式主要是通过parameters来完成。而attributes的使用就主要是框架内部使用。
虽然修改之后系统成功运行,但对于java的Http以及表单请求却产生了许多问题,借此机会做个了解。
以上是来自tomcat源代码中整理出来的Servlet系统的一部分接口、类的继承和实现关系。但由于这里使用的是HttpServletRequest,所以研究的重点要放在HttpServletRequest类上,下面是根据tomat源代码整理出来的HttpServletRequest系统的结构图。
从上图可以看出,本项目中的request.getAttribute和request.getParameter方法是继承自父接口ServletRequest的。这上面解释了tomcat所提供的http系统的大致框架结构。要理解这两个方法之间具体的差别,需要知道这两个对象的实际类型和对象实例化的点。使用
System. out.println("the actual type for request "+request.getClass().getName());将request对象的类型打印出来,显示的结果为“the actual type for request org.apache.struts2.dispatcher.StrutsRequestWrapper”
为什么是request的类型是org.apache.struts2.dispatcher.StrutsRequestWrapper呢?
StrutsRequestWrapper类是来自Struts框架,由于在项目中采用了SSH框架,Struts框架对tomcat的http系统进行了扩充。StrutsRequestWrapper是继承自HttpServletRequestWrapper类,这个类又继承自ServletRequestWrapper,并且实现了HttpServletRequest接口
public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest{/*....*/},它提供一个带HttpServletRequest类型参数的构造函数。代码如下
public HttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
其父类ServletRequestWrappet实现了ServletRequest接口,并且提供了一个带ServletRequest类型参数的构造函数,相关代码如下。
private ServletRequest request;
/**
* Creates a ServletRequest adaptor wrapping the given request object.
*
* @throws java.lang.IllegalArgumentException
* if the request is null
*/
public ServletRequestWrapper(ServletRequest request) {
if (request == null) {
throw new IllegalArgumentException("Request cannot be null");
}
this.request = request;
}
在StrutsRequestWrapper类中重写了getAttribute方法,没有重写getParameter方法。其父类HttpServletRequestWrapper中对这两个方法都没有进行重写。所以,本项目中request对象调用的getParameter方法是来自于ServletRequestWrapper的,代码如下
@Override
public String getParameter(String name) {
return this .request .getParameter(name);
}
结合其构造函数来看,具体其作用的还是在生成StrutsRequestWrapper对象时传递进来的HttpServletRequest对象。
那就从Struts框架的启动配置入手,通过在web.xml中配置filter来将Struts框架引入项目。在web.xml中雨filter相关的配置代码如下。也就是说,tomcat在加载项目的时候,会以StrutsPrepareAndExecuteFilter作为入口,下面顺藤摸瓜。
<filter>
<filter-name> struts</ filter-name>
<filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class>
</filter>
StrutsPrepareAndExecuteFilter实现了Filter接口,每次进行请求的时候,tomcat会调用其doFilter方法。在doFilter代码如下
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns )) {
chain.doFilter(request, response);
} else {
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
 
补充:Web开发 , 其他 ,