SpringMVC页面跳转的三种方式

SpringMVC页面跳转详解
本文详细介绍了SpringMVC中实现页面跳转的三种主要方式:通过返回字符串、使用request或response对象以及利用ModelAndView对象。每种方式下又分为服务端转发、客户端重定向等具体操作,为开发者提供了全面的指导。

                                  SpringMVC页面跳转的三种方式

 

一、 根据 String 字符串跳转

1、返回字符串 --- 返回jsp页面

/**
* description: 返回字符串 --- 返回jsp页面
* @return String
* @version v1.0
* @author w
* @date 2018年10月22日 下午3:01:43
*/
@RequestMapping(value={"/forwardJsp"})
public String forwardJsp(Model model){
    model.addAttribute("name", "返回jsp页面");
    return "modules/sys/sysLogin";
}

 

2、返回字符串 --- 服务端转发

/**
* description: 返回字符串 --- 服务端转发
* @return String
* @version v1.0
* @author w
* @date 2018年10月22日 15:41:37
*/
@RequestMapping(value={"/forward"})
public String forward(Model model){
    model.addAttribute("name", "服务端转发");
    return "forward:forwardJsp";
}

 

3、返回字符串 --- 客户端重定向

/**
* description: 返回字符串 --- 客户端重定向
* @return String
* @version v1.0
* @author w
* @date 2018年10月22日 15:41:57
*/
@RequestMapping(value="/redirect")
public String redirect(){
    return "redirect:"+"/forward";
}

 

二、根据 request 或 response 进行跳转

1、返回 void --- 请求转发(request转发)

/**
* description: 返回 void --- 请求转发(request转发)
* @param request
* @param response
* @throws ServletException
* @throws IOException
* @version v1.0
* @author w
* @date 2018年10月22日 下午3:42:28
*/
@RequestMapping(value="/requestForward")
public void requestForward(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
    request.setAttribute("name", "请求转发(服务端转发)");
    request.getRequestDispatcher("/forward").forward(request, response);
}

 

2、返回 void --- 重定向 (response)

/**
* description: 返回 void --- 重定向 (response)
* @param response
* @throws IOException
* @version v1.0
* @author w
* @date 2018年10月22日 下午3:43:40
*/
@RequestMapping(value="/response")
public void response(HttpServletResponse response) throws IOException{
    response.sendRedirect("/forwardJsp");
}

 

3、返回 void --- Json字符串

/**
* description: 返回 void --- Json字符串
* @param response
* @throws IOException
* @version v1.0
* @author w
* @date 2018年10月22日 下午3:43:40
*/
@RequestMapping(value="/responseJson")
public void responseJson(HttpServletResponse response) throws IOException{
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=utf-8");
    response.getWriter().write("json串");
}

 

三、根据 ModelAndView 对象进行跳转

1、返回对象 ModelAndView --- 返回 jsp 页面

/**
* description: 返回对象 ModelAndView --- 返回 jsp 页面
* @return ModelAndView
* @version v1.0
* @author w
* @date 2018年10月22日 15:46:37
*/
@RequestMapping(value="/modelAndViewJsp")
public ModelAndView modelAndViewJsp(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("modules/sys/sysLogin");
    return modelAndView;
}

2、返回对象 ModelAndView --- 服务端转发

/**
* description: 返回对象 ModelAndView --- 服务端转发
* @return ModelAndView
* @version v1.0
* @author w
* @date 2018年10月22日 15:46:53
*/
@RequestMapping(value="/modelAndViewForward")
public ModelAndView modelAndViewForward(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("forward:/forwardJsp");
    return modelAndView;
}

 

3、返回对象 ModelAndView --- 重定向

/**
* description: 返回对象 ModelAndView --- 重定向
* @return ModelAndView
* @version v1.0
* @author w
* @date 2018年10月22日 15:47:57
*/
@RequestMapping(value="/modelAndViewRedirect")
public ModelAndView modelAndViewRedirect(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("redirect:/forwardJsp");
    return modelAndView;
}

 

 

参考资料: forward请求转发和redirect重定向的区别图解整理

 

 

 

