一、昨天看的是文件上传,今天看了下文件下载
我们一般做文件下载时都是直接在a标签中写文件在服务器端的路径,这样做有两个问题:
(1)遇到中文的文件名时,可能会因为编码的问题而造成不能下载
(2)有些时候可能会遇到权限问题,比如控制用户的下载
这时候,我们就要用到struts的下载了。
<action name="uploadByStruts" class="com.struts.action.UploadAction" method="uploadByStruts">
<param name="inputPath">/upload/会议安排.xlsx</param><result type="stream"><param name="inputName">targetFile</param><param name="contentDisposition">filename="agend.xlsx"</param><param name="bufferSize">4096</param></result>
</action>
public InputStream getTargetFile(){
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
public String uploadByStruts(){
return SUCCESS;
}
这样我们可以在服务器端指定下载文件的位置,并且由于是经过action的,所以可以对权限做控制。
二、我们的微年会项目做了一个demo,新浪在全站推广后,昨天来了第一个需求,是三菱公司的一个新车发布会
由于涉及到访问的域名问题,我们是这样规定的:
(1)用户可以自定去万网申请域名,然后我们做完项目后,会在服务器单独为这个应用跑一个tomcat,这个就是通常的做法,然后到nginx中去配置
(2)用户可以使用我们的域名
http://pj.richmobi.com/XXX,后面的XXX就是项目的名字,这些应用都跑在一个tomcat下,那么就涉及到多个应用跑在一个tomcat下的。
一般部署tomcat,有三种情况
(1)在tomcat的webapp下直接扔各种war包,那么tomcat在启动时就会加载webapp下的war包,比如第一个war的名字是test1.war,第二个是test2.war,那么访问的时候就是
(2)有时候我们不想把应用放到webapp下,那么我们可以指定war包的位置,方法是在server.xml中的host节点下配置多个context,比如
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
这个是tomcat的默认配置,我们可以这样配置
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
<Context
path
=
"/test1"
reloadable
=
"false"
docBase
=
"F:/test1"
/>
<Context path ="/test2" reloadable ="false" docBase ="F:/test2"/>
</Host>
其中,path即context path;docBase指向应用所在的文件夹或war文件,可以是绝对路径,也可以是相对路径(相对该Context所在的Host的appBase属性值);
(3)
在tomcat的conf/[Engine]/[Host]目录下新建xml文件,文件名为context path,比如我们上面配置的host的名字是localhost,engine是catalina,那么在conf/catalina/localhost中,新建一个test1.xml,里面的内容就是配置context,和2一样
这样,就完成了tomcat部署的三种方式
三、
struts的namespace
<s:form action="/user/test/userAction" method="post">
<s:textfield label="姓名" name="user.name"></s:textfield>
<s:textfield label="年龄" name="user.age" value="0"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
比如我们的表单现在是这样,它请求的action是/user/userAction
然后在struts.xml中,我们定义userAction的package的namaspace是/user,也就是说正常访问的路径应该是/user/userAction,但是我们同样可以提交这个表单,进入到相应的方法中,说明struts对于访问路径的处理是先精确查找,也就是先去查找namespace为/user/test中有没有userAction,如果没有的话,就去查找/user中的,如果还是没有,就去查找namespace为/下面的action,如果还没有就去默认的namespace下面,即“”下查找。
<action name="successAction" class="com.struts.action.SuccessAction">
<result>/success.jsp</result>
</action>
而且在result中,资源的路径是相对于浏览器的,和namespace无关
发现一件很有意思的事情:
<action name="*" class="com.struts.action.UserAction" method="universal">
<result>/success.jsp</result>
</action>
<action name="*Action" class="com.struts.action.UserAction" method="{1}">
<result>/success.jsp</result>
</action>
这是我在struts.xml中的配置,如果请求的uri是/user/studentAction,那么那个方法会被引用到呢?也许你会觉得*Action更匹配studentAction,但是错了,在这样的情况下*和*Action的匹配机会是均等的,所以就按照声明的顺序来执行了。
for (Object cfg : config.getPackageConfigs().values()) {
String ns = ((PackageConfig) cfg).getNamespace();
if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() || prefix.charAt(ns.length()) == '/')) {
if (ns.length() > namespace.length()) {
namespace = ns;
}
}
if ("/".equals(ns)) {
rootAvailable = true;
}
}
你看,源码就支持这么匹配的,比如我的访问路径是/user/test/studengAction,namespace是/user,action名字是studentAction,也就是说ns==“/user”,prefix=="/user/test"
如果ns!=null,且prefix以ns开头,这些都符合,他俩长度不等,但是prefix.charAt(ns.length()) == '/'))符合,所以还是可以找到这个动作的。
四、java对国际化的支持
Locale locale = Locale.getDefault();
ResourceBundle bundle = ResourceBundle.getBundle("messageResource", locale);
System.out.println(bundle.getString("user.required"));
我们在类路径下建立messageResource_zh_CN.properties和messageResource_en_US.properties两个文件,在这两个文件中,配置key-value形式的键值对,然后运行,可以得到中文系统环境下的value。