使用注解配置spring mvc
(1)spring mvc的配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--配置包扫描--> <context:component-scan base-package="com.chy.controller" /> <!-- 配置注解的HandlerMapping--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> <!--配置注解的HandlerAdapter--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" /> <!--配置视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/" /> <!--后缀--> <property name="suffix" value=".jsp" /> </bean> </beans>
(2)controller
//在controller上标注@Controller @org.springframework.stereotype.Controller public class UserController{ //在业务方法上标注@RequestMapping @RequestMapping("/userController") public ModelAndView handle(){ ModelAndView mav = new ModelAndView("user_info"); User user = new User(); user.setUsername("chy"); user.setPassword("abcd"); mav.addObject("user", user); return mav; } }
- controller不必实现接口,只需要在controller上标注@Controller,无需在xml中配置controller的<bean>
(使用xml配置需要在xml中配置此controller的<bean>,麻烦且xml文件冗杂)
- controller中可以有多个业务方法
(使用xml配置时controller中只能有1个业务方法,这很不方便,比如UserController,要有saveUser、updateUser、queryUser等多个方法)
- 业务方法的参数类型、返回值类型可以是任意的
(使用xml配置时参数类型、返回值都是固定的,ajax查询数据、访问静态页面,都需要返回ModelAndView,没有必要)
一般都是使用注来配置。
@RequestMapping 配置业务方法
(1)value指定此业务方法对应(映射)的url
@RequestMapping(value = "/userController") //只有value一个属性时可简写 @RequestMapping("/userController") //可以不要开头的斜杠 @RequestMapping(value = "userController") @RequestMapping("userController")
以上4种写法等价,红色标示的写法最常用。
访问路径都是:
http://localhost:8080/springmvc_war_exploded/userController //也可以在末尾加上.do http://localhost:8080/springmvc_war_exploded/userController.do
(3)method 指定请求方式
@RequestMapping(value = "/userController",method = RequestMethod.GET) @RequestMapping(value = "/userController",method = RequestMethod.POST)
只有请求地址符合,且请求方式是GET|POST时,才使用此方法处理业务。
以上2个注解分别等价于:
@GetMapping(value = "/userController") @PostMapping(value = "/userController")
(4)url映射的拼接
有时候controller中有多个业务方法:
@org.springframework.stereotype.Controllerpublic class UserController{ @RequestMapping("/userController/saveUser") public void saveUser(){ //...... } @RequestMapping("/userController/deleteUser") public void deleteUser(){ //...... } @RequestMapping("/userController/updateUser") public void updateUser(User user){ //...... } @RequestMapping("/userController/queryUser") public User queryUser(){ //...... } }
每次url都要写一长串,麻烦。
可以把共同的父路径提出来,写在controller上,业务方法上写子路径即可:
@org.springframework.stereotype.Controller @RequestMapping("/userController") public class UserController{ @RequestMapping("/saveUser") public void saveUser(){ //...... } @RequestMapping("/deleteUser") public void deleteUser(){ //...... } @RequestMapping("/updateUser") public void updateUser(User user){ //...... } @RequestMapping("/queryUser") public User queryUser(){ //...... } }
访问方式和原来一样。
业务方法的参数类型、参数个数可以是任意的,根据需要使用
常见的参数类型:
- HttpServletRequest、HttpServletResponse、HttpSession
- Model 、ModelMap(向视图传递数据)
- 简单数据类型、实体类(接收表单传递的数据)
常见的返回值类型:
- ModeAndView
- String (返回视图名)
示例 返回视图名
@RequestMapping("/userController") public String handler(){ //.... return "user_info"; }
示例 使用Model向视图传递数据
@RequestMapping("/userController") public String handler(Model model){ User user = new User(); user.setUsername("chy"); user.setPassword("abcd"); model.addAttribute("user", user); return "user_info"; }
在视图中可通过${key}的方式获取对应的value。
Model中可储存多个数据,使用多个setAttribute()即可,数据的类型可以不相同(实质是使用Map储存数据)。
示例 直接输出到浏览器
@RequestMapping("/userController") public void handler(HttpServletResponse response) throws IOException { response.getWriter().print("<h1>hello</h1>"); }
浏览器会解析里面的html标签。
注意print()才是输出到浏览器页面上,write()是想浏览器写数据,浏览器会把write()的内容保存到文件中(下载)。
转发、重定向到其它业务方法
@org.springframework.stereotype.Controller @RequestMapping("/userController") public class UserController{ @RequestMapping("/handler1") public String handler1() throws IOException { //转发给handler2处理 return "forward:handler2"; } @RequestMapping("/handler2") public void handler2(HttpServletResponse response) throws IOException { //...... } }
返回String,String本来就会被解析为视图名,我们只需在里面加上关键字:forward(转发),redirect(重定向)。
需要注意的是,springmvc本来就会把返回的字符串作为视图名解析,然后转发到对应的视图,要转发到视图(jsp、html等),直接写视图名即可,不必使用关键字forward、redirect。
如果非要用forward、redirect关键字转发到视图,配置的视图名拼接对这2个关键字无效,只能写全路径:
return "forward:/WEB-INF/jsp/user_info.jsp";
如果是转发、重定向到其它controller的业务方法,只能写全路径。
如果是转发、重定向到本controller的其它业务方法:
- 可以写全路径
return "forward:/userController/handler2";
- 也可以只写子路径,但子路径的开头不要/
不管handler2()标注为@RequestMapping("/handler2"),还是标注为@RequestMapping("handler2"),都只能这样:
return "forward:handler2";
也可以使用servlet的方式来实现:传入HttpServletRequest | HttpServletResponse类型的参数。
我在业务方法中使用了new,实际上,使用spring时,尽量不要使用new,能用依赖注入就用依赖注入。
如果是通用的bean,比如工具类,实例都一样,设计为单例,放到spring容器中,使用时写成成员变量的形式,用注解自动装配。
如果是实例不一样,比如User类,每个用户的信息是不同的,设计为多例,放到spring容器中,使用时写成成员变量的形式,用注解自动装配,可以在方法中调用bean的setter方法赋值。