微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

springMVC

springMVC

springMVC是一站式框架spring中的一个模块,方便前后端数据传输

详情可查看Workplace中的Maven07系列项目

	<!-- spring-webmvc -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-webmvc</artifactId>
	    <version>5.2.2.RELEASE</version>
	</dependency>
	
	<!-- jstl -->
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
                    http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop.xsd
                    http://www.springframework.org/schema/tx
                    http://www.springframework.org/schema/tx/spring-tx.xsd
                    http://www.springframework.org/schema/mvc
                    http://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
                    
</beans>

添加前缀
添加后缀

值得注意的是springmvc的拦截器是不拦截.jsp文件的,只拦截控制器内部请求。

<!-- 开启springmvc注解 --> 
 <mvc:annotation-driven></mvc:annotation-driven>             
                    
      <!-- 视图解析器 -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
      	<property name="prefix" value="/WEB-INF/jsp/"></property>
      	<property name="suffix" value=".jsp"></property>
      </bean>

<!-- 开启spring的注解扫描功能 -->
      <context:component-scan base-package="com.wenhua.spring"></context:component-scan>             
             
       <!-- 导入springMVC配置文件 --> 
       <import resource="springmvc.xml"/>

以前都是在通过main方法,读取.xml文件,从而加载配置文件

springmvc是web工程是要部署在服务器上通过浏览器访问,在项目启动时,就需要将spring配置文件加载,

在web.xml配置文件中将会解析springmvc.xml以及application.xml文件,因为要向服务器部署。需要用到dispatcherServlet分发器0服务器启动前加载

  <!-- 配置spring核心请求分发器 -->
 <servlet>
  <servlet-name>application</servlet-name>
  <servlet-class>
      org.springframework.web.servlet.dispatcherServlet
  </servlet-class>
     <init-param>
       <param-name>contextConfigLocation</param-name>
       <!-- 找web-inf/classes/配置文件 -->
       <param-value>classpath:application.xml</param-value>
     </init-param>
     <load-on-startup>0</load-on-startup>
  </servlet>
	<!-- 请求映射 -->
	  <servlet-mapping>
	    <servlet-name>application</servlet-name>
		<url-pattern>/</url-pattern> 
	  </servlet-mapping>

设置springmvc的字符集编码,直接在web.xml配置文件中进行粘贴

<!-- springmvc配置字符集编码 -->
 <filter>  
    <filter-name>characterEncodingFilter</filter-name>  
    <filter-class>
        org.springframework.web.filter.CharacterEncodingFilter
    </filter-class>  
    <init-param>  
        <!-- 在spring-web的jar包下filter-class第49行
            @Nullable
            private String encoding; -->
       <param-name>encoding</param-name>  
       <param-value>UTF-8</param-value>  
    </init-param>  
