Spring MVC 简明教程

164929_ZVVO_3452433.png

简介

Spring MVC 属于Spring Framework项目中的一部分。主要用于组建MVC结构的项目。比较类似于Struts的功能。而且Spring MVC对于目前比较流行的RESTful架构风格支持的也是比较好的。

官方网站:http://projects.spring.io/spring-framework/

 

原理

DispatcherServlet类是spring mvc的核心控制器,负责分发和响应用户请求。

DispatcherServlet请求处理工作流程如下图所示:

144530_ZGPJ_3452433.png

1、用户将request请求发送至前端控制器(Front controller)

2、前端控制器将请求转发至具体的业务控制器(Controller)

3、业务控制器创建业务逻辑实现(Service)和数据

4、业务控制器(Controller)将结果返回给前端控制器(Front controller)

5、前端控制器(Front controller)选择展示模板(View template)

6、最后将结果通过前端控制器(Front controller)返回给客户

DispatcherServlet继承于HttpServlet,所以它拥有HttpServlet所有特征。

 

加载依赖

由于本人惯用spring boot进行项目构建,所以配置默认都是spring boot的方式

只要在项目中依赖springframework的包就可以使用Spring MVC

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.9.RELEASE</version>
    </dependency>
</dependencies>

如果你使用spring boot来搭建项目,那么是不需要以上依赖的,因为springboot的依赖已经包含他了

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

 

DispatcherServlet拦截配置

DispatcherServlet的url-pattern默认情况下为“/”根路径,所有的url请求都会被DispatcherServlet处理。但是我们可以对url-pattern进行配置。

在spring boot的配置文件application.properties中进行配置

#拦截所有以.do结尾的路径
server.servlet-path=*.do

#拦截所有springmvc目录下的路径
server.servlet-path=/springmvc/*

这里需要注意,项目中的RequestMapping请求路径不能包含拦截内容。比如 拦截路径为“server.servlet-path=/springmvc/*“,RequestMapping为“/index”,那么请求路径为http://localhost:8090/springmvc/index

 

 

注解

 

@Controller

此注解声明了一个Controller层的类,使用此注解的类会被识别为一个控制器。

@Controller
public class StartController {

}

在此例子中我们不用将类声明为一个bean,因为spring boot在初始化时使用了@ComponentScan注解进行自动扫描并注入。

 

@RestController

此注解声明一个类为Restful风格的控制器。其实就是@Controller和@ResponseBody两个注解叠加的效果。

@RestController
public class StartController {

    @PostMapping(value = "/login1")
    public User login1(@RequestBody User user1) {
        User user = new User();
        user.setUsername(user1.getUsername());
        user.setPassword(user1.getPassword());
        return user;
    }

}
  • @RestController注释的类中,所有的方法默认添加@ResponseBody,会将内容放在http主体中返回。

 

@RequestMapping

此注解声明了一个可访问的资源映射,url可以通过RequestMapping配置的映射路径来访问这个方法。

参数:

value(默认)

访问该资源的URI路径。资源路径支持通配符访问。(如例5)

此参数可以不写则为默认访问。(如例1)

该参数可以设置URI形式的入参,入参使用{}进行表示。在方法参数中使用@PathVariable可以将URI参数映射给一个方法入参。(如例4)

method

指定http的提交类型。一般使用RequestMethod类来指定类型。

常用的基本上就是RequestMethod.GET和RequestMethod.POST。(如例2、3)

consumes

指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces

指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;(如例6)

在做接口时往往使用此参数指定接口出参数据结构类型。

params指定request中必须包含某些参数值是,才让该方法处理。
headers指定request中必须包含某些指定的header值,才能让该方法处理请求。

括号内只写参数值,则代表此参数是默认参数的值。

例子: 

@RequestMapping("/home")
public class StartController {

    @RequestMapping
    public String index(Model model) {
        return "index";
    }

    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String login(Model model) {
        return "login";
    }

    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String loginPost(Model model) {
        return "login";
    }

    @RequestMapping(value = "/{parameter}",method = RequestMethod.GET)
    public String parameter(@PathVariable("parameter") String urlParameter, Model model) {
        return "login";
    }

    @RequestMapping(value = "/*/login",method = RequestMethod.GET)
    public String login(Model model) {
        return "login";
    }

    @RequestMapping(value = "/login1", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public String login1(Model model) {
        return "login";
    }
}

 

  • RequestMapping可以标识一个类或一个方法,在类上时代表这个类内所有资源都在该路径下。在方法上时代表该方法的访问路径。如例2的路径为“/home/login”
  • RequestMapping有一些变种注解,如@GetMapping、@PostMapping等。此类注解省去了method参数。@GetMapping相当于@RequestMapping(method = RequestMethod.GET)

 

