Spring-MVC

217 阅读5分钟

Spring-MVC

  • Controller(控制层)的一个框架
  • SpringMVC 应当看作 Spring 的一部分 就像是spring JDBC单独的模块

流程

  • 导入jar包

    • spring-web-版本号.RELEASE.jar
    • spring-webmvc-版本号.RELEASE.jar
  • Tomcat 核心配置web.xml

    • spring-mvc会默认去到web目录下去找 请求名-servlet.xml 的 spring-MVC核心文件
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        
        <servlet>
            <servlet-name>请求命名</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>0</load-on-startup>   
        </servlet>
        
        <servlet-mapping>
            <servlet-name>请求命名</servlet-name>
            <url-pattern>*.do</url-pattern>  <!--拦截的请求-->
        </servlet-mapping>
    </web-app>
  • Spring-MVC核心配置

    • 将Controller 对象交由spring容器管理

      • 方式一:

        • <!--<bean id="ID名" class="包名.类名"></bean>-->
          
      • 方式二:

        •     <context:component-scan base-package="controller"></context:component-scan> 扫包
          
        • @Controller
          public calss TetsController(){
              public void test(){
                  System.out.print("controller测试")
              }
          }
          
    • 配置真实的请求和类对应关系

      • 方式一:

        • <bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping>
                 <property name="mappings">
                      <props>
                          <prop key="请求名.do">对应的类名</prop>
                      </props>
                 </property>
          </bean>
          
      • 方式二

        • <mvc:annotation-driven> </mvc:annotation-driven>  <!--开启注解驱动 相当于是加载了HandlerMapping类对象-->
          
        • @RequestMapping("请求名.do")
          public class TestController {
          ​
              @RequestMapping
              public String test(){
                  System.out.println("成功");
                  return "weclome.jsp";
              }
          }
          

    接收请求

    如何接收请求

    方式一
    //直接写在类上
    @RequestMapping("请求名.do")
    public class TestController {
    ​
        @RequestMapping()
        public String test(){
            System.out.println("成功");
            return "weclome.jsp";
        }
    }
    
    方式二
<!--发送请求-->

<a href="url:端口号/请求?method=请求的方法名&参数1=test1,参数2=test2">
// 接收请求

@RequestMapping("请求名.do")
public class TestController{
    @RequestMapping(parame={"参数1""参数2"})
    public String test(){
        System.out.print("Hello Word")
    }
    
}
方式三
请求方式同上


public class TestController{

	直接在方法上写该注解
	@RequestMapping("请求.do",parame={"参数1""参数2"})
	public void test(){
		System.out.print("Hello Word")
	}
}
方式三
//将接收的参数,组成集合 list,map等
//map需要前面加上注解 @RequestParam
//其他集合正常写即可
@RequestMapping(path = "testThree.do",method = RequestMethod.GET)
    public String testThree(@RequestParam Map map){
        System.out.println(map.get("user"));
        System.out.println(map.get("pass"));
        return "weclome.jsp";
    }

RequestMapping 解析

	path={"",""} //填写请求
	value={"",""} //填写值
	params={"",""}  //定义传递的参数名字
	method={RequestMethod.GET} //定义接收的请求方式
		   GET,
    	   HEAD,
           POST,
           PUT,
           PATCH,
           DELETE,
           OPTIONS,
           TRACE;
	headers={"Accept-Language",""} //获取请求头

中文乱码

方式一
    <!--在请求时后台输出会出现乱码,可在配置文件添加拦截器,交由springMVC解析-->
	<filter>
        <filter-name>encoding</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>
    </filter>

    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

