(JavaEE)SpringMVC

                                     (JavaEE)SpringMVC


今天就把我学到的SpringMVC的知识,我认为对我来说比较重要的贴出来,做个记录方便以后查看。

预备:

-1).导入SpringMVC的基本包(包括依赖包) -> 

-2).编写Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">
	<display-name>SpringMVCExperience</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>

	<!-- 配制字符编码过滤器 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<!-- 配置SpringMVC的 DispatcherServlet 请求分发器 -->
	<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:SpringMVC.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<!-- 配置REST风格的 HiddenHttpMethodFilter -->
	<filter>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

-3).编写SpringMVC.xml配置文件

<?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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">

<!-- 
	配置 SpringMVC 的扫描组件
-->
<context:component-scan base-package="com.YHStudio.SpringMVCcom.YHStudio.SpringMVC"></context:component-scan>

<!-- 
	配置 SpringMVC 的视图解析器	
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/views/" />
	<property name="suffix" value=".jsp" />
</bean>

<!-- 
	
-->

</beans>

项目目录结构:

一、SpringMVC - HelloWorld

-1).先在WebContent目录下新建一个名为index.jsp的文件里面我们做一些测试

-2).在controller包下新建一个DealDataController.java文件 -> 内容

@Controller
@RequestMapping(value="dealData")
public class DealDataController {

	private static final String SUCCESS = "success";
	
	@RequestMapping(value="testSpringMVCHelloWorld")
	public String testSpringMVCHelloWorld() {
		System.out.println("testSpringMVCHelloWorld ...");
		return SUCCESS;
	}
}

其中@Controller注解就是标识DealDataController类被Spring IOC容器进行管理。

@RequestMapping注解就是设置我们的控制器方法的请求映射 -> value属性就指定了映射名称

这个控制器方法我们最后返回一个字符串success;

请看index.jsp文件中的内容

-3).然后在WEB-INF下面新建一个views文件夹里面新建一个名字为success.jsp文件

来我们运行程序并点击超链接

可以看到成功的跳转到了success.jsp

看看控制台打印 

这说明:其运行流程是这样的 -> 前台发来请求被我们配置在web.xml中的dispatcherServlet截获,并且加载SpringMVC.xml文件,对我们的包进行扫描,查找有无与请求路径相符合的控制器方法的请求映射,如果正好找到就会执行该方法,控制器方法返回一个字符串被SpringMVC.xml文件中的视图解析器进行解析,实际上就是将其路径拼接出来再进行请求转发。

当然返回的字符串与views目录下面的jsp文件名务必对应。

二、SpringMVC - @RequestMapping剩下3个属性

-1).method属性可以控制请求的方式,如果我设置仅仅接收post请求就算你的请求地址都对但你是get请求我也照样不接受你!

这次仅贴出方法

@RequestMapping(value="testSpringMVCHelloWorld", method = RequestMethod.POST)
	public String testSpringMVCHelloWorld() {
		System.out.println("testSpringMVCHelloWorld ...");
		return SUCCESS;
	}

老样子看看这次是否可以接收到a标签默认的GET请求:

运行程序,点击链接,发现:

路径与上次一样都没进去,这就是因为我们只接受POST请求所以你发送GET请求是不行的。

当然RequestMethod支持POST、GET、PUT、DELETE四种请求类型,至于(PUT、DELETE)请求我们后面再说。

-2).params属性可以控制接收的参数,如果参数不符合条件我也不接受你的请求。

仅仅贴出方法

	@RequestMapping(value="testSpringMVCHelloWorld", method = RequestMethod.GET, params = {"age!=10"})
	public String testSpringMVCHelloWorld() {
		System.out.println("testSpringMVCHelloWorld ...");
		return SUCCESS;
	}

这次是不接收参数age等于10的请求

index.jsp中

和想象当中的一样

如果我们将参数改为11再看

-3).headers属性是对请求中的请求头做出了严格的把控

我们就拿下面这个请求头来说吧,如果请求中带过来的请求头与下面这个符合的话就走我们的控制器方法。

仅仅贴出方法

	@RequestMapping(value="testSpringMVCHelloWorld", method = RequestMethod.GET, params = {"age=10"}, headers = {"Connection=keep-alive"})
	public String testSpringMVCHelloWorld() {
		System.out.println("testSpringMVCHelloWorld ...");
		return SUCCESS;
	}

