Spring MVC 小试牛刀

来源:互联网 发布:微信一键群发软件免费 编辑:程序博客网 时间:2024/05/04 19:36

Spring MVC是Spring框架的重要组成部分,由名字也可以看出,这是一个MVC框架,本文通过简单的例子介绍Spring MVC的搭建和配置,并对其功能作简单介绍。

Spring MVC项目的创建可以参考:
使用IntelliJ IDEA开发SpringMVC网站(一)开发环境
在这里不再赘述。

Spring MVC 框架配置

Spring MVC框架配置主要有xml配置和java配置两种方式,其中xml配置网上的资源已经比较丰富,可以参考这篇:使用IntelliJ IDEA开发SpringMVC网站(二)框架配置

这里重点介绍下采用java的配置方式。
首先在src/main/java/文件夹下创建“config” package,然后创建如下class

package config;import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;import javax.servlet.MultipartConfigElement;import javax.servlet.ServletRegistration;/** * Created by chyzh on 2016/3/19. */public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {    protected Class<?>[] getRootConfigClasses() {        return new Class<?>[] {RootConfig.class};    }    protected Class<?>[] getServletConfigClasses() {        return new Class<?>[] {WebConfig.class};    }    protected String[] getServletMappings() {        return new String[] {"/"};    }}

我们创建了一个“WebAppInitializer”class 继承了“AbstractAnnotationConfigDispatcherServletInitializer ”类,实现了三个方法。这个类的作用类似于xml配置中的“web.xml”文件,但并不相同。

这里有一个WebConfig.class类,这个class的作用很像xml配置中“xxx-servlet.xml”配置文件的作用。有了“WebAppInitializer”类,我们就无需手动创建“DispatcherServlet” 了,Spring会自动给我们创建。

再来看下class “WebConfig”,代码如下:

@Configuration@EnableWebMvc@ComponentScan("controller")public class WebConfig extends WebMvcConfigurerAdapter {    @Bean    public InternalResourceViewResolver viewResolver() {        InternalResourceViewResolver resolver =                new InternalResourceViewResolver();        resolver.setPrefix("/WEB-INF/pages/");        resolver.setSuffix(".jsp");        return resolver;    }}

可以看到,WebConfig class继承了“WebMvcConfigurerAdapter ”类。class上方 @Configuration 注解表示这是一个Spring MVC配置文件;@EnableWebMvc 注解表示开启WebMvc;@ComponentScan 注解定义了扫描Controller的基本包。
class内部,@Bean 注解定义了一个自动装配的bean,这是一个视图解析bean。其中定义了逻辑视图名称映射到jsp文件的逻辑。

接下来,在/src/main/java/下定义“controller”package,并在其中创建“WelcomeController” 类,其实现如下:

@Controller@RequestMapping("/")public class WelcomeController {    @RequestMapping(method = RequestMethod.GET)    public String hello() {        return "welcome";    }}

其中,@Controller 注解表示这是一个请求处理类,里面的每个方法都是一个请求处理方法。此外,我们看到class 头上和内部的hello方法上都有一个@RequestMapping 注解,它的作用是不一样的,在class头上的表示父路径,其中的每个方法头上的表示父路径下的一个子路径,如下面的例子:

@Controller@RequestMapping("/aaa")public class DemoController {    @RequestMapping("/bbb")    public String hello() {    //...    }}

web端要访问hello方法其路径应该是 http://www.xxx.com/context/aaa/bbb

在接着看上面的WelcomeController 类,其hello方法就是一个不同的方法,不接受任何参数,返回一个“welcome”字符串。这个返回的字符串就是逻辑视图名。SprinMVC 会把它转换成实际的jsp名称。由前面“InternalResourceViewResolver”类的定义,加上前缀和后缀,实际的jsp文件应该存储在/src/webapp/WEB-INF/pages/路径下,我们在这个路径下创建一个“welcome.jsp”的文件,内容很简单:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Welcome</title></head><body>Welcome!!!</body></html>

完成这些后,启动服务器,打开localhost:8080/ 就可以看到“Welcome!!!“了。

Spring MVC 的依赖注入

Spring的依赖注入主要使用 @Component@AutoWired 注解,但在Spring MVC中主要使用 @Service@Autowried 注解。事实上,你也可以使用 @Component 注解代替 @Service 注解。

下面的例子模拟在网站上的注册过程,重点关注下@Autowired@Service 注解的使用。
创建class “UserController” ,代码如下:

package controller;import chy.zhao.data.User;import chy.zhao.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;/** * Created by chyzh on 2016/3/22. */@Controller@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;    @RequestMapping(value = "/register", method = RequestMethod.GET)    public String register() {        return "register";    }    @RequestMapping(value = "/saveUser", method = {RequestMethod.GET, RequestMethod.POST})    public String saveUser(User user, Model model) {        userService.saveUser(user);//保存用户注册信息        model.addAttribute("user", user);        return "userInfo";    }}

这是一个控制器类,有两个方法,当访问localhost:8080/user/register/ 路径时显示注册页面,用户填入用户名和密码后,点击submit,后端获取用户填入的信息,进行相应的处理(如存入数据库)然后返回给用户注册成功信息,并显示用户注册的用户名和邮箱。

这里需要两个jsp页面,分别是 “register.jsp” 和 “userInfo.jsp”,两个页面如下:
register.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Register</title></head><body>    <form action="/user/saveUser" method="post">        <fieldset>            <legend>Register</legend>            <p>                <label for="username">Username: </label>                <input type="text" id="username" name = "username" tabindex="1">            </p>            <p>                <label for="email">Email: </label>                <input type="text" id="email" name="email" tabindex="2">            </p>            <p>                <label for="password">Password</label>                <input id="password" type="password" name="password" tabindex="3">            </p>            <p>                <input id="reset" type="reset" tabindex="4">                <input id="submit" type="submit" tabindex="5">            </p>        </fieldset>    </form></body></html>

userInfo.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>User Info</title></head><body>    <h4>Register Success!</h4>    <p>        <h5>Details</h5>        Username: ${user.username}<br/>        Email: ${user.email}    </p></body></html>

在Controller类中使用@AutoWired 注解自动注入了一个UserService类型的bean 这里bean主要用鱼处理从前端提交的请求,诸如校验数据,存入数据库等功能都有它实现,在saveUser方法中,我们在获取了User对象后调用了这个bean的saveUser方法保存用户信息。
看一下UserService 类的实现:
“`Java
package service;

import chy.zhao.data.User;
import org.springframework.stereotype.Service;

/**
* Created by chyzh on 2016/3/22.
*/
@Service
public class UserService {
public void saveUser(User user){
//…
}
}
``
可以看到 “UserService”类使用了
@Service` 注解,这样他就能通过Spring的依赖注入机制注入到UserController 类中了。
其中saveUser方法的具体实现在这里省略。

启动tomcat,打开浏览器,在地址栏输入localhost:8080/user/register 可以看到注册表单,填入信息点击submit就可以看到注册成功的页面了。

网页重定向和Flash属性

转发和重定向是有区别的,最重要的区别是转发不经过客户端而重定向经过客户端,所以转发比重定向要快。但有些时候不适合使用转发,而适合使用重定向,比如在上面的例子中,我们使用了转发,但在得到“Register Success!!!”的信息后,如果用户不小心刷新了页面,此时已经提交过的表单信息就会再次提交,这有时会带来一些问题,如注册过的用户再次进行注册,往往会出多。此时最好的办法是使用重定向使客户端重定向到另一个页面,此时再刷新不会重新提交表单。

但重定向有一个不便之处,就是不容易向视图传递参数,好在Spring MVC提供了FlashAttributes,通过它可以向视图传递参数。

我们修改UserController 类,使提交注册表单后显示注册成功页面改为重定向方式。修改后的代码为:

package controller;import chy.zhao.data.User;import chy.zhao.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.mvc.support.RedirectAttributes;/** * Created by chyzh on 2016/3/22. */@Controller@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;    @RequestMapping(value = "/register", method = RequestMethod.GET)    public String register() {        return "register";    }    @RequestMapping(value = "/saveUser", method = {RequestMethod.GET, RequestMethod.POST})    public String saveUser(User user, RedirectAttributes attributes) {        userService.saveUser(user);//保存用户注册信息        attributes.addFlashAttribute("user", user);        return "redirect:/user/userInfo";    }    @RequestMapping(value = "/userInfo", method = RequestMethod.GET)    public  String userInfo() {        return "userInfo";    }}

可以看到,我们在saveUser方法中去掉了Model参数,添加了FlashAttributes参数,通过她,添加一个键为“user”的User对象到视图,并将return方法改为了重定向方式,重定向到了“userInfo”路径。同时添加了“userInfo”方法,这个方法返回”userInfo” 字符串也就是“userInfo.jsp”页面。

此时,提交表单后再刷新页面就不会重新提交表单了。

请求参数和路径变量

请求参数和路径变量都可以用于发送值给服务器,二者都是URL的一部分,请求参数采用“key=value”的形式,中间使用“&”符号分割,在Spring MVC中我们可以通过@RequestParam 注解标注一个参数来获取请求参数的值,比如下面的URL:
localhost:8080/user/register?age=12
我们可以这样获取“age“变量:

@Controller@RequestMapping("/user")public class UserController {    @RequestMapping(value="/register", method=RequestMethod.GET)     public String register(@RequestParam int age){        System.out.println("age : " + age);        return "register";    }}

路径变量的形式为:localhost:8080/context/value,它没有key部分,只有一个值。获取路径变量使用@PathVariable

@RequestMapping("/")public String hello(@PathVariable int age) {    return "hello";}

@ModelAttribute 注解

Spring MVC在每次调用请求处理方法时,都会自动创建一个Model 类型的对象,若需要使用这个对象,我们只需在方法的参数中加上一个Model类型的对象即可,就像我们在第一个版本的例子(使用转发的那个版本)中使用的那样,通过这个Model类型的对象,我们就可以把User类型的对象传递给了视图以显示在jsp页面中。

除此之外,也可以使用@ModelAttribute 注解来访问Model实例,带有这个注解的参数会将其创建或输入的参数对象添加到Model对象中(在上面的例子中,我们是手动调用了Model的addAttribute方法)。我们在使用这个注解时,还可以为其指定一个键值,指定的方式是在注解后面的括号里添加一个表示建的字符串。

比如,我们可以把上面的例子(使用转发方式而不是重定向的那个例子)改为下面的形式:

@RequestMapping(value = "/saveUser", method = {RequestMethod.GET, RequestMethod.POST})    public String saveUser(@ModelAttribute("user") User user) {        userService.saveUser(user);//保存用户注册信息        return "userInfo";    }

这样,我们就使用”user“建添加了一个User类型的对象到”userInfo“视图中,在”userInfo“页面中就可以使用”user“键值来访问这个User对象的各个属性了。这个User中的各个参数值来自”register“输入的值。

0 0