相关注解

 @RequestBody //获取请求的主体
 @CookieValue //获取请求的cookie
 @RequestHeader  //获取请求头
 @ModelAttribute("请求名.do")  //可以立即为请求初始化
 @RequestMapping("请求名.do")
    public String testParam1(@RequestBody String body, @CookieValue("JSESSIONID") String cookieValue,             @RequestHeader("Accept-Language")String header){
        //请求(参数)  domain  控制层  业务层  持久层  domain(属性-数据库中列)  JDBC-->数据库
        System.out.println("参数的测试方法");
        System.out.println("接收到的body:"+body);
        System.out.println("接收到的header:"+header);
        System.out.println("接收到的cookie:"+cookieValue);
        return "weclome.jsp";
    }

	@ModelAttribute("想要拦截的请求")
   public void testModel(){
       System.out.print("我是提前的方法")
   }

响应

原生

			只能自己通过原生response获取输出流 回写响应信息
	//void表示不需要框架帮我们处理响应信息
    public void  testReponse(HttpServletResponse response){
	//将数据返回给浏览器
	response.getWrite().write("要响应的内容")
	// 转发:
	requet.getRequestDispatcher().forward(requset,response);
	// 重定向:
	response.sendReddirect();
}
	

框架

//			String(没有@ResponseBody注解)
		//	表示请求框架帮我们处理响应信息路径的转发或重定向
			//forward:
			//redirect:	
	public String testRepsone(){
	//转发
	return "redirect:资源"
	//重定向
	return "forward:资源"
	//默认不写即为转发
	return "资源"
}	

异步请求

	//通常发送异步请求  map domain list set
	// 需要导入json相关的包(core databind annotations)
	//并在方法上添加@Responsebody
	//完成上述步骤,框架会自动将你想传递的值转换为json形式
   @ResponseBody
    @RequestMapping("response.do")
    public Map<String,String> testResponse(@RequestBody Student student){
        System.out.println("我是接收的用户名"+student.getUser());
        System.out.println("我是接收的密码"+student.getPass());
        Student student1=new Student("lll",1);
        //domain (存储一对数据的容器,但是比map更具体) 
        Student student1=new Student();
        student.setUser("lym");
        student.setpass(123);
        return student1;
        //Map (集合,存放一堆相同格式的容器) 方式 其他集合只用正常放入集合中,正常返回就好
        HashMap<String,String> map=new HashMap<String, String>();
        map.put("aaa","a1");
        map.put("bbb","b2");
        map.put("ccc","c3");
        return map;
    }