所以这次 -> 

 -> 所以说@RequestMapping中的4个属性是至关重要的,他们可以对请求本身、请求方式、请求参数、请求头做出精细的控制,相比较来说本人认为SpringMVC比Struts2要好一些。

三、SpringMVC - Ant风格的参数设置

? -> 匹配任意一个参数

* -> 匹配任意多个参数

** -> 匹配多层路径

仅仅贴出方法

	// Ant风格的参数
	@RequestMapping(value="testAnt/**/apple")
	public String testAnt() {
		System.out.println("testAnt ...");
		return SUCCESS;
	}

index.jsp

运行程序

点击链接

成功跳转,按理说正常情况下是不可以的,但是由于你设置了** ,就可以匹配多层路径了。

四、SpringMVC - 接收前台参数的3种方式

-1).通过@RequestParam

	// 接收前台参数
	@RequestMapping(value="testRequestParam")
	public String testRequestParam(@RequestParam(value="name") String name) {
		System.out.println("name:" + name);
		return SUCCESS;
	}

index.jsp

运行程序,点击链接

-2).通过Servlet原生api获取前台参数

仅仅贴出方法

	@RequestMapping(value="testServletAPI")
	public String testServletAPI(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("name:" + request.getParameter("name"));
		return SUCCESS;
	}

index.jsp

运行点链接

-3).通过POJO方式接收前台参数

仅仅贴出方法

	@RequestMapping(value="testPOJO")
	public String testPOJO(Person person) {
		System.out.println(person);
		return SUCCESS;
	}

Person实体类

public class Person {

	private String name;
	private int age;
	private char sex;
	private Direction dt;
	
	public Person() {
		super();
	}
	public Person(String name, int age, char sex, Direction dt) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.dt = dt;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public char getSex() {
		return sex;
	}
	public void setSex(char sex) {
		this.sex = sex;
	}
	public Direction getDt() {
		return dt;
	}
	public void setDt(Direction dt) {
		this.dt = dt;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + ", dt=" + dt + "]";
	}
}

Direction实体类

public class Direction {

	private String city;
	private String province;

	
	public Direction() {
		super();
	}
	
	public Direction(String city, String province) {
		super();
		this.city = city;
		this.province = province;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getProvince() {
		return province;
	}

	public void setProvince(String province) {
		this.province = province;
	}

	@Override
	public String toString() {
		return "Direction [city=" + city + ", province=" + province + "]";
	}
}

index.jsp

运行点链接

所以SpringMVC会自动的将参数映射到JavaBean对象中且支持级联属性

五、SpringMVC - REST风格的请求

仅仅贴出方法

	// REST风格请求
	@RequestMapping(value="testREST", method = RequestMethod.PUT)
	public String testREST(@RequestParam(value="name") String name) {
		System.out.println("name:" + name);
		return SUCCESS;
	}

index.jsp

画红框的地方要特别注意,实际上请求在从前台到后台的过程中一直都是post请求,但是被SpringMVC 拦截后通过红框中的配置会将其转换为PUT请求。 -> hidden固定必填、_method固定必填 PUT/DELETE涉及到这两种请求的时候都必须这么干。

而且REST风格请求是

get -> 获取

post -> 添加

put -> 更新

delete -> 删除

四种请求分别对应数据库的4种操作。

上面就以PUT请求为例

至于是谁拦截的请求进行的转换,就是我们在web.xml中配置的HiddenHttpMethodFilter

六、SpringMVC - 怎么优雅的将数据放进请求域中呢?

-1).通过ModelAndView将视图与数据进行绑定并且将数据放入请求域中

仅仅贴出方法

	@RequestMapping(value="testModelAndView")
	public ModelAndView testModelAndView(@RequestParam(value="name") String name) {
		ModelAndView mv = new ModelAndView("show");
		mv = mv.addObject("name", name);
		return mv;
	}

index.jsp

show.jsp

运行程序,点击链接

-2).通过Map集合将数据放入请求域中

仅仅贴出方法

	// 通过Map集合将数据放入请求域中
	@RequestMapping(value="testTRequestScope")
	public String testMapRquestScope(Map<String, Object> map, @RequestParam(value="name")String name) {
		map.put("name", name);
		return "show";
	}

index.jsp

show.jsp

运行程序,点击链接

至于为什么上面那个也有值,就是因为恰好请求域中有一个键为name值为LJ的元素,所以 ...