@PathVariable 

此注解用于获取URI形式的参数,参数作为路径的一部分被传递过来。

参数:

value(默认)

URI形式参数的名称。也就是@RequestMapping注解使用“{}”来标注的参数名称。

此参数不写,则要求方法入参名称与URI参数名称一致。(如例3)

括号内只写参数值,则代表此参数是默认参数的值。(如例二)

例子: 

 @RequestMapping(value = "/{parameter}")
 public String parameter(@PathVariable(value = "parameter") String urlParameter, Model model) {
     return "login";
 }

 @RequestMapping(value = "/{parameter}")
 public String parameter(@PathVariable("parameter") String urlParameter, Model model) {
     return "login";
 }

 @RequestMapping(value = "/{parameter}")
 public String parameter(@PathVariable String parameter, Model model) {
     return "login";
 }

 

@RequestParam

获得request请求参数并绑定到方法参数上,get请求时使用此注解获取参数。

参数:

value(默认)

请求参数名称。

此参数不写,则要求方法入参名称与请求参数名称一致。(如例2)

required是否必输。默认情况下是true必输,如果希望那个参数为非必输就设置成false(如例3)

括号内只写参数值,则代表此参数是默认参数的值。(如例1)

例子: 

    //以下例子的url参数为?username=andy&password=111111

    @GetMapping(value = "/login1")
    public String login1(@RequestParam("username") String username ,@RequestParam("password") String password) {
        return "login";
    }

    @GetMapping(value = "/login2")
    public String login2(@RequestParam String username ,@RequestParam String password) {
        return "login";
    }

    @GetMapping(value = "/login3")
    public String login3(@RequestParam String username ,@RequestParam(required=false) String password) {
        return "login";
    }

    @GetMapping(value = "/login4")
    public String login4(@RequestParam Map user) {
        return "login";
    }
  • @RequestParam的参数可以使用map接收,url的入参名和值,会以键值对的形式存储在map中(如例4)

 

@RequestHeader

获取request头信息。

参数:

value(默认)

请求头参数名称。

此参数不写,则要求方法入参名称与请求头参数名称一致。(如例2)

required是否必输。默认情况下是true必输,如果希望那个参数为非必输就设置成false(如例5)

括号内只写参数值,则代表此参数是默认参数的值。(如例1)

例子: 

    @GetMapping(value = "/login1")
    public String login1(@RequestHeader("Host") String host) {
        return "login";
    }

    @GetMapping(value = "/login2")
    public String login2(@RequestHeader String Host) {
        return "login";
    }

    @GetMapping(value = "/login3")
    public String login3(@RequestHeader("Accept-Encoding") List<String> encoding ) {
        return "login";
    }

    @GetMapping(value = "/login4")
    public String login4(@RequestHeader Map<String,String> header) {
        return "login";
    }

    @GetMapping(value = "/login5")
    public String login5(@RequestHeader(value = "Host",required=false) String host) {
        return "login";
    }
  • @RequestHeader可以使用list接收一组用逗号分割的值(如例3)。如“gzip,deflate” 就会被list拆分接收。
  • @RequestHeader可以使用Map来接收所有的头信息,头信息会以键值对的形式存储在map中(如例4)。

 

@RequestBody

获取request请求,http主体内的参数,post请求时使用此注解获取参数。

参数:

required是否必输。默认情况下是true必输,如果希望那个参数为非必输就设置成false(如例2)

