JFinal 中的Controller(1)

本文介绍了JFinal框架中的Controller概念及其作用,并详细解释了如何在Controller中定义Action方法,同时展示了getPara系列方法的使用,包括如何获取URL参数及负数参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JFinal 中的Controller(1)

概述

Controller是JFinal中的核心类之一,该类作为MVC模式中的控制器。基于JFinal的Web应用的控制器需要继承该类。Controller是定义Action方法的地点,是组织Action的一种方式,一个Controller可以包含多个Action。Controller是线程安全的。

Action

在Controller之中定义的public方法称为Action。Action是请求的最小单位。Action方法必须在Controller中定义,且必须是pubic可见性。


public class HelloController extends Controller{  
    public void index(){  
        renderText("此方法是一个Action");
    }
    public String test(){  
        return "index.html";
    }
}  

以上代码中定义了两个Action: HelloController.index()和HelloController.test()
Action可以有返回值,返回值可以在拦截器中通过invocation.getReturnValue()方法获取到,以便进行render控制。

getPara系列方法

方法调用返回值
getPara(“title”)返回页面表单域名为“title”参数值
getParaToInt(“age”)返回页面表单域名为“age”的参数值并转为int型
getPara(0)返回url请求中的urlPara参数的第一个值,如http://localhost/controllerKey/method/v0-v1-v2这个请求返回v0
getParaToInt(1)返回url请求中的urlPara参数的第二个值并转换成int型
getParaToInt(2)http://localhost/controllerKey/method/2-5-N8这个请求将返回-8.注意:约定字母N与n可以表示负号,这对urlParsSeparator为“-”时非常有用。
getPara()返回url请求中的urlPara参数的整体值,如http://localhost/controllerKey/method/v0-v1-v2 将会返回 “v0-v1-v2”

写个小例子看下,在jfinal_demo的IndexController加入这个getNumber方法:

  public void getNumber(){  
       String number = "";
        number += getPara(0) + "#";
        number += getPara(1);
        renderText("传递的参数是" + number);
  }    

启动项目,访问http://localhost:8080/getNumber/1-2
Jfinal getPara1
为了测试一下负数参数的获取,我们改一下getNumber代码

   public void getNumber(){
        String number = "";
        number += getParaToInt(0) + "#";
        number += getParaToInt(1);
        renderText("传递的参数是" + number);
    }

启动项目,访问http://localhost:8080/getNumber/n5-n10
jianl getPara2
这样的话成功获取了负数参数值。

