控制器作用
一个控制器会接收并解析用户的请求,然后把它转换成一个模型交给视图,由视图渲染出页面最终呈现给用户。Spring对控制器的定义非常宽松,这意味着你在实现控制器时非常自由。
注解实现控制器
基于注解的控制器有以下优点:
一个控制器类可以处理多个动作(而实现了Controller接口的一个控制器类只能处理一个动作),这样就减少了控制层类的数量。比如对同一个数据实体的相关操作可以定义的一个控制器类中,由@RequestMapping 将不同的action映射到不同的方法中。
基于注解的请求映射无需再在配置文件中进行映射配置
注解使用
@Controller(org.springframework.stereotype.Controller)
作用:@Controller 注解表明了一个类是作为控制器的角色而存在的。
使用@Controller首先需要完成两件事:
- 在配置文件中声明spring-context
<beans
... xmlns:context="http://www.springframework.org/schema/context"
...
>
- 应用component-scan元素指定控制器类所在包,框架会扫描指定包中@Controller注解类
<context:component-scan base-package="package-name">
@RequestMapping(org.spirngframework.web.bind.annotation.RequestMapping)
作用:@RequestMapping 将请求url映射到方法中,也可以映射到控制器类中
@RequestMapping常用属性
- value ——–>被映射路径
- method —–>RequestMethod,若多个method使用大括号
@Autowired(org.springmvcframework.beans.factory.annotation)
@Autowired 注解字段或方法可以被注入依赖
@Service(org.springframework.stereotype)
@Service注解类是一个服务,可以作为依赖注入。所以在SpringMVC框架应用过程中,往往会写一个Service层(提供一些处理方法)用来向Controller层注入
- 和@Controller的使用方法类似,需要在配置文件中配置
<context:component-scan base-package="dependencyPackage"/>
@ModelAttribute(org.springmvc.web.bind.annotation)
- 将方法参数添加到Model对象中,省去显式添加
model对象是调用处理器方法都会创建的实例对象,使用时将其添加至方法参数中
public String methodName(@ModelAttribute("key-name") ParameterType param, Model model)
- 标注非请求方法,每次调用请求方法前都会被调用
//return非void自动添加至model
@ModelAttribute
public String methodName(@RequestParame String param){
...
return string;
}
//return void
@ModelAttribute
public void methodName(@RequestParame String param, Model model){
...
model.addAttribute("key-name", value-object);
}
重定向
控制器通常都会返回一个逻辑视图名,然后视图解析器会把它解析到一个具体的视图技术上去渲染。
为何使用重定向
有时我们想要在视图渲染之前,先把一个HTTP重定向请求发送回客户端。比如一次成功的表单提交,当一个控制器成功地接受到了 POST 过来的数据,而响应仅仅是委托另一个控制器来处理时,我们希望发生一次重定向。在这种场景下,如果只是简单地使用内部转发,那么意味着下一个控制器也能看到这次 POST 请求携带的数据,这可能导致一些潜在的问题。另一种重定向需求是防止用户多次提交表单的数据。在请求被处理后浏览器会收到一个重定向响应,然后浏览器直接被重定向到一个不同的URL,最后浏览器会使用重定向响应中携带的URL发起一次 GET 请求。因此,从浏览器的角度看,当前所见的页面并不是 POST 请求的结果,而是一次 GET 请求的结果。这就防止了用户因刷新等原因意外地提交了多次同样的数据。此时刷新会重新 GET 一次结果页,而不是把同样的 POST 数据再发送一遍。使用方法
return "redirect:url" //注意url写绝对路径还是相对路径
- 重定向传递数据
@RequestMapping 方法可以声明一个 RedirectAttributes 类型的方法参数,用它来指定专门供重定向视图 RedirectView 取用的属性。如果重定向成功发生,那么 RedirectAttributes 对象中的内容就会被使用;否则则使用模型model中的数据。
请求参数
路径变量
使用路径变量
- 在@RequestMapping中添加 url/{路径变量}
- 然后在方法签名中对同名变量使用@PathVariablezhujie
- 之后路径变量就可以直接被使用
以上知识点样例代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import entity.Product;
import entity.ProductForm;
import service.ProductService;
/*
* 注解优势
* 1. 使用注解不必在进行繁琐的xml配置,框架会根据注解扫描控制器完成映射
* 2. 使用注解可以在一个Controller中实现多个请求的处理方法
* 所以可以将InputProductController和SaveProductController进行合并
*/
@Controller
public class ProductController {
@Autowired
private ProductService productServ;
@RequestMapping(value="/product_input")
public String inputProduct() {
return "ProductForm";
}
//Controller 处理方法中的参数(传入处理载体,生成传出至view的载体)
//参数列表(传入载体,转发载体)
@RequestMapping(value="/product_save", method=RequestMethod.POST)
public String saveProdcut(ProductForm proForm, RedirectAttributes redirectAttr) {
Product pro = new Product();
pro.setName(proForm.getName());
pro.setDescription(proForm.getDescription());
pro.setPrice(Float.parseFloat(proForm.getPrice()));
//add product 给form提交的product加一个id,同时生成转发url
//为了获取id值,必须返回一个product对象
Product savedPro = productServ.add(pro);
redirectAttr.addFlashAttribute("message", "This product has been added successfully");
return "redirect:/product_view/" + savedPro.getId();
}
//重定向url映射到指定视图,model传递数据
@RequestMapping(value="/product_view/{id}")
public String viewProduct(@PathVariable Long id, Model model) {
Product product = productServ.get(id);
model.addAttribute("product", product);
//视图解析器在当前路径下渲染视图,即重定向后的spirngmvc/product_view/路径
//之后根据prefix和suffix补全url访问css
return "ProductShow";
}
}