You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring应用中如何通过iCal4j连接自建CalDAV(DaviCal)日历?

Connecting Spring App to DaviCal with iCal4j

Hey there! I’ve worked with both DaviCal and iCal4j before, so let’s break down how to get your Spring app connected and performing basic operations. You’re right about caldav4j—it’s pretty much abandoned at this point, so iCal4j is the way to go (it’s actively maintained and has solid CalDAV support).

Step 1: Add Dependencies

First, add the necessary iCal4j modules to your project. You’ll need the core library plus the CalDAV extension, along with an HTTP client (ical4j uses Apache HttpClient under the hood):

Maven (pom.xml)

<dependencies>
    <dependency>
        <groupId>org.mnode.ical4j</groupId>
        <artifactId>ical4j</artifactId>
        <version>4.0.0</version> <!-- Check for the latest stable version -->
    </dependency>
    <dependency>
        <groupId>org.mnode.ical4j</groupId>
        <artifactId>ical4j-caldav</artifactId>
        <version>4.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents.client5</groupId>
        <artifactId>httpclient5</artifactId>
        <version>5.2.1</version>
    </dependency>
</dependencies>

Gradle (build.gradle)

dependencies {
    implementation 'org.mnode.ical4j:ical4j:4.0.0'
    implementation 'org.mnode.ical4j:ical4j-caldav:4.0.0'
    implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.1'
}

Step 2: Configure CalDAV Client & Authentication

DaviCal relies on HTTP Basic Authentication, so we’ll set up a reusable client bean in Spring. Avoid hardcoding credentials in production—use environment variables or Spring’s config support instead.

import org.mnode.ical4j.caldav.CalDavClient;
import org.mnode.ical4j.caldav.CalDavSession;
import org.mnode.ical4j.caldav.session.BasicAuthSession;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CalDavConfig {

    @Value("${davical.base-url}")
    private String baseUrl;

    @Value("${davical.username}")
    private String username;

    @Value("${davical.password}")
    private String password;

    @Bean
    public CalDavClient calDavClient() {
        // Set up credentials for basic auth
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
        
        // Build HTTP client with auth enabled
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultCredentialsProvider(provider -> {
                    provider.setCredentials(org.apache.hc.client5.http.auth.AUTH.WWW_RESP, null, credentials);
                })
                .build();
        
        // Initialize CalDAV session and client
        CalDavSession session = new BasicAuthSession(httpClient, baseUrl);
        return new CalDavClient(session);
    }
}

Step 3: Verify Connection & Fetch Calendars

Once the client is set up, you can fetch the user’s calendar collections to confirm the connection works. Here’s a service method example:

import org.mnode.ical4j.caldav.CalDavClient;
import org.mnode.ical4j.caldav.response.CalendarHome;
import org.springframework.stereotype.Service;

@Service
public class DaviCalService {

    private final CalDavClient calDavClient;

    public DaviCalService(CalDavClient calDavClient) {
        this.calDavClient = calDavClient;
    }

    public void listUserCalendars() throws Exception {
        // Fetch the user's calendar home (DaviCal uses this path structure)
        CalendarHome calendarHome = calDavClient.getCalendarHome(username);
        
        // Print out available calendars
        calendarHome.getCalendars().forEach(calendar -> {
            System.out.println("Calendar Name: " + calendar.getName());
            System.out.println("Calendar URL: " + calendar.getUrl());
        });
    }
}

Step 4: Create an Event in DaviCal

To add an event, build an iCal4j Calendar object and push it to your target calendar URL:

import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.property.*;
import org.mnode.ical4j.caldav.CalendarCollection;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.time.ZonedDateTime;
import java.util.UUID;

@Service
public DaviCalEventService {

    private final CalDavClient calDavClient;

    public DaviCalEventService(CalDavClient calDavClient) {
        this.calDavClient = calDavClient;
    }

    public void createEvent(String calendarUrl, String summary, ZonedDateTime start, ZonedDateTime end) throws Exception {
        // Get the target calendar collection
        CalendarCollection calendar = calDavClient.getCalendarCollection(URI.create(calendarUrl));
        
        // Build the event with start/end times and summary
        VEvent event = new VEvent(
                new DateTime(start.toInstant()),
                new DateTime(end.toInstant()),
                summary
        );
        
        // Add mandatory properties (required for RFC compliance)
        event.getProperties().add(new Uid(UUID.randomUUID().toString()));
        event.getProperties().add(new DtStamp(new DateTime()));
        event.getProperties().add(new Organizer("mailto:" + username + "@your-domain.com"));
        
        // Wrap the event in a calendar object
        Calendar ical = new Calendar();
        ical.getProperties().add(new ProdId("-//Your Spring App//EN"));
        ical.getProperties().add(Version.VERSION_2_0);
        ical.getProperties().add(CalScale.GREGORIAN);
        ical.getComponents().add(event);
        
        // Push the event to DaviCal
        calendar.add(ical);
    }
}

Key DaviCal Compatibility Tips

  • URL Structure: DaviCal’s calendar paths follow the pattern http://your-server/caldav.php/your-username/your-calendar/—use the listUserCalendars() method to get exact URLs.
  • ETag Handling: For updates/deletes, fetch the event’s ETag first to prevent conflicts. Use calendar.getEvents() to retrieve existing events with their ETags.
  • RFC Compliance: DaviCal is strict about standards, so ensure all mandatory iCal properties (like UID, DTSTAMP) are included in your events.

That should get you up and running with connecting to DaviCal and performing core operations. Let me know if you hit snags with more advanced features like user management or recurring events!

内容的提问来源于stack exchange,提问作者Ihor Biedin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 21:27:46