26 KiB
Real Image Seed Data Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Generated sample SQL stores image URLs that point to real bundled image files in generated runnable projects.
Architecture: Keep database values as web resource URLs, not server disk paths. Add one small Java support class that owns deterministic mock image URLs, generated PNG bytes, and generated asset paths. Use that support class from SQL seed generation and from backend ZIP packaging, then update the generated file controller so /files/mock/image-01.png can be served safely.
Tech Stack: Java 8, Spring Boot generated templates, Velocity templates, ZIP packaging, JUnit 4, Mockito, MySQL seed SQL files.
File Structure
- Create:
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockImageSeedSupport.java- Owns
/files/mock/image-XX.pngURLs and generateduploads/mock/image-XX.pngPNG bytes.
- Owns
- Create:
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/MockImageSeedSupportTest.java- Verifies generated images are readable PNGs and URL/path numbering is stable.
- Modify:
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockDataSqlBuilder.java- Replaces hard-coded
/files/mock/image-N.pngvalues withMockImageSeedSupport.imageUrlForRow(row).
- Replaces hard-coded
- Modify:
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/MockDataSqlBuilderTest.java- Covers image seed URL output.
- Modify:
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenProjectServiceImpl.java- Adds bundled mock images to backend ZIP output beside the generated backend
pom.xml.
- Adds bundled mock images to backend ZIP output beside the generated backend
- Modify:
ruoyi-generator/src/test/java/com/ruoyi/generator/service/GenProjectServiceImplTest.java- Covers backend ZIP entries for
uploads/mock/image-01.pnganduploads/mock/image-10.png.
- Covers backend ZIP entries for
- Modify:
ruoyi-generator/src/main/resources/qing/fileController.java.vm- Serves nested paths under
/files/**and blocks path traversal.
- Serves nested paths under
- Modify:
ruoyi-generator/src/test/java/com/ruoyi/generator/util/QingTemplateSupportTest.java- Covers the file controller template and SQL seed copies.
- Modify:
sql/qing_templates.sql- Syncs the
FileController.java.vmtemplate seed.
- Syncs the
- Modify:
sql/db.sql- Syncs the runnable template seed copy.
Task 1: Add Mock Image Seed Support
Files:
-
Create:
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockImageSeedSupport.java -
Create:
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/MockImageSeedSupportTest.java -
Step 1: Write the failing tests
Create ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/MockImageSeedSupportTest.java:
package com.ruoyi.generator.service.front;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import javax.imageio.ImageIO;
import org.junit.Test;
public class MockImageSeedSupportTest
{
@Test
public void imageUrlsAndAssetPathsUseStableTwoDigitNames()
{
assertEquals("/files/mock/image-01.png", MockImageSeedSupport.imageUrlForRow(1));
assertEquals("/files/mock/image-10.png", MockImageSeedSupport.imageUrlForRow(10));
assertEquals("/files/mock/image-01.png", MockImageSeedSupport.imageUrlForRow(11));
assertEquals("uploads/mock/image-01.png", MockImageSeedSupport.imageAssetPathForRow(1));
assertEquals("uploads/mock/image-10.png", MockImageSeedSupport.imageAssetPathForRow(10));
}
@Test
public void createsReadablePngImagesForAllSeedRows() throws Exception
{
for (int row = 1; row <= MockImageSeedSupport.IMAGE_COUNT; row++)
{
byte[] bytes = MockImageSeedSupport.imageBytesForRow(row);
assertTrue("image bytes should not be empty", bytes.length > 1000);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
assertNotNull("image should be readable", image);
assertEquals(640, image.getWidth());
assertEquals(360, image.getHeight());
}
}
}
- Step 2: Run tests to verify failure
Run:
mvn -q -pl ruoyi-generator -Dtest=MockImageSeedSupportTest test
Expected: FAIL because MockImageSeedSupport does not exist.
- Step 3: Add the support class
Create ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockImageSeedSupport.java:
package com.ruoyi.generator.service.front;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Locale;
import javax.imageio.ImageIO;
public final class MockImageSeedSupport
{
public static final int IMAGE_COUNT = 10;
private static final int WIDTH = 640;
private static final int HEIGHT = 360;
private static final Color[] BACKGROUNDS = new Color[] {
new Color(44, 123, 229),
new Color(0, 150, 136),
new Color(255, 152, 0),
new Color(103, 58, 183),
new Color(76, 175, 80),
new Color(233, 30, 99),
new Color(63, 81, 181),
new Color(0, 121, 107),
new Color(198, 40, 40),
new Color(69, 90, 100)
};
private MockImageSeedSupport()
{
}
public static String imageUrlForRow(int row)
{
return "/files/mock/image-" + imageNumber(row) + ".png";
}
public static String imageAssetPathForRow(int row)
{
return "uploads/mock/image-" + imageNumber(row) + ".png";
}
public static byte[] imageBytesForRow(int row) throws IOException
{
int index = normalizedIndex(row);
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = image.createGraphics();
try
{
drawImage(graphics, index);
}
finally
{
graphics.dispose();
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(image, "png", output);
return output.toByteArray();
}
private static void drawImage(Graphics2D graphics, int index)
{
Color background = BACKGROUNDS[index - 1];
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(background);
graphics.fillRect(0, 0, WIDTH, HEIGHT);
graphics.setColor(new Color(255, 255, 255, 42));
graphics.fillOval(-90, -80, 260, 260);
graphics.fillOval(WIDTH - 210, HEIGHT - 180, 300, 300);
graphics.setStroke(new BasicStroke(3f));
graphics.setColor(new Color(255, 255, 255, 80));
graphics.drawRoundRect(28, 28, WIDTH - 56, HEIGHT - 56, 28, 28);
drawCenteredText(graphics, "Sample Image", new Font(Font.SANS_SERIF, Font.BOLD, 42), HEIGHT / 2 - 22);
drawCenteredText(graphics, imageNumber(index), new Font(Font.SANS_SERIF, Font.BOLD, 72), HEIGHT / 2 + 62);
}
private static void drawCenteredText(Graphics2D graphics, String text, Font font, int baseline)
{
graphics.setFont(font);
FontMetrics metrics = graphics.getFontMetrics();
int x = (WIDTH - metrics.stringWidth(text)) / 2;
graphics.setColor(Color.WHITE);
graphics.drawString(text, x, baseline);
}
private static String imageNumber(int row)
{
return String.format(Locale.ENGLISH, "%02d", normalizedIndex(row));
}
private static int normalizedIndex(int row)
{
int safeRow = Math.max(1, row);
return ((safeRow - 1) % IMAGE_COUNT) + 1;
}
}
- Step 4: Run tests to verify pass
Run:
mvn -q -pl ruoyi-generator -Dtest=MockImageSeedSupportTest test
Expected: PASS.
- Step 5: Commit
git add ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockImageSeedSupport.java ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/MockImageSeedSupportTest.java
git commit -m "feat: add bundled mock image seed support"
Task 2: Use Real Image URLs in Mock SQL
Files:
-
Modify:
ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/MockDataSqlBuilderTest.java -
Modify:
ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockDataSqlBuilder.java -
Step 1: Write the failing test
Add this test method to MockDataSqlBuilderTest:
@Test
public void imageUploadColumnsUseBundledMockImageUrls()
{
DatabaseTableDesign table = new DatabaseTableDesign();
table.setTableName("product");
table.setColumns(Arrays.asList(
column("id", "bigint(20)", "ID", "ID", "1", "1", "input", null, null),
column("cover_url", "varchar(100)", "Cover", "Cover", "0", "0", "imageUpload", null, null),
column("avatar_url", "varchar(100)", "Avatar", "Avatar", "0", "0", "avatar", null, null)));
String sql = builder.build(table);
assertTrue(sql.contains("'/files/mock/image-01.png' as `cover_url`"));
assertTrue(sql.contains("'/files/mock/image-01.png' as `avatar_url`"));
assertTrue(sql.contains("'/files/mock/image-10.png'"));
assertFalse(sql.contains("/files/mock/image-1.png"));
}
- Step 2: Run test to verify failure
Run:
mvn -q -pl ruoyi-generator -Dtest=MockDataSqlBuilderTest#imageUploadColumnsUseBundledMockImageUrls test
Expected: FAIL because the existing SQL contains /files/mock/image-1.png.
- Step 3: Replace the image branch
In MockDataSqlBuilder.valueFor, replace this branch:
if (StringUtils.inStringIgnoreCase(htmlType, "imageUpload", "avatar"))
{
return quoted(fitTextValue("/files/mock/image-" + row + ".png", column));
}
with:
if (StringUtils.inStringIgnoreCase(htmlType, "imageUpload", "avatar"))
{
return quoted(fitTextValue(MockImageSeedSupport.imageUrlForRow(row), column));
}
No import is needed because both classes are in com.ruoyi.generator.service.front.
- Step 4: Run tests to verify pass
Run:
mvn -q -pl ruoyi-generator -Dtest=MockDataSqlBuilderTest,MockImageSeedSupportTest test
Expected: PASS.
- Step 5: Commit
git add ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockDataSqlBuilder.java ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/MockDataSqlBuilderTest.java
git commit -m "feat: seed image columns with bundled file urls"
Task 3: Package Mock Images into Backend Downloads
Files:
-
Modify:
ruoyi-generator/src/test/java/com/ruoyi/generator/service/GenProjectServiceImplTest.java -
Modify:
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenProjectServiceImpl.java -
Step 1: Write the failing ZIP test
Add this test method near the existing downloadStructure... tests in GenProjectServiceImplTest:
@Test
public void downloadStructurePackagesMockImageAssetsWithBackend() throws Exception {
GenProject project = project();
project.setFrontDraft(true);
TemplateFile pomTemplate = templateFile("pom.xml.vm", "<project></project>");
pomTemplate.setTemplateId(9201L);
when(templateService.selectTemplateList(any(Template.class))).thenReturn(Arrays.asList(template(9201L, 0L)));
when(sysProjectStructureService.selectSysProjectStructureList(any(SysProjectStructure.class))).thenReturn(Arrays.asList(
structure(1L, 0L, "{projectName}", "folder", null, null),
structure(2L, 1L, "pom.xml", "file", 11L, "pom.xml.vm")
));
when(sysProjectModuleService.selectSysProjectModuleList(any(SysProjectModule.class))).thenReturn(Arrays.asList());
when(codeSnippetService.selectSysCodeSnippetList(any(SysCodeSnippet.class))).thenReturn(Arrays.asList());
when(templateFileService.selectTemplateFilesByTemplateId(9201L)).thenReturn(Arrays.asList(pomTemplate));
byte[] data = service.downloadStructure(project, "backend");
Set<String> entries = zipEntries(data);
assertTrue(entries.contains("demo-app/uploads/mock/image-01.png"));
assertTrue(entries.contains("demo-app/uploads/mock/image-10.png"));
}
- Step 2: Run test to verify failure
Run:
mvn -q -pl ruoyi-generator -Dtest=GenProjectServiceImplTest#downloadStructurePackagesMockImageAssetsWithBackend test
Expected: FAIL because backend ZIPs do not include uploads/mock/image-01.png.
- Step 3: Add import
In GenProjectServiceImpl.java, add:
import com.ruoyi.generator.service.front.MockImageSeedSupport;
- Step 4: Replace
processStructureand add helpers
Replace the existing processStructure method:
private void processStructure(List<Map<String, Object>> structure, ZipOutputStream zip, GenProject project, String type) throws IOException {
processStructureWithPath(structure, zip, project, "", type, new HashSet<String>());
}
with:
private void processStructure(List<Map<String, Object>> structure, ZipOutputStream zip, GenProject project, String type) throws IOException {
Set<String> zipEntries = new HashSet<String>();
processStructureWithPath(structure, zip, project, "", type, zipEntries);
appendMockImageAssets(zip, type, zipEntries);
}
private void appendMockImageAssets(ZipOutputStream zip, String type, Set<String> zipEntries) throws IOException {
if (!"backend".equals(type)) {
return;
}
String backendRootPrefix = backendRootPrefix(zipEntries);
if (backendRootPrefix == null) {
return;
}
for (int row = 1; row <= MockImageSeedSupport.IMAGE_COUNT; row++) {
String entryName = backendRootPrefix + MockImageSeedSupport.imageAssetPathForRow(row);
if (zipEntries.add(entryName)) {
zip.putNextEntry(new ZipEntry(entryName));
zip.write(MockImageSeedSupport.imageBytesForRow(row));
zip.closeEntry();
}
}
}
private String backendRootPrefix(Set<String> zipEntries) {
for (String entryName : zipEntries) {
if ("pom.xml".equals(entryName)) {
return "";
}
if (entryName != null && entryName.endsWith("/pom.xml")) {
return entryName.substring(0, entryName.length() - "pom.xml".length());
}
}
return null;
}
- Step 5: Run focused tests
Run:
mvn -q -pl ruoyi-generator -Dtest=GenProjectServiceImplTest#downloadStructurePackagesMockImageAssetsWithBackend,MockImageSeedSupportTest test
Expected: PASS.
- Step 6: Commit
git add ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenProjectServiceImpl.java ruoyi-generator/src/test/java/com/ruoyi/generator/service/GenProjectServiceImplTest.java
git commit -m "feat: package mock images with generated backend"
Task 4: Serve Nested Mock Image Paths
Files:
-
Modify:
ruoyi-generator/src/main/resources/qing/fileController.java.vm -
Modify:
ruoyi-generator/src/test/java/com/ruoyi/generator/util/QingTemplateSupportTest.java -
Step 1: Write the failing template test
In QingTemplateSupportTest, add this test method near the other runnable Qing template checks:
@Test
public void fileControllerTemplateServesNestedMockImagePathsSafely() throws Exception
{
String template = read(repoRoot().resolve("ruoyi-generator/src/main/resources/qing/fileController.java.vm"));
assertTrue(template.contains("@GetMapping(\"/**\")"));
assertTrue(template.contains("HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE"));
assertTrue(template.contains("Path normalizedRoot = uploadRoot.toAbsolutePath().normalize();"));
assertTrue(template.contains("if (!filePath.startsWith(normalizedRoot))"));
assertFalse(template.contains("@GetMapping(\"/{fileName:.+}\")"));
}
- Step 2: Run test to verify failure
Run:
mvn -q -pl ruoyi-generator -Dtest=QingTemplateSupportTest#fileControllerTemplateServesNestedMockImagePathsSafely test
Expected: FAIL because the template still uses @GetMapping("/{fileName:.+}").
- Step 3: Replace the file controller template content
Replace the complete content of ruoyi-generator/src/main/resources/qing/fileController.java.vm with:
package ${packageName}.controller;
import ${packageName}.common.Result;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
@RestController
@RequestMapping("/files")
public class FileController
{
private final Path uploadRoot = Paths.get("uploads");
@PostMapping("/upload")
public Result<Map<String, String>> upload(@RequestParam("file") MultipartFile file) throws IOException
{
Files.createDirectories(uploadRoot);
String originalName = StringUtils.cleanPath(file.getOriginalFilename() == null ? "file" : file.getOriginalFilename());
String suffix = "";
int dotIndex = originalName.lastIndexOf('.');
if (dotIndex >= 0)
{
suffix = originalName.substring(dotIndex);
}
String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
Files.copy(file.getInputStream(), uploadRoot.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
Map<String, String> data = new HashMap<String, String>();
data.put("name", originalName);
data.put("url", "/files/" + fileName);
return Result.success(data);
}
@GetMapping("/**")
public ResponseEntity<Resource> getFile(HttpServletRequest request) throws MalformedURLException
{
String requestPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String fileName = cleanStoredPath(requestPath);
if (!StringUtils.hasText(fileName))
{
return ResponseEntity.notFound().build();
}
Path normalizedRoot = uploadRoot.toAbsolutePath().normalize();
Path filePath = normalizedRoot.resolve(fileName).normalize();
if (!filePath.startsWith(normalizedRoot))
{
return ResponseEntity.notFound().build();
}
Resource resource = new UrlResource(filePath.toUri());
if (!resource.exists())
{
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
private String cleanStoredPath(String requestPath)
{
String storedPath = requestPath == null ? "" : requestPath;
if (storedPath.startsWith("/files/"))
{
storedPath = storedPath.substring("/files/".length());
}
else if (storedPath.startsWith("/files"))
{
storedPath = storedPath.substring("/files".length());
}
while (storedPath.startsWith("/"))
{
storedPath = storedPath.substring(1);
}
storedPath = StringUtils.cleanPath(storedPath);
return storedPath.contains("..") ? "" : storedPath;
}
}
- Step 4: Run template test
Run:
mvn -q -pl ruoyi-generator -Dtest=QingTemplateSupportTest#fileControllerTemplateServesNestedMockImagePathsSafely test
Expected: PASS.
- Step 5: Commit
git add ruoyi-generator/src/main/resources/qing/fileController.java.vm ruoyi-generator/src/test/java/com/ruoyi/generator/util/QingTemplateSupportTest.java
git commit -m "fix: serve generated mock image subpaths"
Task 5: Sync SQL Template Seeds
Files:
-
Modify:
sql/qing_templates.sql -
Modify:
sql/db.sql -
Modify:
ruoyi-generator/src/test/java/com/ruoyi/generator/util/QingTemplateSupportTest.java -
Step 1: Add SQL seed assertions
In QingTemplateSupportTest, add this test method:
@Test
public void sqlSeedFileControllerTemplatesServeNestedMockImagePaths() throws Exception
{
String qingTemplatesSql = read(repoRoot().resolve("sql/qing_templates.sql"));
String dbSql = read(repoRoot().resolve("sql/db.sql"));
assertTrue(qingTemplatesSql.contains("'FileController.java.vm'"));
assertTrue(qingTemplatesSql.contains("@GetMapping(\"/**\")"));
assertTrue(qingTemplatesSql.contains("HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE"));
assertTrue(qingTemplatesSql.contains("if (!filePath.startsWith(normalizedRoot))"));
assertFalse(qingTemplatesSql.contains("@GetMapping(\"/{fileName:.+}\")"));
assertTrue(dbSql.contains("'FileController.java.vm'"));
assertTrue(dbSql.contains("@GetMapping(\"/**\")"));
assertTrue(dbSql.contains("HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE"));
assertTrue(dbSql.contains("if (!filePath.startsWith(normalizedRoot))"));
assertFalse(dbSql.contains("@GetMapping(\"/{fileName:.+}\")"));
}
- Step 2: Run test to verify failure
Run:
mvn -q -pl ruoyi-generator -Dtest=QingTemplateSupportTest#sqlSeedFileControllerTemplatesServeNestedMockImagePaths test
Expected: FAIL because sql/qing_templates.sql and sql/db.sql still contain the old file controller template.
- Step 3: Mechanically sync the SQL template body
Run this PowerShell command from the repository root:
$templatePath = "ruoyi-generator/src/main/resources/qing/fileController.java.vm"
$template = Get-Content -Raw -Encoding UTF8 $templatePath
$escaped = $template.Replace("\", "\\").Replace("'", "''")
foreach ($path in @("sql/qing_templates.sql", "sql/db.sql")) {
$text = Get-Content -Raw -Encoding UTF8 $path
$marker = "(920107, 9201, 'FileController.java.vm', NULL, 'FileController.java.vm', '"
$start = $text.IndexOf($marker)
if ($start -lt 0) { throw "FileController template row not found in $path" }
$contentStart = $start + $marker.Length
$contentEnd = $text.IndexOf("`n', 'admin', sysdate())", $contentStart)
if ($contentEnd -lt 0) { throw "FileController template row end not found in $path" }
$updated = $text.Substring(0, $contentStart) + $escaped + $text.Substring($contentEnd)
Set-Content -Path $path -Value $updated -Encoding UTF8
}
- Step 4: Run SQL seed test
Run:
mvn -q -pl ruoyi-generator -Dtest=QingTemplateSupportTest#sqlSeedFileControllerTemplatesServeNestedMockImagePaths test
Expected: PASS.
- Step 5: Commit
git add sql/qing_templates.sql sql/db.sql ruoyi-generator/src/test/java/com/ruoyi/generator/util/QingTemplateSupportTest.java
git commit -m "chore: sync runnable file controller template seeds"
Task 6: Final Verification
Files:
-
Verify only, no file edits.
-
Step 1: Run focused Java tests
Run:
mvn -q -pl ruoyi-generator -Dtest=MockImageSeedSupportTest,MockDataSqlBuilderTest,GenProjectServiceImplTest,QingTemplateSupportTest test
Expected: PASS.
- Step 2: Verify generated SQL values
Run:
rg -n "/files/mock/image-0[1-9]\\.png|/files/mock/image-10\\.png|/files/mock/image-[1-9]\\.png" ruoyi-generator/src/main/java ruoyi-generator/src/test/java
Expected: output includes the new two-digit paths in tests or assertions, and no production Java code contains /files/mock/image- followed by a single digit.
- Step 3: Verify SQL seed copies
Run:
rg -n "HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE|@GetMapping\\(\"/\\*\\*\"\\)|@GetMapping\\(\"/\\{fileName:\\.\\+\\}\"\\)" ruoyi-generator/src/main/resources/qing/fileController.java.vm sql/qing_templates.sql sql/db.sql
Expected: output includes HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE and @GetMapping("/**"); output does not include @GetMapping("/{fileName:.+}").
- Step 4: Verify ZIP contents with the focused test already exercising bytes
Run:
mvn -q -pl ruoyi-generator -Dtest=GenProjectServiceImplTest#downloadStructurePackagesMockImageAssetsWithBackend test
Expected: PASS, proving backend downloads include demo-app/uploads/mock/image-01.png and demo-app/uploads/mock/image-10.png.
- Step 5: Check whitespace
Run:
git diff --check
Expected: no output.
- Step 6: Review final diff
Run:
git diff --stat
git diff -- ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockImageSeedSupport.java ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/MockDataSqlBuilder.java ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenProjectServiceImpl.java ruoyi-generator/src/main/resources/qing/fileController.java.vm
Expected: diff is limited to mock image support, image seed SQL path selection, backend ZIP asset packaging, nested file serving, tests, and SQL template seed copies.
Self-Review
- Spec coverage: sample image columns store
/files/mock/image-XX.png; generated backend ZIPs contain matchinguploads/mock/image-XX.pngfiles; generated file controller serves nestedmock/...resource paths; SQL template seed copies are synchronized. - Placeholder scan: all code-producing steps include concrete code or concrete replacement snippets.
- Type consistency:
MockImageSeedSupport.imageUrlForRow,imageAssetPathForRow,imageBytesForRow, andIMAGE_COUNTare used consistently across SQL builder, ZIP packaging, and tests.