</filter>  
	<filter-mapping>  
	    <filter-name>characterEncodingFilter</filter-name>  
	    <url-pattern>/*</url-pattern>  
	</filter-mapping>
  • Controller类

@Controller 注解可以实例化该类

@RequestMapping(path="/userCtr") 为该类或该方法指定路径(映射地址)

ModelAndView mv = new ModelAndView(“user/login”); 视图名就是将要访问页面的路径。通过springmvc.xml配置中的视图解析机制后路径为WEB-INF/jsp/user/login.jsp(请求转发)

package com.wenhua.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(path = "/userCtr")
public class UserController {

	@RequestMapping(path = "/list")
	public ModelAndView UserList() {
		System.out.println("list列表");
		ModelAndView mv = new ModelAndView("user/login");
		mv.addobject("name", "文华");
		return mv;

	}

}

index.jsp页面

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

<a href="userCtr/list">登录</a>

</body>
</html>

login.jsp页面

${}需要添加jstl的jar包

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<Meta charset="UTF-8">
<title>login</title>
</head>
<body>
	 ${name }
	 登录成功
</body>
</html>

总结

在服务器部署项目时很多情况下有时候不成功,要检查是否加载为class文件,在服务器以及项目根目录下检查。

springMVC插件

  • dispatcherServlet:前端控制器,在web.xml配置文件中配置
  • HandlerMapping:处理器映射器,根据请求的url找到处理该请求的处理器Handler(即Controller),又返回给前端控制器dispatcherServlet
  • HandlerAdapter:dispatcherServlet选择合适的HandlerAdapter(适配器),
    • HttpMessageConveter:将请求对象转换成一个对象
    • 数据转化
    • 数据格式化
    • 数据验证
    • 返回一个ModelAndView
  • ModelAndView:dispatcherServlet取得了ModelAndView之后,l 需要将把逻辑视图名解析为具体的View,比如jsp视图,pdf视图等,这个解析过程由ViewResolver来完成。
  • ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术。
  • View:就是要想用户展示的jsp,pdf等,最终dispatcherServlet将渲染的结果响应到客户端。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IzxCwmyK-1615994444236)(springMVC流程.jpg)]

参数接收

@RequestMapping(path="/userCtr") 为该类或该方法指定路径(映射地址),

@RequestMapping(value="/userCtr") 但是value也是可以进行配置路径的

@RequestMapping(path={"/userCtr","/user"}) path可以配置多个路径string[]

method=RequestMethod.Get/Post指定请求的方式

@GetMapping(path="/userCtr") 只能是get请求

@PostMapping(path="/userCtr") 只能是Post请求

  • 注意在接收日期时一定要指定格式
@DateTimeFormat(pattern="yyyy-MM-dd")// 不然会报404错误
	private Date birthday;

在Controller中接收jsp中的数据

// 通过 @RequestHeader获得请求头        @RequestParam 获得请求参数   
public ModelAndView getRequset(
    @RequestHeader("User-Agent") String userAgent,
	@RequestHeader("Cookie") String cookie,
	@RequestParam("account") String account,
	@RequestParam("password") String password){ }

// 如果需要的参数名一致可直接获取(数据类型转换)
	public ModelAndView getRequset(
        String account,
        String password,
        Integer age){}

// 如果是一个实体,框架直接进行封装
	 public ModelAndView getRequset(User user){
		 // 注意要给日期格式
		 System.out.println(user);
		 return null;
	 }

// 实体外还有信息可直接通过名字获取
	public ModelAndView getRequset(User user,String mark){}

// 通过HttpServletRequest,HttpServletResponse,HttpSession和JavaEE-servlet一样获取参数
	 public ModelAndView getRequset(
         	 HttpServletRequest request,
			 HttpServletResponse response,
			 HttpSession session){
			System.out.println(request.getParameter("account"));
			System.out.println(request.getParameter("password"));
		return null;
	 }

请求转发,重定向,访问静态资源

Maven07-2项目

在Controller中可以返回String类型,但是返回的仍然是路径,这个路径仍然会经过视图解析器。

这种一般用于跳转页面时使用。但这也是通过请求转发,可以通过request传递数据

@RequestMapping(value="/test")
	public String vRedirection(){
		return "user/login";
	}

index.jsp

<form action="${path }/user/test" method="get">
	账号<input type="text" name="account"/><br/>
	密码<input type="password" name="password"/><br/>
	<input type="submit" value="登录"/>
</form>

UserController.java

	/**
	 * 重定向
	 * @param request
	 * @return
	 */
	@RequestMapping(value="/test")
	public String vRedirection(HttpServletRequest request){
		System.out.println(request.getParameter("account"));
        // 在字符串前添加redirect:前缀,不会经过视图解析器,
		// 以重定向的方式跳转页面,地址会变化,不能访问web-inf目录下的文件
		// "/"表示从项目的根目录查找,形成绝对路径
		return "redirect:/Redirection.jsp";
	}
	
	/**
	 * 跳转页面
	 * @return
	 */
	@RequestMapping(value="/str")
	public String vStrign(){
		return "user/login";
	}

Redirection.jsp

<a href="user/str">
		这是重定向转发过来的,重定向不能访问web-inf文件夹下的jsp,<br/>
	但是可以通过Controller跳转。<br/>
</a>
  • 访问静态资源(jsp是动态文件)

在springmvc中的jsp页面上,不能访问静态资源文件(例如:图片,css,js……)

如果没有经过配置,访问静态文件是访问不到的,因为在web.xml配置文件

springMvc /

配置地址为"/",所有的请求都会进入dispatcherServlet的映射地址,然后通过HandlerMapping去找对应的控制类。

在springmvc.xml配置文件中配置如下就OK了。认serlvet进行处理。

 <!-- 过滤静态资源文件 -->
       <mvc:default-servlet-handler/>

ajax异步请求处理

请求转发,重定向都是同步请求。

  	<!-- jackson -->
  		<dependency>
  			<groupId>com.fasterxml.jackson.core</groupId>
  			<artifactId>jackson-databind</artifactId>
  			<version>2.9.1</version>
  		</dependency>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<Meta charset=UTF-8>
