`
掌心童话
  • 浏览: 15098 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Java Web Application 自架构 六 邮件服务器与资源存储

阅读更多

       这篇里,做一些简单轻松的配置,邮件服务器的连接与资源的存储。

       第一篇的架构中就有提到,通常在开发Web程序时,要连接的外部辅助系统不仅仅只是数据库,还有很多其他的系统需要连接,故而将业务层下面一层叫做Pin, 来做与外部系统的数据交互。这里就列举一些:比如LDAP 服务器,即轻量级目录访问协议的服务器,简单而言是一种优化了读操作的数据库;用来连接其他Web或非Web程序的Web-Service ;邮件服务器;资源管理服务器等等。

      很明显,我们的架构是:业务逻辑(Business)层将业务数据模型(Entity)传递给Pin层,Pin层将Entity解析为外部系统能够接受的形式后交由外部系统使用或帮助本系统代管;反方向地,Pin层将外部系统的数据读到并封装成本系统的Entity 后交给Business层做相应处理。

LDAP和Web-Service将会放在后面的两篇。这里,配置两个简单的:邮件服务器,资源管理服务器


       1,邮件服务器。用法很容易想到,我们都见过很多的邮件服务器的Web Application,因为

      这里笔者就不再废话连篇,上代码:

在@Configuration的ApplicationContext.java文件中ApplicationContext 类体中加入:

 

@Bean
public JavaMailSender mailSender() {
        Properties parameters = WebConfiguration.getSysParams();
	JavaMailSenderImpl jms = new JavaMailSenderImpl();
	jms.setHost((String) parameters.get("mail.smtp.host"));
	jms.setUsername((String) parameters.get("mail.smtp.username"));
	jms.setPassword((String) parameters.get("mail.smtp.password"));
	jms.setDefaultEncoding((String) parameters.get("mail.smtp.encoding"));
	jms.setPort(Integer.parseInt((String) parameters.get("mail.smtp.port")));
	jms.setProtocol((String) parameters.get("mail.transport.protocol"));
	jms.setJavaMailProperties(parameters);
	return jms;
}

 

 

      JavaMailSender类在org.springframework.context-support-x.x.x.RELEASE.jar包中,不要忘记导此包入WEB-INF/lib下

      当然,还要有JavaMail API的类库,在Spring文档http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mail.html中写的是

mail.jar和activation.jar

      由于activation.jar即JAF已经成为标准的Java组件而被包含在1.6版本以上的JDK中,所以1.6版本以上的JDK不再需要activation.jar,然后新版的JavaMail API应该是6个jars.分别为:mail.jar mailapi.jardsn.jap imap.jar pop3.jarsmtp.jar

 

Parameters 自然还在sysParams.properties文件中去写。

mail.store.protocol=pop3
mail.transport.protocol=smtp
mail.smtp.encoding=utf-8
mail.smtp.host=127.0.0.1
mail.smtp.port=25
mail.smtp.username=root
mail.smtp.password=root
mail.smtp.socketFactory.port=465
mail.smtp.auth=true
mail.smtp.timeout=10000
mail.smtp.starttls.enable=true
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

 

      而后,在pin层新建接口IMailPin.java, 在pin.imap下新建该接口实现类SpringMailPin.java

      代码如下:

package com.xxxxx.webmodel.pin.impl;

import java.io.Serializable;

import javax.annotation.Resource;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;

import com.xxxxx.webmodel.pin.IMailPin;

@Component
public class SpringMailPin implements IMailPin,Serializable {
	
	private static final long serialVersionUID = -1313340434948728744L;
	private JavaMailSender mailSender;

	public JavaMailSender getMailSender() {
		return mailSender;
	}
	@Resource
	public void setMailSender(JavaMailSender mailSender) {
		this.mailSender = mailSender;
	}
	@Override
	public void testMail() {
		JavaMailSenderImpl jms = (JavaMailSenderImpl)this.mailSender;
		System.out.println(jms.getHost());
		MimeMessage mimeMsg =jms.createMimeMessage();
		try {
                   mimeMsg.setSubject("Test James");
			mimeMsg.setFrom(new InternetAddress("xxxxxx@tom.com"));
			mimeMsg.setRecipient(RecipientType.TO, new Inter-netAddress("xxxxx@live.com"));
			mimeMsg.setRecipient(RecipientType.CC, new Inter-netAddress("xxxxxx@yahoo.com"));
			mimeMsg.setRecipient(RecipientType.BCC, new Inter-netAddress("xxxxx@mail.com"));
			mimeMsg.setText("Hello");
//			MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMsg, true, "utf-8");
//			mimeMessageHelper.setFrom("hitmit1314@tom.com");
//			mimeMessageHelper.setTo("palmtale@live.com");
//			
//			mimeMessageHelper.setCc("palmtale@yahoo.com");
//			mimeMessageHelper.setBcc("palmtale@mail.com");
//			mimeMessageHelper.setSubject("Test mail");
//			mimeMessageHelper.setText("Hi, Hello", true);
			mailSender.send(mimeMsg);
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		
	}
}

 

       然后还有简单的单元测试类

package com.xxxxx.webmodel.test.pin;

import javax.annotation.Resource;

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;

import com.xxxxx.webmodel.pin.IMailPin;
import com.xxxxx.webmodel.util.ApplicationContext;
import com.xxxxx.webmodel.util.WebConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ApplicationContext.class})
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, DirtiesContext-TestExecutionListener.class, TransactionalTestExecutionListener.class })
public class MailPinTest {

	private IMailPin mailPin;
	
	public IMailPin getMailPin() {
		return mailPin;
	}
	@Resource
	public void setMailPin(IMailPin mailPin) {
		this.mailPin = mailPin;
	}

	@BeforeClass
	public static void init() throws Exception {
		new WebConfiguration().onStartup(null);
	}
	
	@Test
	public void test() {
		mailPin.testMail();
	}
}

 

      可以运行起一个James做简单测试http://james.apache.org/,3.0的新版还未有Release出Stable版本来,最新稳定版本是2.3.2.

Download Stable James Server2.3.2后的得到james-binary-2.3.2.tar.gzjames-binary-2.3.2.zip

 

      解压后放到自己的安装目录下,然后读下面链接的内容,来获知基本用法;

http://wiki.apache.org/james/JamesQuickstart

以及下面的内容,获知如何将James安装为系统的service

http://wiki.apache.org/james/RunAsService

 

      一切就绪后,测试。成功与否就查自己的邮件吧,有些邮件服务器发不到,多试一些。

      比如,我在雅虎邮箱里能收到上述测试邮件



 

 

      其它需求可以在上述Spring文档中查阅。

 

      2,资源管理服务器。什么是资源管理服务器?用来存储诸如图片,音频,视频,文档等资源的服务器。有人会说,存储在部署Web的服务器本身的硬盘上不就行了么。 好,文件系统,最简单的资源管理服务器。可是,把这些资源放到Local的文件系统上,这样的Case会有不适合的情况。例如我们需要部署一个Web服务集群以供并发量较高的访问,有好多台服务器部署着同样的WebApp,一个控制Node去管理是哪台机器响应用户的访问,这时,你就需要同步每一台服务器的文件系统的同一个位置上的所有资源(文件)。虽然可以做到,但是跑一个线程去同步N个 /var/resources比起配置所有服务器通过某协议访问一个固定的Socket(Host:Port)还是复杂,而且前者会遇到实时拖延问题:是说在一个时刻,A用户访问到了A服务器需要B资源,可是当时正好B资源还没有被跑着的线程挪过来到A服务器上。所以用一个固定的资源管理器是个不错的选择,比如Amazon 的S3服务器。想地有点儿远了,自己架设个FTP比什么都强。

 

      这部分很简单,直接贴代码喽:

   接口:

package com.xxxxx.webmodel.pin;

import java.io.InputStream;

public interface IResourcePin {
	
	public boolean isExisting(String key) throws Exception;
	public void storeResource(String key,Object data) throws Exception;
	public <Form> Form achieveResource(String key,Class<Form> clasze)throws Exception;
	public void removeResource(String key) throws Exception;
	
	enum DataType{
		Base64(String.class),ByteArray(byte[].class),InputStream(InputStream.class);

		@SuppressWarnings("rawtypes")
		DataType(Class claze){
			this.dataType=claze;
		}
		@SuppressWarnings("rawtypes")
		private Class dataType;
		@SuppressWarnings("rawtypes")
		public Class getDataType(){return dataType;}
	}
}


    测试方法:

 

package com.xxxxx.webmodel.test.pin;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.annotation.Resource;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.util.FileCopyUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import com.xxxxx.webmodel.pin.IResourcePin;
import com.xxxxx.webmodel.util.ApplicationContext;
import com.xxxxx.webmodel.util.WebConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ApplicationContext.class})
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, DirtiesContext-TestExecutionListener.class, TransactionalTestExecutionListener.class })
public class ResourcePinTest {

	private String testKey =  "projectA/belong1/belong2/doc3";
	private IResourcePin resourcePin;
	@BeforeClass
	public static void init() throws Exception{
		new WebConfiguration().onStartup(null);
	}
	@Resource(name="ftpResourcePin")
	public void setResourcePin(IResourcePin resourcePin){
		this.resourcePin = resourcePin;
	}
	@Test
	public void testIsExisting()throws Exception {
		Assert.assertFalse(resourcePin.isExisting(testKey));
	}

	@Test
	public void testStoreResource()throws Exception {
		resourcePin.storeResource(testKey, "Test Resource".getBytes("UTF-8"));
		Assert.assertTrue(resourcePin.isExisting(testKey));
		resourcePin.removeResource(testKey);
		resourcePin.storeResource(testKey, new ByteArrayInputStream("Test Re-source".getBytes("UTF-8")));
		Assert.assertTrue(resourcePin.isExisting(testKey));
		resourcePin.removeResource(testKey);
		resourcePin.storeResource(testKey, new BASE64Encoder().encode("Test Re-source".getBytes("UTF-8")));
		Assert.assertTrue(resourcePin.isExisting(testKey));
		resourcePin.removeResource(testKey);
	}

	@Test
	public void testAchieveResource() throws Exception{
		resourcePin.storeResource(testKey, "Test Resource".getBytes("UTF-8"));
		InputStream is0 =resourcePin.achieveResource(testKey, null);
		byte[] resultBytes0 = FileCopyUtils.copyToByteArray(is0);
		Assert.assertTrue(new String(resultBytes0,"UTF-8").equals("Test Resource"));
		InputStream is =resourcePin.achieveResource(testKey, InputStream.class);
		byte[] resultBytes = FileCopyUtils.copyToByteArray(is);
		Assert.assertTrue(new String(resultBytes,"UTF-8").equals("Test Resource"));
		byte[] byteArray = resourcePin.achieveResource(testKey, byte[].class);
		Assert.assertTrue(new String(byteArray,"UTF-8").equals("Test Resource"));
		String base64Code = resourcePin.achieveResource(testKey,String.class);
		Assert.assertTrue(new String(new BASE64Decoder().decodeBuffer(base64Code),"UTF-8").equals("Test Resource"));
		try{resourcePin.achieveResource(testKey, Integer.class);}
		catch(Exception use){
			Assert.assertTrue(use.getMessage().startsWith("Data Type is not support-ed"));
		}	
		resourcePin.removeResource(testKey);		
	}

	@Test
	public void testRemoveResource() throws Exception{
		resourcePin.storeResource(testKey, "Test Resource".getBytes("UTF-8"));
		Assert.assertTrue(resourcePin.isExisting(testKey));
		resourcePin.removeResource(testKey);
		Assert.assertFalse(resourcePin.isExisting(testKey));
	}

}


    FileSystem实现:

 

 

package com.xxxxx.webmodel.pin.impl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.Serializable;

import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import com.xxxxx.webmodel.pin.IResourcePin;
import com.xxxxx.webmodel.util.WebConfiguration;
@Component
public class FileSystemResourcePin implements Serializable,IResourcePin {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8508501371117792553L;

	private String fileSystemRoot;
	
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	public FileSystemResourcePin(){
		try{
			this.fileSystemRoot =   WebConfigura-tion.getSysParams().getProperty("resource.storage.relativePath");
			if(!this.fileSystemRoot.startsWith("/"))this.fileSystemRoot='/'+this.fileSystemRoot;
		}
		catch(Exception e){this.fileSystemRoot= "/fileStorage";}
		this.fileSystemRoot = this.getClass().getResource("/").getFile().replace("/WEB-INF/classes",this.fileSystemRoot);
	}
	@Override
	public boolean isExisting(String key) throws Exception {
		return isExisting(new File(this.fileSystemRoot,key));
	}

	private boolean isExisting(File file){
		return file.exists();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void storeResource(String key, Object data) throws Exception {
		if(key==null||key.trim().length()==0||data==null) return;
		@SuppressWarnings("rawtypes")
		Class dataType = data.getClass();
		for(DataType supportedType: DataType.values()){
			if(supportedType.getDataType().isAssignableFrom(dataType))
			{
				File targetFile = new File(this.fileSystemRoot,key);
				if(!targetFile.exists())
					{target-File.getParentFile().mkdirs();targetFile.createNewFile();}
				FileOutputStream fos = new FileOutputStream(targetFile);
				switch(supportedType){
				case Base64:data =(Object) new BASE64Decoder().decodeBuffer((String)data);
				case ByteArray:data = (Object)new ByteArrayInputStream((byte[])data);
				case InputStream:FileCopyUtils.copy((InputStream)data, fos);
				default:return;
				}
			}
		}
		throw new Exception("Data Type is not supported");
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <Form> Form achieveResource(String key, Class<Form> clasze)
			throws Exception {
		File keyFile = new File(this.fileSystemRoot,key);
		if(!keyFile.exists()||keyFile.isDirectory())return null;
		if(clasze==null)return (Form) achieveResource(key,InputStream.class);
		for(DataType supportedType: DataType.values()){
			if(clasze.equals(supportedType.getDataType()))
			{
				FileInputStream fis = new FileInputStream(keyFile);
				switch(supportedType){
				case InputStream:return (Form)fis;
				case ByteArray:return (Form)FileCopyUtils.copyToByteArray(fis);
				case Base64:return (Form)new BASE64Encoder().encode(FileCopyUtils.copyToByteArray(fis));
				}
			}
		}
		throw new Exception("Data Type is not supported");
	}

	@Override
	public void removeResource(String key) throws Exception {
		new File(this.fileSystemRoot,key).delete();
	}

}

 

 

    FTP实现

package com.xxxxx.webmodel.pin.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.net.SocketAddress;

import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.net.ftp.FtpClient;
import sun.net.ftp.FtpProtocolException;

import com.xxxxx.webmodel.pin.IResourcePin;
import com.xxxxx.webmodel.util.WebConfiguration;
@Component("ftpResourcePin")
public class FTPResourcePin implements Serializable,IResourcePin{

	/**
	 * 
	 */
	private static final long serialVersionUID = -4273201499908924422L;
	private FtpClient ftpClient;
	private String ftpUser="admin";
	private String password="password";
	private SocketAddress ftpServerAddress = new InetSocket-Address("127.0.0.1",FtpClient.defaultPort());
	private String releateRootPath="/ftproot";
	
	public FTPResourcePin(){
		String ftpURL = null;
		try{
			ftpURL =WebConfiguration.getSysParams().getProperty("resource.ftp.url");
			if(ftpURL!=null){
				int protocolIndex = ftpURL.indexOf("://");
				if(protocolIndex>=0)ftpURL=ftpURL.substring(protocolIndex+3);
				int usrIndex = ftpURL.indexOf('@');
				if(usrIndex>=0){
					this.ftpUser = ftpURL.substring(0,usrIndex);
					ftpURL = ftpURL.substring(usrIndex+1);
				}
				int hostIndex = ftpURL.indexOf('/');
				if(hostIndex>=0){
					String[] socket = ftpURL.substring(0,hostIndex).split(":");
					this.ftpServerAddress = new InetSocket-Address(socket[0],socket.length>1?Integer.parseInt(socket[1]):FtpClient.defaultPort());
					ftpURL=ftpURL.substring(hostIndex);
				}
				this.releateRootPath=ftpURL.startsWith("/")?ftpURL:"/"+ftpURL;
			}
			this.releateRootPath+=WebConfiguration.getSysParams().getProperty("resource.storage.relativePath");
		}
		catch(Exception e){/*do as default value*/}
		try {
			this.ftpClient =FtpClient.create((InetSocketAddress)this.ftpServerAddress);
		} catch (FtpProtocolException | IOException e) {
			e.printStackTrace();
		}
	}
	
	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	private void checkConnection(){
		try {
			if(!ftpClient.isConnected())
				this.ftpClient.connect(this.ftpServerAddress);
			if(!ftpClient.isLoggedIn())
			{
				try{this.password = WebConfigura-tion.getSysParams().getProperty("resource.ftp.password");}catch(Exception e){}
				ftpClient.login(this.ftpUser, this.password.toCharArray());
			}
		} catch (FtpProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void gotoDirectory(String dir,Boolean write){
		if(dir==null||dir.trim().length()==0)return;
		if(write==null)write=false;
		try {
			dir = dir.replaceAll("\\\\+", "/");
			if(dir.startsWith("/")){
				this.checkConnection();
				ftpClient.reInit();
				dir=(this.releateRootPath+dir).replaceAll("/+", "/");
				if(dir.startsWith("/"))dir=dir.substring(1);
			}
			String[] dirs = dir.split("/");
			this.checkConnection();
			for(String dire:dirs){
				if(write)try{ftpClient.makeDirectory(dire);}
				catch(sun.net.ftp.FtpProtocolException fpe){
					if(!fpe.getMessage().contains("Cannot create a file when that file already exists"))
						throw fpe;}
				ftpClient.changeDirectory(dire);
			}
		} catch (FtpProtocolException | IOException e) {
			if(e instanceof FtpProtocolException && e.getMessage().contains("The sys-tem cannot find the file specified"));
		}
	}
	@Override
	public boolean isExisting(String key) throws Exception {
		if(key==null)
			return false;
		try{
			key =('/'+key.replaceAll("\\\\+", "/")).replaceAll("/+", "/");
			int lastIdx = key.lastIndexOf('/');
			this.gotoDirectory(key.substring(0,lastIdx), null);
			String fileName = key.substring(lastIdx+1);
			InputStream is =ftpClient.nameList(fileName);
			byte[] testContent = FileCopyUtils.copyToByteArray(is);
			if(testContent!=null&&testContent.length>0)
				return new String(testContent).trim().equals(fileName);
			else return false;
		}catch(Exception e){
			if(e instanceof sun.net.ftp.FtpProtocolException && e.getMessage().contains("The system cannot find the file specified"))
				return false;
			else throw e;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public void storeResource(String key, Object data) throws Exception {
		if(key==null||key.trim().length()==0||data==null) return;
		@SuppressWarnings("rawtypes")
		Class dataType = data.getClass();
		for(DataType supportedType: DataType.values()){
			if(supportedType.getDataType().isAssignableFrom(dataType))
			{
				OutputStream os = null;
				try{
					key =('/'+key.replaceAll("\\\\+", "/")).replaceAll("/+", "/");
					int lastIdx = key.lastIndexOf('/');
					this.gotoDirectory(key.substring(0,lastIdx), true);
					os =ftpClient.putFileStream(key.substring(lastIdx+1));
					switch(supportedType){
					case Base64:data =(Object) new BASE64Decoder().decodeBuffer((String)data);
					case ByteArray:data = (Object)new ByteArrayIn-putStream((byte[])data);
					case InputStream:FileCopyUtils.copy((InputStream)data, os);
					default:return;
					}
				}catch(Exception e){}
			}
		}
		throw new Exception("Data Type is not supported");
		
	}

	@SuppressWarnings("unchecked")
	@Override
	public <Form> Form achieveResource(String key, Class<Form> clasze)
			throws Exception {
		if(key==null)return null;
		if(clasze==null)return (Form) achieveResource(key,InputStream.class);
		for(DataType supportedType: DataType.values()){
			if(clasze.equals(supportedType.getDataType()))
			{
				InputStream is =null;
				try{
					key =('/'+key.replaceAll("\\\\+", "/")).replaceAll("/+", "/");
					int lastIdx = key.lastIndexOf('/');
					this.gotoDirectory(key.substring(0,lastIdx), null);
					is =ftpClient.getFileStream(key.substring(lastIdx+1));
					switch(supportedType){
					case InputStream:return (Form)is;
					case ByteArray:return (Form)FileCopyUtils.copyToByteArray(is);
					case Base64:return (Form)new BASE64Encoder().encode(FileCopyUtils.copyToByteArray(is));
					}
				}catch(Exception e){}
			}
		}
		throw new Exception("Data Type is not supported");
	}

	@Override
	public void removeResource(String key) throws Exception {
		try{
			key =('/'+key.replaceAll("\\\\+", "/")).replaceAll("/+", "/");
			int lastIdx = key.lastIndexOf('/');
			this.gotoDirectory(key.substring(0,lastIdx), true);
			String resName =key.substring(lastIdx+1);
			ftpClient.deleteFile(resName);
			String preName = key.substring(1,lastIdx);
			String dirs[] = preName.split("/");
			for(int i=dirs.length-1;i>-1;i--)
			{
				ftpClient.changeToParentDirectory();
				ftpClient.removeDirectory(dirs[i]);
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}

}

 

      FTP的安装与配置就不多说了,网络上随处可见,Windows 里把IIS的FTP服务打开,Linux用相应的源管理软件安装个ftpd 或vsftpd, pure-ftpd都可以。配置好之后在sysParam里填加上相应的properties

resource.storage.relativePath=/FileStorage
resource.ftp.url=ftp://[ftpusername]@[hostname{:pot}]/{为该应用配置的路径}
resource.ftp.password=ftppasswordvalue


      在单元测试类中通过改变@Resource的name值注入不同的实现类,分别测试,成功。


分享到:
评论

相关推荐

    自己开发的JAVA Web Email邮件系统

    在IT领域,开发一个JAVA Web Email邮件系统是一项具有挑战性的任务,它涉及到多个技术栈的整合,包括JAVA编程、Web开发、邮件处理协议以及服务器配置等。这个系统允许用户通过Web界面发送、接收、管理电子邮件,类似...

    WebApplication1.zip

    【标题】"WebApplication1.zip" 是一个包含Web应用程序资源的压缩文件,它很可能是一个基本的Web项目,可能由开发人员用于部署到Web服务器上运行。这个文件的名称表明这可能是一个初版或者示例应用,名为“Web...

    java web信息管理

    除此之外,MVC(Model-View-Controller)设计模式也是Java Web开发中常用的一种架构模式。Model代表数据模型,View负责展示,Controller处理用户请求并协调Model和View。这种模式有助于提高代码组织和解耦。 此外,...

    Sun Java System Application Server Enterprise Edition 8.2 管理指南.pdf

    Sun Java System Application Server Enterprise Edition 8.2 (以下简称 Sun Java Application Server EE 8.2) 是一款全面的企业级应用服务器,专为复杂的业务环境设计。它提供了强大的功能集合,支持Java EE标准,...

    服务器端+Web管理端,web服务器端程序,Java源码.zip

    9. **部署与运行**:Java应用通常被打包成WAR(Web Application Archive)或EAR(Enterprise Application Archive)文件,然后部署在Web容器(如Tomcat、Jetty)或应用服务器(如WebLogic、WildFly)上运行。...

    Elecve Web Application (Java servlet)

    【Elecve Web Application(Java Servlet)】是一个基于Java技术的Web应用程序,主要利用Java Servlet和JSP(Java Server Pages)来实现一个E-Leave(电子请假)系统。该系统通常用于企业管理员工的请假申请流程,...

    基于JAVA WEB的通讯簿管理系统(jsp)

    10. **部署与运行**: 该系统通常被打包成WAR(Web Application Archive)文件,部署在支持Java EE的Web服务器,如Tomcat、Jetty上运行。 通过分析和理解这些知识点,你可以对基于JAVA WEB的通讯簿管理系统有一个...

    WebDynpro for Java

    - **双服务器架构**:SAP Web Application Server 6.30 采用了一种双服务器架构,包括 ABAP 和 Java 两个部分。 - **数据库分离**:ABAP 和 Java 部分使用了逻辑上分开的数据库存储空间和不同的模式(schema)。 ####...

    李兴华 Java Web 开发实战经典_带源码_高清pdf 带书签 上

    第1章 JAVA WEB开发简介 1.1、WEB发展历程 1.2、企业开发架构 1.3、JAVA EE架构 1.4、JAVA EE核心设计模式 1.5、Struts开发框架 1.6、本章摘要 1.7、开发实战讲解 第2章 HTML、JavaScript简介 2.1、服务器...

    Tomcat与java web 开发技术详解-孙卫琴-第二版-541-761

    《Tomcat与Java Web开发技术详解》是由孙卫琴编著的第二版书籍,该书深入探讨了在Java Web开发中使用Tomcat服务器的核心技术和实践方法。Tomcat是一款开源、轻量级的Java Servlet容器,它是Java EE Web应用程序部署...

    Java Web开发技术(课件)

    5. **Web应用对象的存储管理**:在Java Web中,会涉及到Session、Cookie和Application范围内的对象存储。这些技术用于在用户会话期间保持状态,例如,用户登录信息、购物车数据等。同时,也会讲解到HTTP无状态特性和...

    java web通讯录管理系统

    【Java Web通讯录管理系统】是一种基于Java Web技术开发的应用,主要用于管理和存储个人或组织的联系人信息。这个系统由菜鸟wyh开发,虽然界面设计可能较为简单,但基本功能已经实现,包括添加、删除、修改和查询...

    java 实现上传文件到远程服务器

    ### Java 实现上传文件到远程服务器(Spring MVC) 在现代软件开发中,文件上传功能是十分常见的需求之一,尤其在Web应用中。本篇文章将详细介绍如何利用Java编程语言结合Spring MVC框架来实现文件的远程上传功能。...

    java web学生信息管理系统

    【Java Web学生信息管理系统】是一个基于Java Web技术开发的简易应用,主要目的是为了帮助初学者理解和实践Web应用程序的开发流程。这个系统的核心功能是管理和维护学生的信息,包括添加、删除、修改和查询学生数据...

    WebApplication1.rar

    以上是对"WebApplication1.rar"可能包含的技术点的分析,具体的应用架构和技术选型需要解压文件并查看源代码才能确定。在进一步研究之前,建议确保有足够的权限访问和使用这个文件,并遵循相关的开源许可协议。

    Java Web整合开发王者归来 源代码

    《Java Web整合开发王者归来》源代码包含了丰富的Java Web开发技术,主要涵盖了Servlet、JSP等核心组件。这里我们将深入探讨这些技术,并扩展到相关的Web开发知识。 Servlet是Java平台上的一个服务器端程序,它是...

    Java Web组件技术 讲义.pdf

    ### Java Web组件技术详解 #### 一、Servlet与JSP入门 Servlet与JSP是Java Web开发中的核心组件,它们负责处理HTTP请求并生成动态网页。 - **Servlet**:Servlet是一种运行在服务器上的小型程序,主要用于接收...

    java技术架构图汇总.doc

    Tomcat 是一个流行的 Java Web 服务器,用于部署 Java Web 应用程序。Tomcat 架构图展示了 Tomcat 服务器的整体结构,包括 Connector、Engine、Host 等组件。Tomcat 的主要功能是提供了一个灵活的 Web 服务器来部署 ...

    java web 电子商城

    Java Web电子商城是一个基于Java技术构建的在线购物平台,它集成了前端用户界面与后端管理系统,为用户提供了一个完整的电子商务解决方案。在这个系统中,开发者通常会利用Java Web的三大框架——Spring、Struts和...

Global site tag (gtag.js) - Google Analytics