<think>我们有一个需求:在同一个Controller中处理多个统计查询,并为每个统计项生成跳转链接。 需要在一个Controller方法中完成三个统计查询,并设置对应的跳转链接。 注意:跳转链接需要携带查询参数,以便目标页面能够重现相同的查询条件。 我们使用MyBatis-Plus的LambdaQueryWrapper来构建查询条件。 然后,将查询条件转换为URL参数字符串,并设置到返回对象中。 步骤: 1. 获取租户ID(tenantId) 2. 分别构建三个查询条件(每个查询条件包括riskLevel、status、tenantId) 3. 执行查询,获取统计数量 4. 将每个查询条件转换为URL参数字符串(注意:需要URL编码) 5. 设置每个统计项的跳转链接(例如:跳转到/warning/list页面,并带上参数) 6. 返回包含三个统计项数量和跳转链接的VO对象 假设返回的VO对象(WorkPlantVO)包含以下属性: private Integer lowarningIncomplete; // 低风险未完成数量 private String incompleteLink; // 未完成跳转链接 private Integer lowarningInProgress; // 低风险进行中数量 private String inProgressLink; // 进行中跳转链接 private Integer lowarningCompleted; // 低风险已完成数量 private String completedLink; // 已完成跳转链接 注意:在构建查询条件时,每个统计项的status条件不同: - 未完成:status IN (0,1) - 进行中:status = 1 - 已完成:status = 2 为了避免重复代码,我们可以编写一个工具方法将查询条件转换为URL参数。 代码实现:</think>### 解决方案:在单个 Controller 中实现完整功能 以下是在一个 Controller 中实现所有统计查询和跳转链接生成的完整解决方案,包含详细代码和解释: ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.util.UriComponentsBuilder; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @RestController public class RiskStatsController { private final AfterLoanRiskWarningInfoMapper warningInfoMapper; public RiskStatsController(AfterLoanRiskWarningInfoMapper warningInfoMapper) { this.warningInfoMapper = warningInfoMapper; } @GetMapping("/risk-stats") public R<WorkPlantVO> getRiskStats() { WorkPlantVO vo = new WorkPlantVO(); String tenantId = Webutil.getTenantId(); // 1. 低风险未完成统计 Map<String, Object> incompleteParams = Map.of( "riskLevel", "0", "status", Arrays.asList("0", "1"), "tenantId", tenantId ); vo.setLowarningIncomplete(executeCountQuery(incompleteParams)); vo.setIncompleteLink(buildQueryLink("/warning/list", incompleteParams)); // 2. 低风险进行中统计 Map<String, Object> inProgressParams = Map.of( "riskLevel", "0", "status", List.of("1"), "tenantId", tenantId ); vo.setLowarningInProgress(executeCountQuery(inProgressParams)); vo.setInProgressLink(buildQueryLink("/warning/list", inProgressParams)); // 3. 低风险已完成统计 Map<String, Object> completedParams = Map.of( "riskLevel", "0", "status", List.of("2"), "tenantId", tenantId ); vo.setLowarningCompleted(executeCountQuery(completedParams)); vo.setCompletedLink(buildQueryLink("/warning/list", completedParams)); return R.ok(vo); } // 执行统计查询 private int executeCountQuery(Map<String, Object> params) { LambdaQueryWrapper<AfterLoanRiskWarningInfo> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(AfterLoanRiskWarningInfo::getRiskLevel, params.get("riskLevel")) .eq(AfterLoanRiskWarningInfo::getTenantId, params.get("tenantId")); if (params.get("status") instanceof List) { List<String> statusList = (List<String>) params.get("status"); wrapper.in(AfterLoanRiskWarningInfo::getStatus, statusList); } return warningInfoMapper.selectCount(wrapper); } // 构建安全的查询链接 private String buildQueryLink(String basePath, Map<String, Object> params) { MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>(); params.forEach((key, value) -> { if (value instanceof List) { List<String> values = ((List<?>) value).stream() .map(Object::toString) .collect(Collectors.toList()); queryParams.addAll(key, values); } else { queryParams.add(key, value.toString()); } }); // 添加签名参数 String signature = SecurityUtils.generateSignature(queryParams); queryParams.add("sig", signature); return UriComponentsBuilder.fromPath(basePath) .queryParams(queryParams) .build() .toUriString(); } } // 安全工具类 class SecurityUtils { private static final String SECRET_KEY = "your-secret-key"; public static String generateSignature(MultiValueMap<String, String> params) { String canonicalString = params.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .flatMap(entry -> entry.getValue().stream() .map(value -> entry.getKey() + "=" + value)) .collect(Collectors.joining("&")); return HmacUtils.hmacSha256Hex(SECRET_KEY, canonicalString); } } // 响应对象 class R<T> { private int code; private String msg; private T data; public static <T> R<T> ok(T data) { R<T> r = new R<>(); r.code = 200; r.msg = "success"; r.data = data; return r; } // getters and setters } // 视图对象 class WorkPlantVO { private Integer lowarningIncomplete; private String incompleteLink; private Integer lowarningInProgress; private String inProgressLink; private Integer lowarningCompleted; private String completedLink; // getters and setters } ``` #### 代码解释 1. **统一入口方法**: ```java @GetMapping("/risk-stats") public R<WorkPlantVO> getRiskStats() { ... } ``` 单个端点处理所有统计查询,返回包含三个统计项和对应链接的视图对象 2. **参数化查询执行**: ```java private int executeCountQuery(Map<String, Object> params) { // 动态构建查询条件 if (params.get("status") instanceof List) { wrapper.in(AfterLoanRiskWarningInfo::getStatus, statusList); } return warningInfoMapper.selectCount(wrapper); } ``` 通用方法处理不同状态组合的查询,支持单值和多值状态 3. **安全链接构建**: ```java private String buildQueryLink(String basePath, Map<String, Object> params) { // 转换参数为MultiValueMap MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>(); // 添加数字签名 String signature = SecurityUtils.generateSignature(queryParams); queryParams.add("sig", signature); return UriComponentsBuilder.fromPath(basePath) .queryParams(queryParams) .build() .toUriString(); } ``` 使用Spring的UriComponentsBuilder安全构建URL,添加防篡改签名 4. **签名生成机制**: ```java public static String generateSignature(MultiValueMap<String, String> params) { String canonicalString = params.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .flatMap(entry -> entry.getValue().stream() .map(value -> entry.getKey() + "=" + value)) .collect(Collectors.joining("&")); return HmacUtils.hmacSha256Hex(SECRET_KEY, canonicalString); } ``` 基于HMAC-SHA256生成参数签名,确保参数不被篡改 #### 前端处理(React示例) 目标页面验证签名并执行查询: ```tsx import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import axios from 'axios'; const WarningListPage = () => { const location = useLocation(); useEffect(() => { const loadData = async () => { // 验证签名 const isValid = await verifySignature(location.search); if (!isValid) { alert('参数已被篡改!'); return; } // 解析参数 const params = new URLSearchParams(location.search); const query = { riskLevel: params.get('riskLevel'), status: params.getAll('status'), // 获取所有status值 tenantId: params.get('tenantId') }; // 执行查询 const response = await axios.get('/api/warnings', { params: query }); setData(response.data); }; loadData(); }, [location.search]); // 验证签名 const verifySignature = async (queryString: string) => { // 提取原始参数(排除sig) const params = new URLSearchParams(queryString); params.delete('sig'); // 获取服务端验证 const response = await axios.post('/api/verify-signature', { queryString: params.toString() }); return response.data.valid; }; // 渲染表格... }; ``` #### 关键优势 1. **单一职责Controller**: - 所有相关功能集中在一个端点 - 避免分散在多个Controller- 统一错误处理和日志记录 2. **参数安全机制**: - HMAC-SHA256数字签名防止参数篡改 - 租户ID自动注入确保数据隔离 - 参数编码防止XSS攻击 3. **高效查询**: - 复用查询逻辑避免代码重复 - LambdaQueryWrapper提供类型安全查询 - 批量执行减少数据库连接次数 4. **可扩展设计**: ```java // 添加新统计项只需扩展VO和参数 vo.setMediumRiskCount(executeCountQuery(mediumRiskParams)); vo.setMediumRiskLink(buildQueryLink("/warning/list", mediumRiskParams)); ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值