<title>index</title>
<script type="text/javascript" src="${path }/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">

	$(function(){
		$("#loginbtn").click(function(){
		<%-- $.请求方式("发送路径"  ,  
                    "向Controller发送的数据" , 
                    		接收返回值函数) --%>
			$.get("${path}/user/list",$("#formId").serialize(),function(res){
				console.log(res);
				if(res != null){
					alert("登录成功");
					location.replace("${path}/user/str");
				}else{
					alert("登录失败");
				}
			})
		})
	})
</script>
</head>
<body>
<form id="formId">

	账号<input type="text" name="account"/><br/>
	密码<input type="password" name="password"/><br/>
	<input type="button" value="登录" id="loginbtn"/>
</form>

</body>
</html>
  • Controller控制类

在servlet中都是通过

PrintWriter out = response.getWriter();

来向jsp页面响应ajax请求,但是在springmvc中,不需要这样,而是通过

@ResponseBody

该注解的作用是将controller的方法返回都得对象通过适当的转换器转换为指定的格式后,写入到response对象的body区,通过用来向异步请求返回json数据,所以需要jar包

注意,在使用该注解之后,不会再走视图解析器,而是直接将数据写入到输入流中。

/**
	 * ajax异步请求返回普通数据类型
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="/list")
	public int userlist(){
		try {
			return 1;
		} catch (Exception e) {
			return 2;
		}
	}
	
	/**
	 * ajax异步请求返回Account封装结果
	 * @param ac
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="/list")
	public Account userlist(Account ac){
		try {
			return ac;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 跳转页面
	 * @return
	 */
	@RequestMapping(value="/str")
	public String vStrign(){
		return "user/login";
	}

文件上传

Maven_ssm_db项目

对提交的二进制文件进行解析

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
  • 通过表单将本地文件提交到服务器
<div>
	<form action="${path }/user/userImg" method="post" enctype="multipart/form-data">
		头像<input type="file" name="userPhoto" accept=".png,.jpg"/>
		<input type="submit" value="上传文件"/>
	</form>
</div>
  • 配置文件解析器,将apache组件解析后的结果给再次封装

<bean id=“multipartResolver” class**="org.springframework.web.multipart.commons.CommonsMultipartResolver">**

​ <property name=“defaultEncoding” value**="utf-8">property*>**

​ <property name=“maxUploadSize” value**="10485760">property*>**

文件上传后能放在项目中吗?