例子: 

    @PostMapping(value = "/login1")
    public String login1(@RequestBody User user) {
        return "login";
    }

    @PostMapping(value = "/login2")
    public String login2(@RequestBody(required=false) User user) {
        return "login";
    }
  • @RequestBody将http主体中的数据转换到入参对象中(如例1)。
  • http主体的形式由http Content Type定义。一般为application/json或application/xml
  • @RequestBody入参接收对象中的属性名要求与http主体中的变量名一致。如:User类定义了usernam和password两个属性,那么json 形式的http body就应该写成{"username":"myuser","password":"111111"}

 

@ResponseBody

将响应内容直接放在http主体中返回。通常的@Controller方法返回的是视图名称,并跳转到这个视图。

    @PostMapping(value = "/login1")
    @ResponseBody
    public User login1(@RequestBody User user1) {
        User user = new User();
        user.setUsername(user1.getUsername());
        user.setPassword(user1.getPassword());
        return user;
    }
  • @ResponseBody经常用于ajax请求和接口方法。因为ajax请求和接口方法要求直接返回内容而不是跳转到某一视图。

 

@SessionAttributes(不常用)

用于获取session中的参数。

@SessionAttributes作用于类的时候,会在方法执行结束时将对应名字的model内容存储到session中。(如例1)

@SessionAttributes作用于参数的时候,会取出session中对应名字的内容,赋值给当前的参数。(如例2)

参数:

value(默认)

session中的参数名称。

此参数不写,则要求方法入参名称与请求参数名称一致。(如例3)

括号内只写参数值,则代表此参数是默认参数的值。(如例2)

例子: 

@Controller
@RequestMapping(value = "/home")
@SessionAttributes("username")
public class StartController {
    @PostMapping(value = "/login1")
    public String login1(HttpSession httpSession,Model model) {
        model.addAttribute("username","woshicanshu");
        return "login";
    }

    @PostMapping(value = "/login2")
    public String login2(@SessionAttribute("user") User user, HttpSession httpSession) {
        return "login";
    }

    @PostMapping(value = "/login3")
    public String login3(@SessionAttribute User user, HttpSession httpSession) {
        return "login";
    }
}

 

@RequestAttribute(不常用)

获取request的参数。@RequestAttribute作用于参数的时候,会取出request中对应名字的内容,赋值给当前的方法入参。

参数:

value(默认)

request中的参数名称。

此参数不写,则要求方法入参名称与请求参数名称一致。(如例2)

括号内只写参数值,则代表此参数是默认参数的值。(如例1)

例子: 

    @PostMapping(value = "/login1")
    public String login1(@RequestAttribute("username") String username,HttpRequest request) {
        return "login";
    }

    @PostMapping(value = "/login2")
    public String login2(@RequestAttribute String username,HttpRequest request) {
        return "login";
    }

 

@ModelAttribute(不常用)

将参数保存到Model模型中,供视图页面使用。

  • 作用于参数时表示这个参数保存到model中。(如例1)
  • 作用于方法时表示将这个方法的出参保存到model中,此方法会在执行任意一个@RequestMapping之前执行一次。(如例2)

参数:

value(默认)

model中的参数名称。

括号内只写参数值,则代表此参数是默认参数的值。(如例1)

例子: 

    //本例请求参数为 ?username=pltx

    @GetMapping(value = "/login1")
    public String login1(@ModelAttribute("username") String username,Model model) {
        return "login";
    }

    @ModelAttribute("password")
    public String login2(String username) {
        return "000000";
    }

 

@RequestPart(不常用)

用于获取使用multipart/form-data格式传递的http请求的请求体,通常用于获取上传文件。

 

@Autowired

用于在类中注入bean。

@Autowired
private Activity2CompanyDao activity2CompanyDao;

 

@Repository

用于声明此类为一个数据库持久化类(DAO层)。

@Repository
public class Activity2ConsumerCouponDaoImpl implements Activity2ConsumerCouponDaoCustom{

}

 

@Service

用于声明一个业务层的类。

@Service
public class Activity2ConsumerService {

}

 

 

Controller层

Controller层是项目的转向控制层,主要负责接收请求、转发请求到业务层(service)进行处理、将处理结果进行响应、控制页面跳转等职责。

需要注意涉及到业务逻辑的代码尽量不要在Controller进行编写,将业务逻辑合理的封装在service层对项目的结构和复用性都是非常有益的。

