今日已更新 35 条资讯 | 累计 23992 条内容
关于我们

标签:#java

找到 746 篇相关文章

AI 资讯

Inbox Zero for Devs: How I Built a JavaScript Script to Destroy Gmail Spam

Hey dev community! 👋 As developers, our inboxes often turn into a graveyard of job alerts (LinkedIn, Indeed, ZipRecruiter) and tech newsletters we subscribe to with the intention of "reading later" but never actually open. The result? Important emails get lost, and we get the dreaded "Account storage is almost full" notification. Recently, I hit that wall. I had thousands of accumulated emails. While Gmail allows you to create filters for incoming mail, it doesn't have a native feature to say: "Delete this email automatically after 7 days" . So, I decided to solve it the way we solve everything: by writing some code. 🛠️ The Solution: Google Apps Script + JavaScript Since the Google Workspace ecosystem runs on a JavaScript-based environment, I put together a custom script. Fun fact: a simple loop originally failed due to Google's strict 6-minute execution limit. To fix this, I optimized the code to process emails in batches of 100 , preventing the server from timing out. Here is the final production-ready script: function cleanSpamTsunami() { // 1. Loop to delete ALL Job Board emails in batches of 100 var continueJobSearch = true; while (continueJobSearch) { var jobThreads = GmailApp.search('computrabajo OR indeed OR linkedin OR OCC OR neuvoo OR talent.com OR jooble', 0, 100); if (jobThreads.length > 0) { Logger.log('Deleting a batch of ' + jobThreads.length + ' job alert emails...'); GmailApp.moveThreadsToTrash(jobThreads); } else { Logger.log('No more job alerts found!'); continueJobSearch = false; // Break the loop } } // 2. Loop to delete old Newsletters (older than 7 days) in batches of 100 var continueNewsletters = true; while (continueNewsletters) { var newsletterThreads = GmailApp.search('unsubscribe OR "cancelar suscripción" older_than:7d', 0, 100); if (newsletterThreads.length > 0) { Logger.log('Deleting a batch of ' + newsletterThreads.length + ' old newsletters...'); GmailApp.moveThreadsToTrash(newsletterThreads); } else { Logger.log('No more old newslett

2026-06-25 原文 →
AI 资讯

Your @EventListener Fires Before the Transaction Commits⚙️

Your domain event fires. Your notification service queries the DB for the entity that just got saved. It finds nothing. You add a log line. It starts working. You remove the log. It breaks again. That's not a race condition. That's @EventListener . What's actually happening Spring's @EventListener fires synchronously, inside the calling thread, before the transaction commits. The DB row exists in Hibernate's session — but it hasn't been flushed and committed yet. Other connections, including the one your listener opens when it calls findById , can't see it. The log statement "fixes" it because the delay gives Hibernate time to flush. Remove the log, the flush doesn't happen in time, and you're back to an empty Optional . Here's the broken setup: @Component public class OrderEventListener { @EventListener // fires MID-TRANSACTION, before commit public void onOrderCreated ( OrderCreatedEvent event ) { // Transaction not committed yet. // Other DB connections see nothing. Order order = orderRepository . findById ( event . getOrderId ()) . orElseThrow (); // ← throws here, row doesn't exist yet notificationService . notifyCustomer ( order ); } } The obvious fix and what it costs you Spring ships @TransactionalEventListener for exactly this. Set phase = TransactionPhase.AFTER_COMMIT and the listener fires after the transaction commits. The row is visible. findById returns the order. Problem solved. @Component public class OrderEventListener { @TransactionalEventListener ( phase = TransactionPhase . AFTER_COMMIT ) public void onOrderCreated ( OrderCreatedEvent event ) { // Transaction committed. All connections see the row. Order order = orderRepository . findById ( event . getOrderId ()) . orElseThrow (); // ← works fine notificationService . notifyCustomer ( order ); } } But the trade-off is real. Your listener is now decoupled from the transaction. If the listener fails — notification service is down, the email throws, the external API times out — the transaction alrea

2026-06-25 原文 →
AI 资讯

Building a Real-Time World Cup 2026 Bracket Predictor with Vanilla JS and GitHub Actions

Introduction With the World Cup 2026 group stage reaching its climax, football fans worldwide are speculating about who will make it to the finals. To make this experience interactive, I built a fully dynamic World Cup 2026 Bracket Simulator. Instead of just letting users click and choose winners, this app dynamically calculates ELO win probabilities and probabilistically generates realistic match scores (including extra time and penalties) based on team ratings. It also syncs with live match data in real-time. Live URL: https://worldcup-predict2026.github.io/champion/ Tech Stack: Vanilla JS, CSS3 (3D parallax), GitHub Actions, Python, football-data.org API Core Features & Technical Implementation ELO-Based Win Probability & Score Simulation Each team in the database is assigned an ELO-based strength rating. When a user runs the AI auto-prediction, the script calculates win probability and generates a realistic scoreline. Here is the goal roll algorithm (Poisson-like simulation) implemented in Vanilla JS: javascript function generateMatchScore(team1, team2, winner) { if (team1 === "TBD" || team2 === "TBD" || !winner) return null; const s1 = teamStrengths[team1] || 70; const s2 = teamStrengths[team2] || 70; const winnerIsTeam1 = (winner === team1); const strengthDiff = Math.abs(s1 - s2); const baseGoalExpected = 1.1; const bonusGoal = Math.min(1.8, strengthDiff / 12.0); // Goal weight based on ELO difference const rollGoals = (lambda) => { let L = Math.exp(-lambda); let k = 0; let p = 1.0; do { k++; p *= Math.random(); } while (p > L && k < 10); return k - 1; }; let gWin = 0; let gLose = 0; const r = Math.random(); if (r < 0.75) { // Regular time win (90 mins) gLose = rollGoals(baseGoalExpected); gWin = gLose + 1 + rollGoals(0.7 + bonusGoal); return winnerIsTeam1 ? ${gWin} - ${gLose} : ${gLose} - ${gWin} ; } else if (r < 0.92) { // Extra time win (AET) const normalGoals = rollGoals(baseGoalExpected); gLose = normalGoals; gWin = normalGoals + 1; return winnerIsTeam1 ?

2026-06-25 原文 →
AI 资讯

Stop Hand-Designing Open Graph Images: Automate Link Previews for Every Page

Open Graph images are the single biggest factor in whether your shared links look credible or broken. Yet most sites ship one generic image on every page because making a unique one by hand is tedious. Here is a more sustainable approach: treat preview images as generated data, not hand-made design. The problem, concretely When you share a link, the receiving platform reads your page's og:image meta tag and renders a card. If that tag is missing, points to a low-res logo, or is the same image on all 200 pages, your links look generic in every feed, Slack channel, and group chat. Studies of social sharing consistently show that posts with a clear, relevant preview image get meaningfully more engagement than those without. The reason teams skip it is not ignorance. It is friction. Opening a design tool, duplicating a template, swapping the title text, exporting at the right dimensions, and uploading the file takes 10 to 20 minutes per page. Nobody keeps that up across a real publishing schedule. So the back catalog stays bare and new posts get whatever the default is. The insight: it is template work Look at a typical preview card and ask what actually changes between pages. Usually just the title, maybe the author and a category tag. The layout, background, logo, and fonts are constant. That is the textbook definition of a job you should template once and generate programmatically, not redo by hand each time. How to solve it The cleanest pattern is to generate the image at build time or on first request, then cache it. Conceptually: // During your build or in an API route async function getOgImage ( post ) { const params = new URLSearchParams ({ title : post . title , author : post . author , tag : post . category , }); // Returns a ready Open Graph image URL return `https://getcardforge.dev/api/card? ${ params } ` ; } // In your page head // <meta property="og:image" content={getOgImage(post)} /> You can build this yourself with a headless browser plus an HTML templ

2026-06-25 原文 →
AI 资讯

The New Standard for NPM Package Discovery: Deep Dive into LibPilot

As web developers, engineering workflows are heavily dependent on the NPM registry. However, the traditional process of searching, auditing, and integrating packages remains highly fragmented. Developers are routinely forced to hop between npmjs.com, GitHub source repositories, and external documentation tabs simply to verify bundle sizes, check dependency trees, or generate setup boilerplate. Following a strong reception on LinkedIn, X, and Facebook, the Motion Mind Team has introduced LibPilot to the dev.to community. LibPilot is not a traditional registry interface; it is an AI-powered search engine and discovery hub engineered to index, track, and analyze over 4,000,000 NPM packages in real time. Here is an architectural breakdown of how LibPilot restructures package exploration for modern developers and autonomous AI code agents. Intent-Based Discovery and Global Search Architecture Traditional search engines require users to input the exact name or strict keyword of a library. LibPilot introduces a dual-input architecture on its home page to eliminate this constraint: Direct Registry Querying: Users can input full or partial package names into the global search bar to instantly surface clean, structured, and typed suggestions directly from the live NPM ecosystem database. Contextual AI Recommendations: For scenarios where the ideal package is unknown, developers can type out a complete description of their project architecture or system constraints (for example: "a lightweight, typed state management engine that handles server-side rendering natively"). LibPilot's internal AI agent processes the functional requirements and suggests production-ready libraries suited for that stack. Continuous Context AI and Interactive Onboarding A core goal of the platform is reducing developer friction and maintaining deployment momentum. LibPilot transitions static package documentation into an interactive environment: Unlimited AI Chat Architecture: Once a library is select

2026-06-24 原文 →
AI 资讯

dev.to How Online Casinos Prove Their RNG Is Fair, and Why Most Software Can't

Math.random() returns a number between 0 and 1, and roughly nobody reading this could explain what happens between the call and the return. That is fine, fine right up until the output decides who gets money, and then it becomes one of the genuinely hard problems in applied software, the kind that regulated industries build entire testing labs around. Start with the thing most people get wrong: a sequence that passes for random and a fair sequence are different claims, and your users cannot tell them apart by staring at outputs. The users will never catch the difference and that is the whole problem in one sentence. This is why fairness in any real-money system, an online casino being the sharpest example, is a verification problem long before it is a math problem. Pseudorandom generators are deterministic. A PRNG eats a seed, runs it through fixed arithmetic, and spits out numbers that sail through statistical randomness tests while being completely predetermined by that seed. Mersenne Twister is the poster child: excellent distribution, used everywhere by default for years, and from a few hundred observed outputs you can reconstruct its internal state and predict the rest. For a Monte Carlo simulation, who cares! For anything where a human has a financial reason to guess your next number, you just shipped a vulnerability and called it a feature. What you want when stakes exist is a CSPRNG. The guarantee that matters: even with a long history of outputs, an attacker cannot compute the next one or recover the internal state. crypto.randomBytes() in Node. crypto.getRandomValues() in the browser. They sit one autocomplete away from the unsafe option and offer wildly different guarantees, which is exactly why this bug ships so often. The safe call and the dangerous call look like fraternal twins. ** The part players actually rely on ** Say you build it correctly: a proper CSPRNG, real entropy, no timestamp nonsense. You know it is fair but now prove it to a stranger wh

2026-06-24 原文 →
AI 资讯

Legacy code não envelhece como vinho: quanto mais espera, pior fica

Semana passada eu passei três horas debugando um bug que deveria levar 20 minutos. O problema? Um módulo de validação escrito em 2019 que ninguém mexe "porque funciona". Spoiler: não funcionava mais, e quando finalmente abri o arquivo, encontrei um // TODO: refactor this datado de 2020. Por que legacy vira bola de neve A indústria trata código legado como se fosse dívida técnica opcional — algo que você paga "quando tiver tempo". Mas código legado se comporta mais como mofo: se espalha, contamina áreas adjacentes, e quanto mais você ignora, mais cara fica a limpeza. O ciclo é previsível: você herda um projeto ou feature antiga, vê que está "meio bagunçado mas roda", adiciona sua feature com um if a mais, e segue em frente. Seis meses depois, outra pessoa faz o mesmo. Um ano depois, aquele arquivo tem 800 linhas, cinco níveis de if aninhados, e zero testes. Ninguém mais entende o fluxo completo, então cada mudança vira uma sessão de especulação: "se eu mexer aqui, quebra ali?" O custo real de esperar Esse código "que funciona" tem um custo oculto que aparece em três formas: Velocidade de desenvolvimento despenca. Features que deveriam levar dois dias levam uma semana porque você passa mais tempo entendendo o contexto do que escrevendo código novo. Bugs aumentam exponencialmente. Código sem testes e com lógica embolada é um gerador de regressões. Você corrige um edge case e quebra outro que nem sabia que existava. Onboarding vira tortura. Novo dev no time? Boa sorte explicando por que aquele service tem três formas diferentes de fazer autenticação, ou por que a mesma validação está copiada em sete lugares. Sinais de que você está sentado em cima de uma bomba Nem todo código antigo é legacy tóxico. Aqui estão os red flags que indicam que você precisa agir agora: // Red flag #1: comentários mentirosos ou inúteis function processPayment ( order ) { // Process the payment const user = order . user ; // TODO: fix this later // HACK: don't touch this, breaks prod if ( user

2026-06-24 原文 →
AI 资讯

Stokado: A Zero-Dependency Proxy Wrapper That Makes Browser Storage Feel Like a Plain Object

If you've shipped anything to the browser, you've used localStorage . And if you've used it for more than five minutes, you've also written this exact line more times than you'd like to admit: const user = JSON . parse ( localStorage . getItem ( ' user ' ) || ' null ' ) The Web Storage API has aged remarkably well for something so small, but it carries three persistent pain points that every frontend codebase ends up papering over by hand. Pain point #1: everything is a string. localStorage.setItem('count', 0) doesn't store the number 0 — it stores the string "0" . Read it back and typeof is "string" . Booleans become "true" / "false" , Date objects collapse into ISO strings (if you're lucky) or "[object Object]" (if you're not), and undefined becomes the literal string "undefined" . So every project grows a thin serialization layer of JSON.parse / JSON.stringify wrappers, plus a pile of defensive try/catch blocks for the day a malformed value sneaks in. Pain point #2: the API is verbose and stringly-typed. getItem , setItem , removeItem — three method calls and a string key for what is conceptually just reading and writing a property. It reads nothing like the rest of your code. Pain point #3: reactivity is broken in the tab you actually care about. The native storage event only fires in other tabs of the same origin. The tab that performed the write never hears about it. So if you want to react to your own storage changes — the overwhelmingly common case — the platform gives you nothing. Stokado is a small, zero-dependency library that addresses all three by wrapping any storage object in a Proxy . It's framework-agnostic, TypeScript-friendly, and works equally well with localStorage , sessionStorage , cookies, async backends like localForage, and a handful of mini-program runtimes. This article walks through what it actually does, feature by feature, with runnable code. Quick start npm install stokado import { createProxyStorage } from ' stokado ' const storage =

2026-06-24 原文 →
AI 资讯

I ran one API response through two JSON-to-Zod converters. One silently turned every field into z.string().

You have an API response. You want a Zod schema. So you paste the JSON into a JSON-to-Zod converter, copy the output, and ship it. Here's the trap: a lot of those converters infer basic types only . Your email , your uuid , your url , your ISO timestamp — they all come out as z.string() . The schema compiles, the types look right, and your validator quietly accepts "not-an-email" , "ftp://nope" , and "2026-99-99" forever. I wanted to see exactly how much gets lost, so I ran the same payload through two tools and diffed the output. Everything below is real, copy-pasteable output — nothing edited. The input A pretty ordinary user object: { "id" : "3f2a9c1e-5b7d-4e8a-9f1c-2d3e4f5a6b7c" , "email" : "ada@example.com" , "website" : "https://ada.dev" , "age" : 34 , "rating" : 4.7 , "created_at" : "2026-03-04T10:15:30Z" , "is_active" : true , "address" : { "city" : "Lyon" , "zip" : "69001" }, "tags" : [ "early-adopter" , "beta" ] } Tool 1 — json-to-zod (npm) const user = z . object ({ id : z . string (), email : z . string (), website : z . string (), age : z . number (), rating : z . number (), created_at : z . string (), is_active : z . boolean (), address : z . object ({ city : z . string (), zip : z . string () }), tags : z . array ( z . string ()), }); Structurally correct. But every meaningful field is a bare z.string() / z.number() . This schema will happily validate email: "lol" and created_at: "yesterday" . Tool 2 — TypeMorph import { z } from " zod " ; export const userAddressSchema = z . object ({ city : z . string (), zip : z . string (). regex ( /^ [ A-Z0-9 ][ A-Z0-9 \s\-]{1,8}[ A-Z0-9 ] $/i ), }); export type UserAddress = z . infer < typeof userAddressSchema > ; export const userSchema = z . object ({ id : z . uuid (), email : z . email (), website : z . url (), age : z . number (). int (). min ( 0 ). max ( 150 ), rating : z . number (). min ( 0 ). max ( 5 ), created_at : z . iso . datetime (), is_active : z . boolean (), address : userAddressSchema , tags :

2026-06-24 原文 →
AI 资讯

TypeScript Tips That Actually Matter in Real Projects (including the satisfies operator)

Most TypeScript tutorials teach you the language. This article teaches you how to use it. There's a difference. The language has hundreds of features. A real project uses maybe twenty of them regularly, and about eight of them make up the difference between TypeScript that fights you and TypeScript that helps you. These are those eight. Each one comes from a pattern I've seen repeatedly in real codebases: first as an antipattern, then as a realization, then as a habit. The goal isn't to show off advanced type gymnastics. It's to show you the specific things that make your code safer, more readable, and less painful to maintain. TL;DR Most TypeScript pain comes from fighting the type system instead of working with it, any , manual casting, and loose types are the usual culprits. A small set of features, discriminated unions, utility types, satisfies , as const , generics, solve the majority of real-world typing problems. The best TypeScript isn't the most complex. It's the most precise. Table of Contents Tip 1: Use Discriminated Unions Instead of Optional Fields Tip 2: Stop Writing Types Twice with Utility Types Tip 3: Use satisfies to Validate Without Losing Inference Tip 4: Use as const for Literal Types That Don't Drift Tip 5: Write Type Guards Instead of Casting Tip 6: Use Generics to Write Functions Once Tip 7: Use ReturnType and Parameters to Stay in Sync Tip 8: Use unknown Instead of any for External Data Honorable Mentions Final Thoughts Tip 1: Use Discriminated Unions Instead of Optional Fields This is the tip that changes how you model data in TypeScript. Once you see it, you'll spot the antipattern everywhere. The antipattern // ❌ A type that tries to represent multiple states with optional fields interface ApiResponse { data ?: User error ?: string isLoading : boolean } The problem: this type allows impossible states. Nothing stops you from having both data and error set at the same time, or neither set, or isLoading: false with no data and no error . The

2026-06-24 原文 →
AI 资讯

The SEC has a free financial data API that nobody talks about

Every quarterly earnings number for every US public company going back to 2009 is sitting in a free, well-documented JSON API run by the US government. No API key. No rate limit for normal use. No paywall. Almost nobody in the dev community seems to know it exists. It's at data.sec.gov , and it's the same data Bloomberg charges $24k/year for. What's in it The SEC requires all US-listed companies to file financial reports in XBRL — a structured XML format where every number is tagged with a standardised concept name. The EDGAR system has been collecting these since around 2009. The companyfacts endpoint exposes all of it as clean JSON: GET https://data.sec.gov/api/xbrl/companyfacts/CIK{cik}.json Where CIK is the company's SEC identifier (10 digits, zero-padded). For Apple, that's 0000320193 . The response is a large JSON object with every concept the company has ever reported, broken down by period. The other endpoint you need is the ticker-to-CIK map: GET https://www.sec.gov/files/company_tickers.json This gives you a flat list of all US-listed companies with their CIK, ticker, and name. Load it once and cache it. One gotcha: concept names vary by company Companies don't all use the same GAAP concept names to report the same thing. Apple reports revenue as RevenueFromContractWithCustomerExcludingAssessedTax . Older companies use Revenues . Some use SalesRevenueNet . If you just look up one concept name, you'll get blanks for most companies. The fix is a concept alias map: try each name in order, use the first one that has data. const CONCEPT_MAP : Record < string , string [] > = { revenue : [ ' Revenues ' , ' RevenueFromContractWithCustomerExcludingAssessedTax ' , ' RevenueFromContractWithCustomerIncludingAssessedTax ' , ' SalesRevenueNet ' , ' SalesRevenueGoodsNet ' , ], netIncome : [ ' NetIncomeLoss ' , ' NetIncomeLossAvailableToCommonStockholdersBasic ' , ' ProfitLoss ' , ], operatingCashFlow : [ ' NetCashProvidedByUsedInOperatingActivities ' , ' NetCashProvidedB

2026-06-24 原文 →
AI 资讯

Deploying a Multi-Module Spring Boot App to Render with PostgreSQL, Redis, Docker, and Flyway

Deploying a Spring Boot backend should be simple in theory. Build the JAR, set the environment variables, connect the database, and ship it. In practice, my deployment exposed several assumptions that worked locally but failed immediately in the cloud. I recently deployed a modular Spring Boot application to Render using Docker, Render Blueprint, PostgreSQL, Redis, Flyway migrations, Spring profiles, Hibernate/JPA, and environment variables. The application worked locally with MySQL and Redis, but deployment exposed several production-specific issues that were easy to miss in local development. This article documents the problems, why they happened, and how I fixed them properly. Who This Article Is For This article is useful if you are deploying a Spring Boot application to Render and your local setup uses MySQL, Redis, Flyway, Docker, or a multi-module Maven structure. It is especially relevant if you are moving from a local MySQL setup to PostgreSQL in the cloud. The Stack The backend was a Java 17 Spring Boot application with multiple Maven modules: alagbafo/ ├── api-contracts ├── core ├── users ├── orders ├── payments ├── wallet ├── notifications ├── admin ├── subscriptions └── app The app module was the actual Spring Boot entry point. Locally, the project used MySQL and Redis: spring.datasource.url = jdbc:mysql://localhost:3306/alagbafo spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver spring.data.redis.host = localhost spring.data.redis.port = 6379 For Render, the target setup was: Spring Boot app PostgreSQL database Redis-compatible Key Value store Docker deployment Flyway migrations Render Blueprint was the best fit because it allowed the infrastructure to be described in a render.yaml file. Step 1: Dockerfile for a Multi-Module Spring Boot App Because the project was a multi-module Maven application, the Dockerfile had to copy all module pom.xml files before copying the source code. This improves Docker layer caching because dependencies can b

2026-06-23 原文 →