能,但是只能用绝对地址,File filePath = new File(request.getcontextpath()+"\statics\imgs\"+user.getAccount()+oldPhotoName);这样是不行的,而且要注意在servlet中不能使用${}符号,只能通过绝对路径

File filePath = new File(“D:\Program Files (x86)\eclipse\WorkPlaces\Maven_ssm_db\src\main\webapp\statics\imgs\”+user.getAccount()+oldPhotoName);

注意存放的位置是服务器,可以通过服务器直接访问已经上传了的图片http://localhost:8888/Maven_ssm_db/statics/imgs/13240797843708908.png

在查看上传的照片时,不能通过D://……等一系列的路径,因为这会返回客户端后,使用客户端D://……路径,在不同的地方,含义不同。

文件下载

<a href="${path }/user/downloadImg">
	<img alt="图片没有" src="${path }/statics/imgs/${user.newFileName}" title="点击下载">
</a>
  • 通过请求在Controller处理器中进行下载文件,有异常时一定要妥善处理,不然代码会存在隐患
	/**
	 * 下载(文件)用户头像
	 * @param session
	 * @param file
	 * @return
	 * @throws IOException 
	 */
	@GetMapping(path="/downloadImg")
	public void DownLoadImg(
			HttpServletResponse response,
			HttpSession session){
		
			// 包装一下,为了效率更高
			BufferedInputStream bin = null;
			bufferedoutputstream bout = null;
			try {
				// 获得当前用户
				User user = (User) session.getAttribute("user");
				// 获得要下载的文件
				String downLoadFile = "D:\\Program Files (x86)\\eclipse\\WorkPlaces"
						+ "\\Maven_ssm_db\\src\\main\\webapp\\statics\\imgs\\"+user.getNewFileName();
				File file = new File(downLoadFile);
				// 代表任意的二进制数据
				response.setContentType("applicatoin/octet-stream");
				// 设置将要下载文件名称
				response.setHeader("content-disposition", "attachment;filename="+
				new String(user.getoldFileName().getBytes("utf-8"),"ISO-8859-1"));
				// 
				FileInputStream in = new FileInputStream(file);
				bin = new BufferedInputStream(in);
				
				OutputStream out = response.getoutputStream();
				bout = new bufferedoutputstream(out);
				
				byte[] bs = new byte[1024];
				int length = 0;
				while((length = bin.read(bs))!= -1){
					bout.write(bs, 0, length);
				}
			} catch (UnsupportedEncodingException e) {
				// Todo Auto-generated catch block
				e.printstacktrace();
			} catch (FileNotFoundException e) {
				// Todo Auto-generated catch block
				e.printstacktrace();
			} catch (IOException e) {
				// Todo Auto-generated catch block
				e.printstacktrace();
			}finally{
				try {
					bin.close();
					bout.flush();
					bout.close();
				} catch (IOException e) {
					// Todo Auto-generated catch block
					e.printstacktrace();
				}
			}
	}

报错:在什么情况下,会报java.lang.IllegalStateException,其实一般情况下都是代码不严谨的问题造成的,下面给出了详细的解析,但是我的问题和下面的有点不同,但是是理解之后才明白自己代码问题的。

今天运行项目时出现的这个问题,java.lang.IllegalStateExceptio,第一次见到这个异常,
查询
错误原因:该异常表示,当前对客户端的响应已经结束,不能在响应已经结束(或说消亡)后再向 客户端(实际上是缓冲区)输出任何内容
具体分析:首先解释下flush(),我们知道在使用读写流的时候数据先被读入内存这个缓冲区中, 然后再写入文件,但是当数据读完时不代表数据已经写入文件完毕,因为可能还有 一部分仍未写入文件而留在内存中,这时调用flush()方法就会把缓冲区的数据强行 清空输出,因此flush()的作用就是保证缓存清空输出。 response是服务端对客户端请求的一个响应,其中封装了响应头、状态码、内容等, 服务端在把response提交到客户端之前,会向缓冲区内写入响应头和状态码,然后 将所有内容flush。这就标志着该次响应已经committed(提交)。对于当前页面中 已经committed(提交)的response,就不能再使用这个response向缓冲区写任何东西 (注:同一个页面中的response.XXX()是同一个response的不同方法,只要其中一个 已经导致了committed,那么其它类似方式的调用都会导致 IllegalStateException异常)。
能够导致响应已经committed的操作包括:forward, redirect, flushBuffer。
可以将项目从tomcat中先移除再部署上去,实在不行就把myeclipse中所有项目都清空一下,再从新部署上去。

创建拦截器类,并且实现handlerinterceptor接口,重写三个方法(也可只重写preHandle方法)

// 获得session并取得user对象
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute("user");
		if(user == null){
			// 注意这里使用的是请求转发,可以直接访问到非WEB-INF文件下的文件
			response.sendRedirect("index.jsp");
			return false;
		}else{
			/*当请求到达控制器之前被执行
			   true--继续向下执行,到达下一个拦截器,或控制器
			   false--不会继续向下执行*/
			return true;
		}

在springmvc.xml配置文件添加拦截器配置,在添加拦截器时头脑一定要清楚,注意preHandle方法拦截页面发往Controller的请求,不会拦截Controller中处理后的View

<!-- 请求拦截器 -->    
<mvc:interceptors>
	<mvc:interceptor>
		<!-- 配置哪些请求被拦截  拦截器不会拦截jsp页面请求-->
        <mvc:mapping path="/**"/>
        <!-- 哪些请求不被拦截(放行) -->
        <mvc:exclude-mapping path="/loginCon/toLogin"/>
           <!-- 放行从index.jsp页面到main/login.jsp页面的请求 -->
     	<mvc:exclude-mapping path="/loginCon/chLogin"/>
         	<!-- 放行login.jsp页面登录的请求 -->
        <mvc:exclude-mapping path="/statics/**"/>
        <!-- 注入拦截器 -->
        <bean id="isLogin" class="com.wenhua.spring.util.isLoginInterceptor"></bean>
	</mvc:interceptor>
</mvc:interceptors> 

法只拦截页面发往Controller的请求,不会拦截Controller中处理后的View

<!-- 请求拦截器 -->    
<mvc:interceptors>
	<mvc:interceptor>
		<!-- 配置哪些请求被拦截  拦截器不会拦截jsp页面请求-->
        <mvc:mapping path="/**"/>
        <!-- 哪些请求不被拦截(放行) -->
        <mvc:exclude-mapping path="/loginCon/toLogin"/>
           <!-- 放行从index.jsp页面到main/login.jsp页面的请求 -->
     	<mvc:exclude-mapping path="/loginCon/chLogin"/>
         	<!-- 放行login.jsp页面登录的请求 -->
        <mvc:exclude-mapping path="/statics/**"/>
        <!-- 注入拦截器 -->
        <bean id="isLogin" class="com.wenhua.spring.util.isLoginInterceptor"></bean>
	</mvc:interceptor>
</mvc:interceptors> 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