zoukankan      html  css  js  c++  java
  • SpringMVC(一)概述、解析器与注解

    个人博客网:https://wushaopei.github.io/    (你想要这里多有)

    一、SpringMVC的概述

    1、概述

    Spring MVC框架是一个开源的Java平台,为开发强大的基于JavaWeb应用程序提供全面的基础架构支持,并且使用起来非常简单容易。

    Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构用于开发灵活和松散耦合的Web应用程序的组件。 MVC模式使应用程序的不同组件(输入逻辑,业务逻辑和UI逻辑)合理有效的分离,同时又有效的将各组件组合一起完成功能。

    • 模型(Model)封装了应用程序数据,通常它们将由POJO类组成。
    • 视图(View)负责渲染模型数据,一般来说它负责生成客户端浏览器可以解释HTML输出。
    • 控制器(Controller)负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。

    2、SpringMVC的核心DispatcherServlet程序

    二、SpringMVC 示例及配置

    1、SpringMVC——Hello world示例的步骤

    【1】创建一个动态web工程

    【2】导入需要的jar包

    【3】SpringMVC的 Hello 程序目录结构:

    【4】web.xml中的配置:

    <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    	<servlet>
    		<servlet-name>springDispatcherServlet</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<!-- 
    			初始化参数,配置Spring的配置文件
    		 -->
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:applicationContext.xml</param-value>
    		</init-param>
    		<!-- load-on-startup标签是在web工程启动之后就会创建Servlet程序 -->
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
    	<!-- Map all requests to the DispatcherServlet for handling -->
    	<servlet-mapping>
    		<servlet-name>springDispatcherServlet</servlet-name>
    		<!-- 支持全部的请求,包含 restful请求 -->
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    

    【5】HelloController代码:

    @Controller
    public class HelloController {
    	/**
    	 * @RequestMapping 配置一个请求地址跟方法对应<br/>
    	 * 	/hello是请求地址。表示http://ip:port/工程名/hello<br/>
    	 */
    	@RequestMapping("/hello")
    	public String hello() {
    		System.out.println("这是SpringMVC的 hello 程序!");
    		// 跳转的地址
    		return "/target.jsp";
    	}
    	
    }

    【6】页面 jsp 内容:

    index.jsp 内容:

    <a href="${ pageContext.request.contextPath }/hello">hello程序</a>

    target.jsp 内容:

    <html>
    	<head>
    		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    		<title>Insert title here</title>
    	</head>
    	<body>
    		hello 请求跳转过来啦……
    	</body>
    </html>

    【7】applicationContext.xml配置文件内容:

    	<!-- 配置包扫描 -->
    	<context:component-scan base-package="com.atguigu"></context:component-scan>

    【8】业务逻辑流程分析:

    2、SpringMVC的配置文件的另一种存放方式

    三、视图解析器

    视图解析器配置:

    	<!-- InternalResourceViewResolver 视图解析器 -->
    	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<!-- 配置前缀地址 -->
    		<property name="prefix" value="/pages/user/"/>
    		<!-- 配置后缀地址 -->
    		<property name="suffix" value=".jsp"/>
    	</bean>

    四、@RequestMapping注解详解

    1、value属性

    value属性是给方法配置一个请求地址

            /**
    	 * @RequestMapping 是给资源配置(Controller中的方法或Controller)一个访问地址。 <br/>
    	 * 	
    	 * 	value属性表示请求的地址<br/>
    	 *  value="/abc" 就表示请求地址是:http://ip:port/工程名/abc<br/>
    	 *  path属性同value作用一样,一般用value居多
    	 */
    	@RequestMapping(path="/abc")
    	public String abc() {
    		System.out.println("这是abc方法被调用了");
    		return "target2";
    	}

    2、params属性

    params是要求此请求的参数匹配

    • params="username" 表示 请求地址必须带有username参数
    • params="username=abc" 表示 请求参数中必须要有username,而且值还必须是abc
    • params="username!=abc" 表示 1、请求参数中不能有username参数。2、有username参数,但值不能等于abc
    • params="!username" 表示 请求地址不能带有username参数
    • params= {"username!=abc","!password"} params可以有多个值,每个值之间是&&关系

    以上条件表示要求:

            ( 请求地址中不能有username参数 || username参数值不能等于 abc && 不能有password参数 )

            /**
    	 * @RequestMapping 是给资源配置(Controller中的方法或Controller)一个访问地址。 <br/>
    	 * 	
    	 * 	value属性表示请求的地址<br/>
    	 *  value="/abc" 就表示请求地址是:http://ip:port/工程名/abc<br/>
    	 *  path属性同value作用一样,一般用value居多<br/>
    	 *  
    	 *  params属性表示当前请求必须要有指定参数的匹配<br/>
    	 *  params="password",表示请求中必须包含有password这个参数<br/>
    	 *  params="password=wzg168",表示请求中必须要的password参数。而且值还要等于wzg168(也就是给定值)<br/>
    	 *  params="password!=wzg168",表示两种情况,1:是可以没有password这个参数。2.如果有这个参数。值不能等于wzg168(也就是给定值)<br/>
    	 *  params="!password",表示请求中不能有此参数<br/>
    	 *  params= {"!password","username"}表示请求中,不能有password参数,必须有username参数
    	 */
    	@RequestMapping(path="/abc",params= {"!password","username"})
    	public String abc() {
    		System.out.println("这是abc方法被调用了");
    		return "target2";
    	}
    

    3、headers属性

    是匹配请求头规则

            /**
    	 * headers属性可以规则此请求中的请求头信息<br/>
    	 * headers="User-Agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
    	 * 表示当前请求必须是谷歌浏览器
    	 * @return
    	 */
    	@RequestMapping(value="/aaa",headers="User-Agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36")
    	public String aaa() {
    		System.out.println("这是aaa方法被调用了");
    		return "target2";
    	}

    4、method属性

       GET:表示GET请求

       POST:表示POST请求

       PUT:表示PUT请求

       DELETE:表示DELETE请求

    •   method 规定当前请求必须是什么请求才能访问此方法
    •  method=RequestMethod.GET 表示必须是GET请求
    •  method=RequestMethod.POST表示必须是POST请求

     GET请求演示:

            @RequestMapping(value="/bbb",method=RequestMethod.GET)
    	public String bbb() {
    		System.out.println("这是bbb方法被调用了");
    		return "target2";
    	}

    POST请求演示:

            /**
    	 * GET:表示GET请求 <br/>
    	 * POST:表示POST请求<br/> 
    	 * PUT:表示PUT请求<br/> 
    	 * DELETE:表示DELETE请求<br/>
    	 * 
    	 * method 规定当前请求必须是什么请求才能访问此方法<br/>
    	 * method=RequestMethod.GET 表示必须是GET请求<br/>
    	 * method=RequestMethod.POST表示必须是POST请求<br/>
    	 */
    	@RequestMapping(value="/bbb",method=RequestMethod.POST)
    	public String bbb() {
    		System.out.println("这是bbb方法被调用了");
    		return "target2";
    	}

    GET 请求和 POST 请求 的区别与调用方式

    5、@RequestMapping标注在Controller类上

    6、通配符在@RequestMapping中的使用

    【绝对匹配】

    创建path.jsp文件

    由地址栏输入连接方法的地址,然后进入方法,直接进行执行跳转到 path 路径下!

    该 path 路径 声明精确!

    跳转到 path页面

    @Controller
    public class PathController {
    	/**
    	 * 	精确匹配<br/>
    	 * 	value="/fun" 表示http://ip:port/工程名/fun<br/>
    	 */
    	@RequestMapping(value="/fun")
    	public String fun() {
    		System.out.println("精确匹配");
    		return "path";
    	}
    	
    }

    【2】 ?问号 匹配资源路径

    ? 问号表示一个任意字符

    	/**
    	 * ? 问号表示一个任意字符<br/>
    	 * http://ip:port/工程名/fun 或 http://ip:port/工程名/fua
    	 */
    	@RequestMapping(value="/fu?")
    	public String fun1() {
    		System.out.println("这是fun1方法被调用了   /fu? ");
    		return "path";
    	}

    【3】 * 星号 匹配资源路径

    * 星号 可以匹配任意个字符

            /**
    	 * * 星号表示任意个字符<br/>
    	 * http://ip:port/工程名/fun 或 http://ip:port/工程名/fuabc
    	 */
    	@RequestMapping(value="/fu*")
    	public String fun2() {
    		System.out.println("这是fun2方法被调用了  /fu* ");
    		return "path";
    	}

    注:当一个路径同时匹配多个规则的时候,调用方法的优先顺序是:

           绝对匹配--->>>>?问号匹配---->>>>*星号匹配

    【4】 ? 匹配一个字符目录

            /**
    	 * value="/?/fun" 这里的问题号匹配一个字符的目录<br/>
    	 */
    	@RequestMapping(value="/?/fun")
    	public String fun3() {
    		System.out.println("这是fun3方法被调用了  /?/fun ");
    		return "path";
    	}

    【5】* 星号 匹配一层目录(多个字符)

    //	 value="/*/fun"这里的星号,表示匹配一层任意多个字符的目录
    	@RequestMapping(value="/*/fun")
    	public String fun4() {
    		System.out.println("这是fun4方法被调用了  /*/fun ");
    		return "path";
    	}

    【6】* *  星星号 匹配多层目录

    	//	 value="/**/fun" 这里的星星 可以匹配多层任意的目录
    	@RequestMapping(value="/**/fun")
    	public String fun5() {
    		System.out.println("这是fun5方法被调用了  /**/fun ");
    		return "path";
    	}

    五、Controller中如何接收请求参数

    1、原生API参数类型

    【1】HttpServletRequest类

            @RequestMapping(value="/param1")
    	public String param1(HttpServletRequest request) {
    		System.out.println("reqeust对象 ===>>>" + request.getHeader("User-Agent"));
    		System.out.println("param1方法被调用了");
    		return "param";
    	}
    

    从请求头获取请求参数:

    打印结果:

    【2】HttpSession类

            @RequestMapping(value="/param2")
        	public String param2(HttpSession session) {
    		System.out.println("HttpSession对象 ===>>>" + session);
    		System.out.println("我想念晶晶姑娘啦!");
    		return "param";
    	}

    获取当前请求会话

    打印结果:

    【3】HttpServletResponse类

            @RequestMapping(value="/param3")
    	public String param3(HttpServletResponse response) {
    		System.out.println("HttpServletResponse对象 ===>>>" + response);
    		System.out.println("param3方法被调用了");
    		return "param";
    	}

            @RequestMapping(value = "/param4")
    	public String param4(HttpServletRequest request, HttpServletResponse response,
    			HttpSession session) {
    		System.out.println("reqeust对象 ===>>>" + request.getHeader("User-Agent"));
    		System.out.println("HttpSession对象 ===>>>" + session);
    		System.out.println("HttpServletResponse对象 ===>>>" + response);
    		System.out.println("param4方法被调用了");
    		return "param";
    	}
    

    2、普通类型入参

    在请求的方法上,写上类型和参数名,那么 SpringMVC模型就会自动的将参数值注入到方法的参数中。

            @RequestMapping("/param5")
    	public String param5(String username,String password) {
    		System.out.println( "请求参数username的值:" + username );
    		System.out.println( "请求参数password的值:" + password );
    		return "param";
    	}

    测试的地址是:

    http://localhost:8080/springmvc_hello/param5?username=wzg186&password=123456

    3、普通类型数组的参数

    把请求的参数名做为方法的参数名用来接收请求参数值即可。数组也一样。

    	@RequestMapping("/param6")
    	public String param6(String[] hobby) {
    		if (hobby != null && hobby.length > 0) {
    			for (String h : hobby) {
    				System.out.println("兴趣爱好:" + h);
    			}
    		}
    		return "param";
    	}

    测试地址:

    http://localhost:8080/springmvc_hello/param6?hobby=cpp&hobby=java&hobby=javaScript

    4、普通类型使用@RequestParam入参

            /**
    	 * 我们的方法参数名是username,而客户端无法(或不方便)传username的参数名。而只能传user参数,给username赋值。怎么办?<br/>
    	 * @RequestParam(name="user") 把请求的参数user的值。注入到方法参数的username。<br/>
    	 * @RequestParam注解name属性指定的值,要求客户端必须传递。否则就报错。<br/>
    	 * required属性设置请求的参数user是否必须传递。默认是true,表示必须。<br/>
    	 * defaultValue属性是默认值。也就是如果客户端没有传递user参数,则使用defaultValue来设置username的值<br/>
    	 */
    	@RequestMapping("/param7")
    	public String param7(@RequestParam(name="user",required=false,defaultValue="我是默认值,帅帅哒!!") String username) {
    		System.out.println("username的值:" + username);
    		
    		return "param";
    	}
    
    	
    	 我们的方法参数名是username,而客户端无法(或不方便)传username的参数名。而只能传user参数,给username赋值。怎么办?<br/>
    	 @RequestParam(name="user") 把请求的参数user的值。注入到方法参数的username。<br/>
    	 @RequestParam注解name属性指定的值,要求客户端必须传递。否则就报错。
    	 
    

    如果这个时候,我希望客户端哪怕没有传递user的参数的时候。也可以调用方法怎么办?

    解决一:

    修改@RequestParam注解的required=false的属性。表示这个参数不是必须传递。

    设置 defaultValue属性是默认值。也就是如果客户端没有传递user参数,则使用defaultValue来设置username的值<br/>

    5、@RequestHeader获取请求头入参

    @RequestHeader 可以把请求头的值注入到,方法参数中。

            @RequestMapping("/param8")
    	public String param8(@RequestHeader("User-Agent") String userAgent,
    			@RequestHeader("Accept") String accept) {
    		System.out.println("请求头User-Agent的值是:" + userAgent);
    		System.out.println("请求头Accept的值:" + accept);
    		return "param";
    	}

    6、@CookieValue获取Cookie值入参

    @CookieValue是可以取得客户端发送过来的某个指定了名称的Cookie的值,注入到方法参数。

            @RequestMapping("/param9")
    	public String param9(@CookieValue(name = "JSESSIONID") String jSessionId,
    			@CookieValue(name = "abcde", defaultValue = "这是晶晶姑娘") String abcde) {
    		System.out.println("获取了【JSESSIONID】Cookie的值是:" + jSessionId);
    		System.out.println("获取了【abcde】Cookie的值是:" + abcde);
    		return "param";
    	}

    7、一个Pojo对象类型的参数

    JavaBean对象

    public class Person {
    	private Integer id;
    	private String name;
    	private Integer age;
    	private String phone;

    有一个表单(表单项的name的属性值一定要跟javaBean的属性名一致

                    <form action="${ pageContext.request.contextPath }/param10">
    			id:<input name="id" /><br/>
    			name:<input name="name" /><br/>
    			age:<input name="age" /><br/>
    			phone:<input name="phone" /><br/>
    			<input type="submit" />
    		</form>

    Controller中的代码:

    	@RequestMapping("/param10")
    	public String param10(Person person) {
    		System.out.println("用户的信息:" + person);
    		return "param";
    	}

    8、对象中套对象(级联属性)

    GET请求中文乱码,找到Servers工程下Tomcat的配置文件server.xml配置文件,找到Connector标签,添加属性URIEncoding

    javaBean对象

    public class Book {
    	private String name;
    	private BigDecimal price;
    
    public class Person {
    	private Integer id;
    	private String name;
    	private Integer age;
    	private String phone;
    	private Book book;
    

    表单设置:

    <h1>添加用户</h1>
    		<form action="${ pageContext.request.contextPath }/param10">
    			id:<input name="id" /><br/>
    			name:<input name="name" /><br/>
    			age:<input name="age" /><br/>
    			phone:<input name="phone" /><br/>
    			书名:<input name="book.name" /><br/>
    			价格:<input name="book.price" /><br/>
    			<input type="submit" />
    		</form>
    
    
  • 相关阅读:
    Python 使用 environs 库来更好地定义环境变量
    五分钟带你了解map、reduce和filter
    部署React前端和Django后端的3种方法
    marshmallow库更优雅的数据转换
    利用 attrs 和 cattrs 两个库实现 Python 面向对象编程
    parse库,更友好的格式化数据提取方案
    python之prettytable模块格式化打印
    使用类型注解让 Python 代码更易读
    jksj算法训练营-第三课01 数组、链表、跳表
    linux安装java步骤
  • 原文地址:https://www.cnblogs.com/wushaopei/p/11793026.html
Copyright © 2011-2022 走看看