• springmvc学习笔记


    基础

    三层框架中的web层

    mvc架构

    • 前端控制器(DispatcherServlet):流程控制的中心,管理其他组件
    • 处理器映射器(HandlerMapping):(RequestMapping)根据用户请求找到Handler(control方法)
    • 处理器适配器:
    • 处理器:controller方法
    • 视图解析器:根据逻辑地址找到物理地址,解析并渲染提交页面

    mvc加载流程

    1. tomcat启动,加载web.xml
      1. 过滤器:解决post乱码问题
      2. 前端控制器:加载核心配置文件,处理所有请求
    2. 加载springmvc.xml
      1. 包扫描
      2. 配置注解驱动,创建springmvc容器:转换器、视图解析器、静态资源

    mvc请求流程

    1. HTTP请求到前端控制器
    2. 前端控制器根据requestmapper寻找并执行方法
    3. 根据返回值,提交到视图解析器
    4. 视图解析器返回页面

    mvc编写流程

    和加载流程一致,便于理解

    配置maven

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!--本案例使用Tomcat进行部署,Tomcat自己有servlet-api的包,需要部署的时候排出这个包-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
    <!--本案例使用Tomcat进行部署,Tomcat自己有jsp-api的包,需要部署的时候排出这个包-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.2</version>
    </dependency>
    

    配置web.xml

    解决post中文乱码
    配置前端控制器(DispatcherServlet)

    <!--配置过滤器解决post的乱码问题-->
    <filter>
        <!--给过滤器起名,叫啥都行-->
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    
        <!--指定过滤器的编码为UTF-8-->
        <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>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
        <init-param>
            <!--配置加载SpringMVC的核心配置文件-->
            <!--contextConfigLocation:是固定写法,是springMVC的属性,不能改-->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    
        <!--配置在什么时候启动SpringMVC容器-->
        <!--使用这种方式:当配置的值是大于0的正整数的时候,SpringMVC是随着Servlet容器(Tomcat)的启动而启动-->
        <!--如果为0或者这不进行配置,SpringMVC的容器是用户第一次访问的时候启动-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <!-- 所有的请求都会被Servlet处理 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    配置springmvc.xml

    包扫描
    配置注解驱动-转换器-视图解析器

    <!--包扫描-->
    <context:component-scan base-package="com.alvin.controller"/>
    
    
    <!--配置注解驱动-->
    <!--配置转换器-->
    <mvc:annotation-driven conversion-service="conversionService"/>
    <!--配置转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.alvin.converter.DateConverter"/>
            </set>
        </property>
    </bean>
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--解决css静态资源的问题-->
    <mvc:resources mapping="/css/**" location="/css/"/>
    

    转换器示例代码

    import org.springframework.core.convert.converter.Converter;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class DateConverter implements Converter<String,Date> {
        @Override
        public Date convert(String s) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date date = dateFormat.parse(s);
                return date;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    编写control

    @Controller
    @RequestMapping("alvin")//所有方法映射的url要加上value
    public class HelloController {
        //可以只写路径,method默认get,参数默认任意
        //如果后面写参数,则参数必须一致,否则报错
        @RequestMapping(value = "/hello",method = RequestMethod.GET,params = {"id","money>100"})
        public String hello() {
            System.out.println("入门案例,执行到这里了");
            //返回xml里面指定的jsp
            return "success";
        }
    }
    

    编写web请求页面

    可以提交基本类型,数组、map、pojo

    <form action="/user/getUser" method="post">
        <input name="id" value="1"/>
        <input name="name" value="李白"/>
        <input name="accounts[0].id" value="0" />
        <input name="accounts[0].money" value="99999" />
        <input name="accounts[1].id" value="0"/>
        <input name="accounts[1].money" value="99999"/>
        <input name="map[nihao].id" value="1"/>
        <input name="map[nihao].money" value="111111"/>
        <input type="submit" value="post提交"/>
    </form>
    

    标题二

    modelAttribute

    在请求执行之前执行的方法

    # 基础使用
    @ModelAttribute
    public void modelAttribute(Person person) {
        System.out.println(person.getUsername() + "model");
    }
    
    @RequestMapping("test")
    public String test(Person person) {
        System.out.println(person.getUsername());
        return "success";
    }
    # 返回对象
    //返回的值会保存在容器中
    @ModelAttribute
    public Person methodAttribute(){
        Person person = queryPerson();
        return person;
    }
    # 自定义存储名称
    @ModelAttribute
    public void methodAttribute(Map<String,Person> map){
        Person person = queryPerson();
        map.put("abc", person);
    }
    
    @RequestMapping("test")
    public String test(@ModelAttribute("abc") Person person) {
        System.out.println(person);
        return "success";
    }
    

    sessionAttribute

    @Controller
    @SessionAttributes(value = {"username", "password"}, types = Integer.class)
    @RequestMapping("sessionAttribute")
    public class SessionAttributeController {
        @RequestMapping("put")
        public String putTest(Model model) {
            model.addAttribute("username", "李白");
            model.addAttribute("password", "123456");
            model.addAttribute("age", 123);
            model.addAttribute("addr", "addr");
            return "success";
        }
    
        @RequestMapping("get")
        public String getTest(ModelMap map) {
            System.out.println(map.get("username"));
            System.out.println(map.get("password"));
            System.out.println(map.get("age"));
            System.out.println(map.get("addr"));//不会输出
            return "success";
        }
    
        @RequestMapping("clean")
        public String cleanTest(SessionStatus sessionStatus) {
            sessionStatus.setComplete();
            return "success";
        }
    }
    

    restful

    增post 删delete 查get 改put

    • 添加put、delete等请求的支持
    <!--支持put、delete等请求-->
    <filter>
        <filter-name>methodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <!--必须放在解决乱码的前面-->
    <filter-mapping>
        <filter-name>methodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    • 前端post请求必须包含_method:put,后端代码:
    @RequestMapping(value = "person/{id}", method = RequestMethod.PUT)
    @ResponseBody //返回的是普通数据
    public String update(@PathVariable("id") int id) {
        System.out.println(id);
        return "success";
    }
    

    返回值

    • 返回string

    默认会返回给视图解析器
    可以通过@ResponseBody返回普通数据

    • 返回void

    本质就是使用request和response

    • 返回ModelAndView
    @RequestMapping("modelAndView")
    public ModelAndView modelAndView() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("success");
        modelAndView.addObject("username", "李白");
        return modelAndView;
    }
    

    转发和重定向

    @RequestMapping("testForward")
    public String testForward(){
        //使用forward关键词完成请求转发,到success.jsp成功页
        return "forward:/WEB-INF/jsp/success.jsp";
    }
    
    @RequestMapping("testRedirect")
    public String testRedirect(){
        //使用redirect关键词完成请求重定向,到第一个testString方法
        return "redirect:testString";
    }
    

    json

    请求必须是json!!!JSON.stringify(rowData)

    • 应用
    <!--支持json格式数据交互的依赖-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.5</version>
    </dependency>
    
    • 使用
    public @ResponseBody Person test(@RequestBody() Person person) {
        return person;
    }
    

    文件上传

    • 引入
    <!--支持文件上传的组件-->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
    <!--跨服务器文件上传的支持-->
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-core</artifactId>
        <version>1.18.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.18.1</version>
    </dependency>
    
    • 配置文件解析器
    <!--配置文件上传解析器-->
    <!--上传解析器的id必须是接口名,首字母消息-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--配置上传文件的大小不能超过1M-->
        <property name="maxUploadSize" value="1048576"/>
    </bean>
    
    • 使用
    # 上传到本地服务器
    
    public String upload(MultipartFile uploadFile, String fileName) throws IOException {
        uploadFile.transferTo(new File("D:/alvin/1.jpg"));
        //返回成功页面
        return "success";
    }
    
    # 上传到其他服务器
    # 修改要上传服务器tomcat的web.xml
    <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>
    ------------------------------------
    
    String imageUrl = "http://127.0.0.1:9090/uploads/"
    //使用jersey进行上传
    Client client = Client.create();
    //执行上传的路径
    WebResource resource = client.resource(imageUrl + fileName);
    //执行上传
    resource.put(String.class,uploadFile.getBytes());
    

    异常处理

    • 自定义error.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    自定义异常!!!
    </body>
    </html>
    
    
    • 自定义异常
    public class MyException extends Exception {
        public MyException(String message) {
            super(message);
        }
    }
    
    
    • 自定义全局异常
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyHandleExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
            MyException myException = null;
            if (ex instanceof MyException) {
                myException = (MyException) ex;
            } else {
                myException = new MyException("运行异常,请找管理员");
            }
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("msg", myException.getMessage());
            modelAndView.setViewName("error");
            return modelAndView;
        }
    }
    
    • 配置全局异常处理器(springmvc.xml)
    <!--全局异常处理-->
    <bean class="com.alvin.ex.MyHandleExceptionResolver"/>
    
    • 正常使用即可
    int a = 1 / 0;
    

    Interceptor拦截器

    与filter区别:
    interceptor只能springmvc使用,filter属于servlet;
    interceptor只能拦截方法,filter可以拦截所有。

    • 自定义拦截器
    public class MyInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("posthandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("after");
        }
    }
    
    
    • 注册

    springmvc.xml

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/test/**"/>
            <bean class="com.alvin.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    
  • 相关阅读:
    项目实践精解读后感(需求分析注意点)
    XP@Scrum
    项目实践精解读后感2(需求分析注意点)
    十一过后,反思。
    可以自动化功能测试了Selenium
    部分关键字段重复的记录(保留最后记录)
    算是代码优化吗?还可以继续优化吗?
    hql查询~
    通用权限管理设计 之 数据库结构设计(摘录)
    jQuery Liger~
  • 原文地址:https://www.cnblogs.com/birdofparadise/p/10012285.html
Copyright © 2020-2023  润新知