1. Ceph packaging and automatic assembly
-
Create cepH-Starter Automation project:
Create a Spring Boot project as a common component.
-
Pom file dependencies:
<dependencies> <! -- Spring Boot custom launcher dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator-autoconfigure</artifactId> </dependency> <! Ceph dependencies --> <dependency> <groupId>com.ceph</groupId> <artifactId>rados</artifactId> <version>0.6.0</version> </dependency> <! Ceph fs operation dependency --> <dependency> <groupId>com.ceph</groupId> <artifactId>libcephfs</artifactId> <version>0.80.5</version> </dependency> <! Ceph swift dependencies --> <dependency> <groupId>org.javaswift</groupId> <artifactId>joss</artifactId> <version>0.10.2</version> </dependency> </dependencies> Copy the code
Adopt the current version directly, adding the three cepH-related dependencies.
-
Code implementation
Encapsulate Ceph operation interface, CephSwiftOperator class:
public class CephSwiftOperator { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); /** * User name */ private String username; /** * Password */ private String password; /** * Authentication access address */ private String authUrl; /** * The default container name */ private String defaultContainerName; /** * Ceph account object */ private Account account; /** * Ceph container object */ private Container container; public CephSwiftOperator(String username, String password, String authUrl, String defaultContainerName) { // Initialize the configuration information this.username = username; this.password = password; this.authUrl = authUrl; this.defaultContainerName = defaultContainerName; init(); } /** * Initialize the connection */ public void init(a) { try { // Ceph user authentication configuration AccountConfig config = new AccountConfig(); config.setUsername(username); config.setPassword(password); config.setAuthUrl(authUrl); config.setAuthenticationMethod(AuthenticationMethod.BASIC); account = new AccountFactory(config).createAccount(); // Get the container Container newContainer = account.getContainer(defaultContainerName); if(! newContainer.exists()) { container = newContainer.create(); log.info("account container create ==> " + defaultContainerName); } else { container = newContainer; log.info("account container exists! ==> "+ defaultContainerName); }}catch(Exception e) { // Do exception catching to avoid service startup failure log.error(Ceph connection initialization exception:+ e.getMessage()); }}/** * Upload object *@param remoteName * @param filepath */ public void createObject(String remoteName, String filepath) { StoredObject object = container.getObject(remoteName); object.uploadObject(new File(filepath)); } /** * Upload file object (byte array) *@param remoteName * @param inputStream */ public void createObject(String remoteName, byte[] inputStream) { StoredObject object = container.getObject(remoteName); object.uploadObject(inputStream); } /** * gets the specified object *@param containerName * @param objectName * @param outpath */ public void retrieveObject(String objectName,String outpath){ StoredObject object = container.getObject(objectName); object.downloadObject(new File(outpath)); } /** * Download the file and convert it to file stream *@param objectName * @return* / public InputStream retrieveObject(String objectName){ StoredObject object = container.getObject(objectName); return object.downloadObjectAsInputStream(); } /** * Deletes the specified file object *@param containerName * @param objectName * @return* / public boolean deleteObject(String objectName){ try { StoredObject object = container.getObject(objectName); object.delete(); return! object.exists(); }catch(Exception e) { log.error(Ceph failed to delete file: + e.getMessage()); } return false; } /** * get all containers *@return* / public List listContainer(a) { List list = new ArrayList(); Collection<Container> containers = account.list(); for (Container currentContainer : containers) { list.add(currentContainer.getName()); System.out.println(currentContainer.getName()); } returnlist; }}Copy the code
-
This wrapper interface will be managed by the Spring container as a singleton, and the constructor will initialize information such as Ceph authenticated connections
-
Set Account and Container as member variables to facilitate reuse and reduce overhead.
-
The default container name is set for initialization. Generally, one container name is set for each service. If the service functions are complex, you can set one container for each service module.
-
Swift Api has been fully encapsulated, which is relatively simple to use internally. It mainly encapsulates upload and download interfaces, and further encapsulates them for easy call processing.
AutoCephSwiftConfiguration automation configuration class:
@Configuration @EnableAutoConfiguration @ConditionalOnProperty(name = "ceph.authUrl") public class AutoCephSwiftConfiguration { @Value("${ceph.username}") private String username; @Value("${ceph.password}") private String password; @Value("${ceph.authUrl}") private String authUrl; @Value("${ceph.defaultContainerName}") private String defaultContainerName; @Bean public CephSwiftOperator cephSwiftOperator(a) { return newCephSwiftOperator(username, password, authUrl, defaultContainerName); }}Copy the code
The ceph. AuthUrl attribute is used to determine whether or not the configuration is loaded. If the ceph attribute is not set in the configuration file, it will be executed without error even if it is referenced in Maven. This automated configuration is responsible for initializing a Ceph Swift interface operation instance.
-
-
Automatic configuration:
In order for the custom Ceph Starter to work, you must follow the SPI extension mechanism of Spring Boot and create a spring.factories file in the meta-INF directory of the Resources environment:
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.ceph.starter.AutoCephSwiftConfiguration Copy the code
Specify the automated configuration class we wrote above.
2. Create a user management project
-
Project configuration application.yml
server: port: 10692 spring: application: name: user-manager # template configuration thymeleaf: prefix: classpath:/templates/ suffix: .html mode: HTML encoding: utf-8 servlet: content-type: text/html # File upload size limit servlet: multipart: max-file-size: 100MB max-request-size: 100MB Ceph Swift authentication information configuration ceph: username: cephtester:subtester password: 654321 authUrl: http://10.10.20.11:7480/auth/1.0 defaultContainerName: user_datainfo Copy the code
-
POM dependency configuration:
<dependencies> <! -- Spring Boot dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <! -- Spring boot thymeleaf template dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <! Ceph Automation Package --> <dependency> <groupId>com.itcast.ceph</groupId> <artifactId>ceph-starter</artifactId> <version>1.0 the SNAPSHOT</version> </dependency> </dependencies> Copy the code
Added Ceph automation package component configuration dependencies.
3. Ceph file upload implementation
-
Implement file upload interface:
/** * Upload user file *@return* / public String uploadUserFile(MultipartFile file) throws Exception { // Get a unique file ID String remoteFileId = globalIDGenerator.nextStrId(); // Upload files to CEPH cephSwiftOperator.createObject(remoteFileId, file.getBytes()); return remoteFileId; } Copy the code
-
Controller layer implementation:
Add the upload interface under UserManagerController:
/** * User file upload *@param file * @return* / @PostMapping("/upload") @ResponseBody public String upload(@RequestParam("file") MultipartFile file) { String result = null; try { // Upload files via Ceph Swift String userFileId = userManagerService.uploadUserFile(file); result = "ID of file uploaded:" + userFileId; }catch(Exception e) { log.error(e.getMessage(), e); result = "An exception occurs:" + e.getMessage(); } return result; } Copy the code
The file is uploaded through Spring Boot. The file is submitted in the form of multipart/form-data, and the parameter name is file. Upload in indirect data flow mode; otherwise, the service cannot recognize the received file.
4. Ceph file download implementation
Added an interface to download files according to the ID of uploaded files.
-
Service layer:
Interface to download user files:
/** * Download user files *@param fileId * @return * @throws Exception */ public InputStream downloadUserFile(String fileId) throws Exception { return cephSwiftOperator.retrieveObject(fileId); } Copy the code
-
The Controller layer:
/** * Download user file information based on file ID *@param filename * @return* / @RequestMapping(value = "/download") public String downloadFile(@notblank (message = "File ID cannot be empty!" ) String filename, HttpServletResponse response){ String result = null; // File stream cache BufferedInputStream bis = null; // File output stream OutputStream os = null; try { // 1. Get the file stream from Ceph server InputStream inputStream = userManagerService.downloadUserFile(filename); // 2. Enable forcible download response.setContentType("application/x-msdownload"); // 3. Set the name of the downloaded file response.addHeader("Content-disposition"."attachment; fileName=" + filename); // 4. Output file stream byte[] buffer = new byte[1024]; bis = new BufferedInputStream(inputStream); os = response.getOutputStream(); int i = bis.read(buffer); while(i ! = -1) { os.write(buffer, 0, i); i = bis.read(buffer); } os.flush(); return null; }catch(Exception e) { log.error(e.getMessage(), e); result = "An exception occurs:" + e.getMessage(); }finally { // Finally, remember to close the file stream if(bis ! =null ) { try { bis.close(); } catch(IOException e) { log.error(e.getMessage(), e); }}}return result; } Copy the code
5. Function verification
-
Visit upload page
Address:http://127.0.0.1:10692/user/file
-
After successful upload, the file ID will be returned:
-
Download file:
Enter the file ID to download:
This article was created and shared by Mirson. For further communication, please add to QQ group 19310171 or visit www.softart.cn