Controller层主要常用的注解有@Controller、@RequestMapping、@Autowired、@RequestParam、@RequestHeader、@RequestBody、@ResponseBody等。

 

默认绑定的参数

Controller层的方法入参可以获得默认绑定的类的实例,这实例我们可以通过形参的声明直接使用。其中主要包括HttpServletRequest、HttpservletResponse、HTTPSession、Model、ModelMap以及他们的衍生类。

HttpServletRequest

此参数可以获得一个HttpServletRequest实例。

@RequestMapping("/unauthorized")
public String unauthorized(HttpServletRequest request, HttpServletResponse response) {

}

 

HttpServletResponse

此参数可以获得一个HttpservletResponse实例。

@RequestMapping("/unauthorized")
public String unauthorized(HttpServletRequest request, HttpServletResponse response) {

}

 

HTTPSession

此参数可以获得一个HTTPSession实例。

@RequestMapping("/unauthorized")
public String unauthorized(HTTPSession session) {

}

 

Model/ModelMap

Model用于将模型数据传递到展示层,保存在Model中的数据可以直接在页面使用获取。

@RequestMapping(value = "/list", method = RequestMethod.GET)
public String list(String name, Integer openType, Model model) {

    model.addAttribute("name", name);
    model.addAttribute("openType", openType);

    return "/activity2_company/list";
}

 

RedirectAttributes

model的Attribute参数传递的声明周期为一次请求。所以如果方法采用重定向到其他资源则Attribute保存的参数将会丢失,在页面是无法获取的。如果想要在重定向后在页面获取参数则需要使用  RedirectAttributes进行保存。

下面的例子在login页面仍然可以拿到message参数值。

@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(RedirectAttributes redirectAttributes) {
    redirectAttributes.addFlashAttribute("message", "您已安全退出");
    return "redirect:login"; 
}

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginInput() {
   
    return "login";
}

RedirectAttributes中有两个添加参数的方法addAttribute和addFlashAttribute ,addAttribute参数会被放在url中进行传递,所以长度和类型会受到限制。而addFlashAttribute 参数放在flashmap内部对象中传递,对于长度和类型没有限制。

 

在重定向的方法中如果想要拿到,前面方法存入的addAttribute参数,只要在重定向方法入参加入这个参数即可

 @GetMapping(value = "/login")
    public String login(RedirectAttributes redirectAttributes) {
        redirectAttributes.addAttribute("username","andy");
        return "redirect:login1";
    }

    @GetMapping(value = "/login1")
    public String login1(String username) {
        System.out.println(username);
        return "login";
    }

在重定向的方法中如果想要拿到,前面方法存入的addFlashAttribute参数,则需要使用@ModelAttribute注解

    @GetMapping(value = "/login")
    public String login(RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("username","andy");
        return "redirect:login1";
    }

    @GetMapping(value = "/login1")
    public String login1(@ModelAttribute("username") String username) {
        System.out.println(username);
        return "login";
    }

 

响应方式

返回到页面

Controller方法的出参直接写视图名称,则代表执行结束后调转到此视图。(加ResponseBody不行)

如下例将访问login页面

@GetMapping(value = "/login")
public String login() {
    return "login";
}

 

跳转到其他Controller

Controller方法的出参可以通过增加forward和redirect前缀的方式进行转发或重定向到,其他Controller。

    @GetMapping(value = "/login")
    public String login() {
        return "login";
    }

    @GetMapping(value = "/login1")
    public String login1() {
        return "redirect:login";
    }

    @GetMapping(value = "/login2")
    public String login2() {
        return "forward:login";
    }

强调一下forward和redirect区别。forward是服务器转发,浏览器地址不变,服务器将请求的新地址内容返回给刘蓝鳍。redirect是浏览器重定向,浏览器地址改变,服务器告诉浏览器要访问新的地址后浏览器重新访问新地址。

 

输出到页面

我们可以使用HttpServletResponse对象将内容直接输出到页面

    @GetMapping(value = "/login")
    public void login(HttpServletResponse response) {
        try {
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            response.getWriter().println("<h1>我是标题</h1>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

转载于:https://my.oschina.net/u/3452433/blog/1456869

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值