七、SpringMVC - 怎么优雅的将数据放进Session域中呢?

通过@SessionAttributes注解将数据放进Session域中

仅仅贴出方法

	@SessionAttributes(value = {"age"})
    @Controller
    @RequestMapping(value="dealData")
    public class DealDataController {


        // 通过@SessionAttribute将数据放进Session域中
	    @RequestMapping(value="testSessionAttributes")
	    public String testSessionAttributes(Map<String, Object> map, @RequestParam(value="age") Integer age) {
		    map.put("age", age);
		    return "show";
	    }
    }

@SessionAttributes注解中的参数age必须与控制器方法的入参处的Map集合添加的元素名相同。

index.jsp

show.jsp

运行程序,点击链接

八、SpringMVC - @PathVariable注解的作用

取出路径中与@PathVariable中变量同名的变量值

仅仅贴出方法

	// @PathVariable注解的作用
	@RequestMapping(value="testPathVariable/{id}")
	public String testPathVariable(@PathVariable(value="id") Integer id) {
		System.out.println("is:" + id);
		return SUCCESS;
	}

index.jsp

运行程序,点击链接

九、通过@RequestHeader注解获取指定请求头的参数值

仅仅贴出方法

	// 通过@RequestHeader来获取请求头的值
	@RequestMapping(value="testGetRequestHeader")
	public String testGetRequestHeader(@RequestHeader(value="Accept") String header) {
		System.out.println("header:" + header);
		return SUCCESS;
	}

index.jsp

运行程序,点击链接

十、通过@CookieValue注解获取指定cookie的cookie值

仅仅贴出代码

	// 通过@CookieValue注解来获取指定的cookie值
	@RequestMapping(value="testCookieValue")
	public String testCookieValue(@CookieValue(value="cookie") String cookie) {
		System.out.println("cookie:" + cookie);	
		return SUCCESS;
	}

index.jsp

运行程序,点击链接

十一、@ModelAttribute - 不得已的场景

现在有一个场景就是如果我们要对信息表进行更新数据的操作,但是数据表中有密码字段,我们不便将密码暴露出来,所以通常情况下从表单中获取的一些属性值密码就可能为null,如果是这样你不做别的操作的话,一更新,完了密码字段的值都没了 ...

为了解决这个问题@ModelAttribute注解登场了。我们可以将数据库中对应字段拿到映射成JavaBean对象,与参数映射的JavaBean对象互相覆盖,最后得到更新对象。就避免了那种情况,实际上就是提供了默认值。

仅仅贴出代码

	// @ModelAttribute
	@ModelAttribute
	public void getPerosnInstance(Map<String, Object> map) {
		map.put("people", new Person("LJ", 21, '男', new Direction("承德", "河北")));
	}
	
	@RequestMapping(value="testModelAttribute")
	public String testModelAttribute(@ModelAttribute(value="people")Person people) {
		System.out.println(people);
		return SUCCESS;
	}

index.jsp

但是依然映射成功

十二、自定义视图

-1).新建自己的视图类并实现View接口重写getContentType方法与render方法

-2).通过返回bean的名字来返回视图

-3).在SpringMVC.xml配置自己的视图解析器

自定义视图类

@Component(value="custom")
public class CustomView implements View {

	@Override
	public String getContentType() {
		return "text/html";
	}

	@Override
	public void render(Map<String, ?> arg0, HttpServletRequest request, HttpServletResponse response) throws Exception {
		response.getWriter().print("Hello SpringMVC ...");
	}
}

SpringMVC.xml中的配置

index.jsp

运行程序,点击链接

返回到了咱们自己定义的视图中去了

十三、SpringMVC - 怎么实现重定向?

在控制器方法中返回"redirect:/Xxx.xx" <- 重定向 

在控制器方法中返回"forward:/Xxx.xx" <- 请求转发

	// SpringMVC实现重定向
	@RequestMapping(value="testRedirect")
	public String testRedirect() {
		return "redirect:/index.jsp";
	}

结果就不贴了,被重定向 ...

十四、SpringMVC - 通过注解对数据进行格式化

SpringMVC.xml中的配置

DataFormat实体类

public class DataFormat {

	@DateTimeFormat(pattern="yyyy-MM-dd")
	private java.util.Date date;
	@NumberFormat(pattern="#,####,#.#")
	private Float num;
	
	public DataFormat() {
		super();
	}