<think>我们讨论的是字符串匹配中的跳转表(也称为坏字符表)优化。 跳转表(skip table)用于在匹配失败时,根据当前字符决定下一次匹配尝试的偏移量,从而跳过不可能匹配的位置。 具体构建算法如下: 1. 初始化一个长度为256的数组(覆盖ASCII字符),默认值为模式串长度m(对于不在模式串中的字符,直接跳过整个模式串长度)。 2. 对于模式串中的每个字符,更新表中该字符对应的值为:从该字符在模式串中最后一次出现的位置到模式串末尾的距离(即m-1-index),但注意通常我们构建的是坏字符表中更常用的是“当坏字符出现时,模式串可以向右移动的位数”,但这里我们构建的是基于首字符的跳转表,用于快速跳过非首字符。 然而,在用户的问题中,我们讨论的跳转表是用于首字符过滤的。具体来说,我们构建一个表,使得: - 如果当前字符是某个模式串的首字符,则跳转值为0(表示需要在此位置进行详细匹配)。 - 如果当前字符不是任何模式串的首字符,则跳转值为1(或其他值,可以设置为跳过该字符,即前进1位);但更优化的做法是,可以跳过尽可能多的字符,即跳过整个模式串长度(因为如果当前字符不是首字符,那么以这个字符开始的位置不可能匹配,所以可以跳过模式串长度,但要注意不能跳过超过模式串长度,因为可能跳过了匹配位置)。 但是,在之前的优化方案中,我们构建的跳转表主要是为了快速跳过非目标字符。具体构建步骤: 步骤1:初始化一个数组(假设为skip),大小为256(覆盖所有字节值),设置默认值为1(即每遇到一个非关注字符,我们前进1位)。 步骤2:对于每一个模式串的首字符,将表中对应的值设为0。这样,当遇到这些字符时,我们不跳过,进行详细匹配。 但是,为了更高效地跳过,我们可以利用坏字符规则,即如果当前字符不在模式串中,则可以跳过模式串长度。但是注意这里我们只关心首字符,所以实际上我们可以这样构建: - 对于所有字符,默认跳转值为1(即安全地每次前进1位,因为即使是非首字符,也可能出现在模式串中间,所以不能直接跳过整个模式串长度,除非我们确定该字符在模式串中任何位置都不出现?) 然而,在之前的描述中,我们只关注首字符,所以非首字符我们就直接跳过(前进1位),这样虽然保守但是安全。另一种更高效的跳转表(坏字符表)可以基于整个模式串构建,但这里我们只用于首字符过滤。 因此,具体构建算法如下: skip_table = [1] * 256 # 初始化所有字符跳1位 # 将每个模式串的首字符在跳转表中设为0 for pattern in pattern_list: first_char = pattern[0] skip_table[ord(first_char)] = 0 # 注意:如果多个模式串,那么多个首字符都要设为0 然后,在匹配循环中: for i in range(0, n): # 如果当前字符应该跳过(即skip_table[current_char]不为0),那么我们就跳过相应的步数 # 但是注意,我们的跳转表默认值为1,所以非首字符都会跳过1位。而首字符则进入详细匹配。 但是,为了更高效地跳过,我们可以设定非首字符的跳转值更大。例如,如果我们确定了某个字符在模式串中任何位置都不存在,那么我们可以直接跳过模式串长度。但这样需要构建一个包含整个模式串字符集的表。 因此,我们可以构建两种跳转表: 1. 首字符跳转表(用于快速检测是否可能匹配): skip_table[char] = 0 当char是某个模式串首字符 skip_table[char] = 1 否则(即非首字符,则跳过1位) 2. 坏字符跳转表(用于详细匹配失败时的跳转): 这里我们暂时不讨论,因为用户问题只问了首字符过滤的跳转表。 对于未出现字符(即不在任何模式串首字符中的字符)的处理: 在首字符跳转表中,我们设置为非0(例如1),表示跳过1位。因为我们不知道这个字符是否在模式串的其他位置出现,为了安全起见,我们只跳过1位。 但是,如果我们可以确定该字符在整个模式串中都不存在(构建一个模式串字符集),那么我们可以跳过模式串长度(即m),这样效率更高。然而,在首字符过滤阶段,我们只构建首字符表,所以为了安全,我们只跳过1位。 另一种更高效的跳转表构建(结合坏字符规则): 构建一个表bad_char,对于每个字符c: 如果c不在模式串中,则bad_char[c] = 模式串长度m 如果c在模式串中,则bad_char[c] = 从模式串尾部开始第一次出现c的位置到末尾的距离(即m-1-index,但注意是最后一次出现的位置) 但在首字符过滤中,我们并不使用整个模式串的坏字符表,而是使用首字符表来快速跳过非首字符。 总结:首字符跳转表的构建非常简单,就是将所有模式串的首字符对应的表项设为0,其他字符设为1(表示跳过1位)。这样,只有遇到首字符才会进入详细匹配,否则跳过1位。 但是,我们可以结合两种跳转表:先用首字符跳转表快速跳过非首字符,然后在详细匹配失败时,使用坏字符跳转表进行更大的跳转。 因此,回答用户问题: 跳转表skip[]的具体构建算法: 初始化:对于所有字符,skip[char] = 1 (默认跳过1位) 遍历每个模式串的首字符c:skip[c] = 0 (表示遇到c时不跳过,进行详细匹配) 对于未出现字符(即不是任何模式串首字符的字符): 已经设置为1,即跳过1位。 如果我们想要更高的跳过效率,可以同时构建坏字符表,用于详细匹配失败后进行更大的跳转。但是在首字符过滤阶段,我们只使用上述跳转表。 注意:在多模式匹配的情况下,我们只需要将每个模式串的首字符都设置为0即可。 示例:模式串["abc", "def"] skip表:对于字符'a','d'设置为0,其他字符设置为1。 在循环中: i = 0 while i < n: if skip[input[i]] == 1: i += 1 # 跳过1位 continue else: # 检查以i开始的是否匹配任何一个模式串 # 例如,检查input[i:i+3]是否等于"abc"或"def" # 如果匹配,则处理并跳过这个模式串长度 # 如果不匹配,则i+=1(或者使用坏字符规则跳转,但这里是首字符过滤,失败后我们只前进1位) # 注意:这里也可以使用坏字符规则进一步跳转,但需要额外的表。 因此,在详细匹配失败后,我们并没有利用坏字符规则,而是简单前进1位。这是因为我们只构建了首字符跳转表,没有构建整个模式串的坏字符表。 所以,在回答中,我们要明确: 跳转表skip[]的具体构建算法: 1. 初始化一个长度为256的整数数组,所有元素初始化为1。 2. 对于给定的模式串集合,提取每个模式串的首字符。 3. 对于每个首字符,将其ASCII值作为索引,将跳转表中对应位置的值设为0。 处理未出现字符:由于初始化时所有字符对应的跳转值都是1,所以未出现在模式串首字符中的字符自然会被跳过1位。 但是,如果我们希望更高效(利用坏字符规则),那么可以构建一个完整的坏字符跳转表,但这是另一个话题。 因此,回答如下: </think>### 跳转表 skip[] 构建算法详解 #### 跳转表构建原理 跳转表(Skip Table)是字符串匹配中的预处理结构,核心目标是通过字符分析**减少无效匹配尝试**。其构建算法如下: ```c // 伪代码:跳转表构建算法 void build_skip_table(const char *pattern, int m, char skip_table[256]) { // 步骤1:初始化默认值(最大跳跃幅度) for (int i = 0; i < 256; i++) { skip_table[i] = m; // 默认跳过整个模式串长度 } // 步骤2:处理模式串中的字符 for (int j = 0; j < m - 1; j++) { skip_table[(unsigned char)pattern[j]] = m - 1 - j; } // 步骤3:特殊处理首字符(必须设为0) skip_table[(unsigned char)pattern[0]] = 0; } ``` #### 算法步骤解析 | 步骤 | 操作 | 数学表示 | 目的 | |------|------|----------|------| | **初始化** | 所有字符设为m | `∀c ∈ [0,255]: skip[c]=m` | 非模式字符跳过整个模式串 | | **模式处理** | 更新模式串字符 | `∀p_j (0≤j<m-1): skip[p_j]=m-1-j` | 失败时根据位置跳转 | | **首字符处理** | 强制设首字符为0 | `skip[p₀]=0` | 确保首字符触发详细匹配 | #### 未出现字符处理原理 1. **默认值机制**: - 所有未在模式串中出现的字符,保持初始化值`skip[c]=m` - 示例:模式串"tp-eth."中字符'z'的跳转值=7 2. **跳转逻辑**: ```c // 匹配主循环 for (int i = 0; i < n; ) { int skip_step = skip_table[(unsigned char)input[i]]; if (skip_step > 0) { i += skip_step; // 跳跃前进 continue; // 跳过详细匹配 } // 首字符匹配时才执行详细匹配... } ``` 3. **处理效果对比**: | 字符类型 | 跳转值 | 处理方式 | 示例输入 `"a1#tp"` | |----------|--------|----------|---------------------| | **首字符** ('t') | 0 | 触发详细匹配 | `'t'`→执行memcmp | | **模式字符** ('-') | 4 | 跳转指定步长 | `'1'`→跳1位(默认值) | | **未出现字符** ('#') | 7 | 跳整个模式长度 | `'#'`→直接跳7位 | #### ASCII表示例(模式串:"tp-eth." m=7) | 字符 | ASCII | 跳转值 | 计算逻辑 | |------|-------|--------|----------| | **t** (p₀) | 0x74 | 0 | 首字符强制0 | | **p** (p₁) | 0x70 | 5 | m-1-1 = 5 | | **-** (p₂) | 0x2D | 4 | m-1-2 = 4 | | **e** (p₃) | 0x65 | 3 | m-1-3 = 3 | | **t** (p₄) | 0x74 | 2 | m-1-4 = 2 | | **h** (p₅) | 0x68 | 1 | m-1-5 = 1 | | **.** (p₆) | 0x2E | - | 未处理(默认值生效) | | **其他字符** | - | 7 | 保持初始化值 | ### 关键技术点 1. **无回溯设计**: - 跳跃决策仅依赖当前字符,无历史状态 - 每个字符只访问一次,保证O(n)复杂度 2. **字节级处理**: - `(unsigned char)`强制转换确保255范围 - 兼容所有8-bit编码(ASCII/UTF-8单字节) 3. **多模式扩展**: ```c // 多模式跳转表构建 void build_multi_skip(char *patterns[], int k, char skip_table[256]) { int max_len = find_max_length(patterns, k); for(int i=0; i<256; i++) skip_table[i] = max_len; for(int p=0; p<k; p++) { int m = strlen(patterns[p]); skip_table[patterns[p][0]] = 0; // 所有首字符设为0 for(int j=0; j<m-1; j++) { // 取各字符最小跳转值 skip_table[patterns[p][j]] = min(skip_table[patterns[p][j]], m-1-j); } } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值