前端(如:浏览器)传json


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <script type="text/javascript">
    function Person(){}
    window.onload = function () {
        //找到按钮DOM对象 绑定单击事件
        document.getElementById("button").onclick = function () {
            //1.创建一个AJAX对象用于发送
            var xhr = new XMLHttpRequest();
            //2.打开一个通道 模拟一个请求  ("请求方式","请求URL",是否为异步true)
            xhr.open("POST","response.do?,true);
            //  2.1如果想要发送的是json形式 告知浏览器解析的时候规则
            xhr.setRequestHeader("Content-type","application/json;charset=UTF-8");
            //3.发送后 时刻监听者服务端的状态   回调机制
            xhr.onreadystatechange = function () {
                if(xhr.readyState==4 && xhr.status==200){
                    //接收响应信息啦
                    alert(xhr.responseText);
                    //接收以后 需要处理 展示在浏览器中的某个组件里
                }
            }
            //4.发送请求
            xhr.send('{"user":"张三","pass":123}');
        }
    }
  </script>
  <body>
<input id="button" type="button" value="测试JSON形式">

  </body>
</html>
	//	发送端设置JSON形式
	//  接收端(服务端的方法) 参数上面@RequestBody即可 domain对象接收
	@ResponseBody
    @RequestMapping("response.do")
    public void testResponse(@RequestBody Student student){
        System.out.print(student.getUser);---> 输出结果:张三
        System.out.print(student.getPass);---> 输出结果:123
    }

ModelAndView

利用控制层的方法返回值来处理响应
	1.void	  不用框架帮我们处理  需要自己处理  response.getWriter() write()
	2.String  让框架帮我们去做转发、重定向   String----资源名字
			forward:     redirect:
	3.Object  domain String Map List----->JSON
			1.处理工具---jar
			2.告知框架方法的返回值需要解释  @Responsebody
	4.ModelAndView
			存储信息
			转发的路径

	服务端业务层可能会产生一些数据
	这些数据我们需要存入作用域中带走
		request.setAttribute();

	1.可以利用原生Map来处理
		Map接收请求参数(@RequestParam)
		Map可以返回数据(@ResponseBody)
        
	2.可以利用ModelModelMap
		Model底层继承ModelMap
		存储数据之前不需要自己创建
		只需将变量放置在方法的参数里即可  框架会帮我们自动注入
		m.addAttribute("",object);
		但是只能存储数据
		不能携带转发的路径资源
		对象不需要返回
            
       public void Login(User user, Model model,ModelMaP map){
        	   model.addAttribute("object","test");
               modelMap.addAllAttributes(Map<T> attributes)
        }
            
            
	3.可以利用ModelAndView
		不能放在方法的参数里 框架不会帮我们注入
		需要用的时候 自己new即可
		mv.addObject("key",object);
		mv.setViewName("xxx.jsp");
		可以包含数据和转发路径
		需要将自己创建的mv对象返回
		
		public ModelAndView Login(User user){
        ModelAndView mv=new ModelAndView();
        System.out.println("这是model"+model);
        mv.addAttribute("modelUser",user);
        mv.addObject("madUser",user);
        return mv;
		
	4.如果想要将值存入session作用域范畴内
		需要在类名上面添加注解
		@SessionAttributes({"key","",""})
	

捕获异常

第一步

//定义实现springMvc提供的接口
public class ExeptionResolver implements HandlerExceptionResolver {


    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        if (e instanceof MyExeption){
            ModelAndView mav=new ModelAndView();
            mav.addObject("err",e.getMessage());
            mav.setViewName("err.jsp");
            return mav;
        }
        return null;
    }
}

第二步

//描述一个异常
//继承java 运行时异常
public class MyExeption extends RuntimeException {

    //描述的错误
    private String message;

    public MyExeption(){}

    public MyExeption(String message) {
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

测试类

@ResponseBody
@Controller
public class TestEer {

    private ModeService service;

    @RequestMapping(path = "rex.do")
    public String testReception()  {
//        ModelAndView mav=new ModelAndView();
        System.out.println("controller执行啦");
        //1.字符集
        //2.接收参数(参数列表)
        //3.找寻业务层方法处理逻辑------>可能会产生异常
        try {
            String s = null;
            s.length();
            //s.length();//NullPointerException
        } catch (Exception e){
            e.printStackTrace();//打印后台开发人员可以看到    异常记录在文件 日志
            throw new MyExeption("错误页面");
        }
        //4.正常的响应
        return "err.jsp";
    }

}

上传下载

@Controller
public class Upload {

    @RequestMapping("upload.do")
//    String text, MultipartFile upload
    public String upload(String text, MultipartFile upload) throws IOException {
        System.out.println("测试成功");
        System.out.println(text);
        System.out.println(upload);
        String fileName=upload.getOriginalFilename();
        upload.transferTo(new File("D://File/",fileName));
        return "weclome.jsp";
    }

    @RequestMapping("download.do")
    public ResponseEntity<byte[]> download(String fileName) throws IOException {
        //获取读取文件即可
        File file=new File("D://File/"+fileName);
        //设置响应相关信息
        //如果有中文 需要处理
        fileName = new String(fileName.getBytes("UTF-8"),"ISO-8859-1");
        HttpHeaders headers=new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment",fileName);
        //将响应信息存入一个返回值对象内即可----ResponseEntity
        byte[] b= FileUtils.readFileToByteArray(file);
        return new ResponseEntity(b,headers, HttpStatus.CREATED);
    }

}

配置文件

//设置读取的文件数
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10244000"></property>
    </bean>

notepad++ 官网: notepad-plus-plus.org/