	public DataFormat(Date date, Float num) {
		super();
		this.date = date;
		this.num = num;
	}

	public java.util.Date getDate() {
		return date;
	}

	public void setDate(java.util.Date date) {
		this.date = date;
	}

	public Float getNum() {
		return num;
	}

	public void setNum(Float num) {
		this.num = num;
	}

	@Override
	public String toString() {
		return "DataFormat [date=" + date + ", num=" + num + "]";
	}
}

仅仅贴出方法

	// 对数据进行格式化
	@RequestMapping(value="testDataFormat")
	public String testDataFormat(DataFormat dataFormat) {
		System.out.println(dataFormat);
		return SUCCESS;
	}

十五、SpringMVC - 对数据进行JSR303验证

Dircement实体类

public class Direction {

	private String city;
	@NotEmpty
	private String province;

	
	public Direction() {
		super();
	}
	
	public ...

仅仅贴出代码

	// JSR303数据验证
	@RequestMapping(value="testJSR303")
	public String testJSR303(@Valid Direction direction, BindingResult result) {
		
		if(result.getFieldErrorCount() > 0) {
			for(FieldError item : result.getFieldErrors()) {
				System.out.println(item.getField() + ":" + item.getDefaultMessage());
				// 打印 province:不能为空
				if("province".equals(item.getField())) {
					return "error";
				}
			}
		}
		return SUCCESS;
	}

上面我们在实体类对数据进行JSR303验证,所以当我们页面

就会被验证 -> 再根据错误类型定制行为

此次我们的行为就是转发到error页面

十六、SpringMVC - 文件上传与下载

使用SpringMVC的文件上传功能得先在SpringMVC.xml中配置文件上传组件

SpringMVC.xml

index.jsp

仅仅贴出代码

	public void save(MultipartFile file) {
		if(!file.isEmpty()) {
			File copyFile = new File("C:\\Users\\Lenovo\\Desktop\\" + file.getOriginalFilename()); 
			if(!copyFile.exists()) {
				copyFile.mkdirs();
			}
			try {
				System.out.println("哈哈");
				file.transferTo(copyFile);
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	@RequestMapping(value="testUpload")
	public String testUpload(Direction direction, @RequestParam(value="files") MultipartFile[] files) {
		System.out.println(direction);
		for(int i = 0;i < files.length;i++) {
			MultipartFile file = files[i];
			save(file);
		}
		return SUCCESS;
	}
	

文件上传成功

十七、向前台返回json数据

向前台返回json数据仅仅需要在控制器方法上使用@ResponseBody注解进行标识即可

仅仅贴出代码

	@RequestMapping(value="testResponseBodyToJson")
	@ResponseBody
	public Map<String, String> testResponseBodyToJson() {
		Map<String, String> map = new HashMap<String, String>();
		map.put("key", "value");
		return map;
	}

{"key":"value"}

十八、自定义拦截器

在SpringMVC.xml文件中配置自己的拦截器

SpringMVC.xml

自定义一个类实现HandlerInterceptor接口并实现preHandle方法、postHandle方法、afterCompletion方法,并且

preHandle方法是在目标方法执行之前执行的,可以进行参数验证、权限判断

postHandle方法是在目标方法执行之后视图渲染之前执行的,可以更改数据/视图

afterCompletion方法实在渲染视图之后执行的,可以用来关闭资源

十九、自定义拦截器的执行顺序

自定义的拦截器的执行顺序,

preHandle方法是正序执行的

postHandle方法是逆序执行的

afterCompletion方法是逆序执行的

二十、我要是硬要访问WEB-INF下面的视图呢?

可以通过<mvc:view-controller  path = "/Xxx.xx" view-name="Xxx" />

这样虽然可以直接访问WEB-INF下面的视图但是会造成其它的资源访问不到,所以我们可以通过<mvc:annotation-driven />来搞定

二十一、怎么访问SpringMVC下面的静态资源?

可以通过<mvc:default-servlet-handler />来允许静态资源访问 -> 至于为什么一开始访问不了,就是因为我们在web.xml中配置的DisPatcherServlet的时候的mapping中国的patthen我们指定的是应答所有请求'/'。所以会出现静态资源也被拦截的情况,可以通过

<mvc:default-driven />来搞定

总结:

以上就是近期学到的关于SpringMVC的知识。先会用再去链接原理

猜你喜欢

转载自blog.csdn.net/qq_39872652/article/details/82715357
今日推荐