SpringMVC1~~~

快速入门

spring容器文件

        在src下就是applicationContext-mvc.xml,需要在web.xml指定<init-param>,给DispatcherServlet指定要去操作的spring容器文件


        在WEB-INF下就是xxx-servlet.xml,不需要在web.xml指定<init-param>,如果我们没有配置 contextConfigLocation,默认按照这样的位置去定位spring配置文件
/WEB-INF/springDispatcherServlet-servlet.xml

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

    <!--配置视图解析器[默认视图解析器]-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置属性suffix 和 prefix-->
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
        <!--调整优先级-->
        <property name="order" value="10"/>
    </bean>

web.xml

<!--配置前端控制器/中央控制器/分发控制器
        用户的请求都会经过它的处理
-->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--配置属性 contextConfigLocation, 指定DispatcherServlet 去操作的spring配置文件-->
        <!--<init-param>-->
        <!--    <param-name>contextConfigLocation</param-name>-->
        <!--    <param-value>classpath:applicationContext-mvc.xml</param-value>-->
        <!--</init-param>-->
        <!--在web项目启动时,就自动的加载DispatcherServlet-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <!--
        配置的url-pattern是 / ,表示用户的请求都经过 DispatcherServlet
        -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

UserServlet

@Controller
public class UserServlet {


    //编写方法,响应用户的请求
    /**
     * 1. login() 方法是用于响应用户的登录请求
     * 2. @RequestMapping(value = "/login") 类似我们以前在原生的Servlet
     *   配置 url-pattern, 就是给方法配置一个url映射
     * 3. 即当用户在浏览器输入 http://localhost:8080/web工程路径/login 就能够访问到login()
     * 4. return "login_ok"; 表示返回结果给视图解析器(InternalResourceViewResolver)
     *   , 视图解析器会根据配置,来决定跳转到哪个页面
     *
     *     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
     *
     *         <property name="prefix" value="/WEB-INF/pages/"/>
     *         <property name="suffix" value=".jsp"/>
     *     </bean>
     *
     *     根据上面的配置 return "login_ok"; 就是转发到 /WEB-INF/pages/login_ok.jsp
     */
    @RequestMapping(value = "/login")
    public String login() {

        System.out.println("login ok.......");
        return "login_ok";
    }
}

细节

执行流程

@RequestMapping

可以指定控制器/处理器的某个方法的请求的url

修饰方法、类和指定请求方式

当同时修饰类和方法时, 请求的url就是组合:/类请求值/方法请求值
buy()方法请求的url: http://ip:port/工程路径/user/buy

@RequestMapping(value = "/user")
@Controller //UserHandler就是一个处理器/控制器,注入到容器
public class UserHandler {
    @PostMapping(value = "/buy")
    public String buy() {
        System.out.println("购买商品~");
        return "success";
    }
}

RequestMethod 四个常用选项 POST, GET, PUT, DELETE
SpringMVC 控制器默认支持GET和POST两种方式,如果指定,必须按照指定方式请求
@PostMapping(value = "/buy")等价@RequestMapping(value = "/buy",method = RequestMethod.POST)

<form action="user/buy" method="post">
    购买人:<input type="text" name="username"><br>
    够买量:<input type="text" name="nums"><br>
    <input type="submit" value="购买">
</form>

 指定params和headers支持简单表达式

    @RequestMapping(value = "/find", params = "bookId=100", method = RequestMethod.GET)
    public String search(String bookId) {
        System.out.println("查询书籍 bookId= " + bookId);
        return "success";
    }

params="bookId" 表示请求该目标方法时,必须给一个bookId参数, 值没有限定
search(String bookId): 表示请求目标方法时, 携带的bookId=100, 就会将请求携带的bookId对应的值 100, 赋给 String bookId
params = "bookId=100" 表示必须给一个bookId参数, 而且值必须是100

<hr><h1>演示params的使用</h1>
<a href="user/find?bookId=100">查询书籍</a>

 支持Ant风格资源地址

    //要求: 可以配置  /user/message/aa, /user/message/aa/bb/cc
    @RequestMapping(value = "/message/**")
    public String im() {
        System.out.println("发送消息");
        return "success";
    }
<hr><h1>演示Ant风格的请求资源方式 </h1>
<a href="user/message/aa">发送消息1</a><br>
<a href="user/message/aa/bb/cc">发送消息2</a><br>

配合@PathVariable映射URL绑定的占位符

不需要在url地址上带参数名,更加简洁明了

    //要求: 获取到 username 和 userid
    //前端页面: <a href="user/reg/kristina/300">占位符的演示</a>
    //(value = "/reg/{username}/{userid}"):,表示kristina->{username} 300=>{userid}
    // value{}大括号的名字随便写,PathVariable里的名字必须跟value{}里保持一致
    @RequestMapping(value = "/reg/{username}/{userid}")
    public String register(@PathVariable("username") String name,
                           @PathVariable("userid") String id) {
        System.out.println("接收到参数--" + "username= " + name + "--" + "usreid= " + id);
        return "success";
    }
<hr><h1>占位符的演示</h1>
<a href="user/reg/kristina/300">占位符的演示</a>

细节

映射的URL不能重复

@RequestMapping(value = "/hi")
    public String hi() {}
@RequestMapping(value = "/hi")
    public String hi() {}

请求简写
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping

//@RequestMapping(value = "/buy",method = RequestMethod.POST)
@PostMapping(value = "/buy")
    public String buy() {
        System.out.println("购买商品~");
        return "success";
    }

如果确定表单或者超链接会提交某个字段数据(比如email),要求提交的参数名和目标方法的参数名保持一致

    @GetMapping(value = "/hello3")
    public String hello3(String email) {
        System.out.println("hello3 " + email);
        return "success";
    }

localhost:8080/user/hello3?email=tom@sohu.com
如果请求参数有 email=xx, 就会将传递的值,赋给String emai,否则输出null

 Rest

web.xml

    <!--配置HiddenHttpMethodFilter
        1. 作用是 把 以pos t方式提交的delete和put请求进行转换
        2. 配置url-pattern 是 /* 表示请求都经过 hiddenHttpMethodFilter过滤
    -->
    <filter>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

spring容器文件

    <!--加入两个常规配置-->
    <!--支持SpringMVC的高级功能,比如JSR303校验, 映射动态请求-->
    <mvc:annotation-driven></mvc:annotation-driven>
    <!--将springmvc不能处理的请求,交给tomcat处理,比如css, js-->
    <mvc:default-servlet-handler/>

HiddenHttpMethodFilter源码

将POST请求转换成PUT、DELETE、PATCH
按照_method参数名来读取

public static final String DEFAULT_METHOD_PARAM = "_method";
   ---------------------------------------------------
   private static final List<String> ALLOWED_METHODS =
			Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
					HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
  ---------------------------------------------------
   if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
			String paramValue = request.getParameter(this.methodParam);
			if (StringUtils.hasLength(paramValue)) {
				String method = paramValue.toUpperCase(Locale.ENGLISH);
				if (ALLOWED_METHODS.contains(method)) {
					requestToUse = new HttpMethodRequestWrapper(request, method);
				}
			}
		}

Delete、Put

默认情况下 <a href="user/book/600">删除指定id的书</a> 是get
需要将 get <a href="user/book/600">删除指定id的书</a> 以post方式提交给后端handler, 这样过滤器才会生效

    //删除[DELETE]
    @RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
    public String delBook(@PathVariable("id") String id) {
        System.out.println("删除书籍 id= " + id);
        //return "success"; //[如果这样返回会报错 JSPs only permit GET POST or HEAD]
        //1. redirect:/user/success重定向
        //2. 会被解析成 /springmvc/user/success
        return "redirect:/user/success";
    }

    //如果请求是 /user/success , 就转发到 success.jsp
    //successGenecal对应的url http://ip:port/springmvc/user/success
    @RequestMapping(value = "/success")
    public String successGenecal() {
        return "success";  //由该方法 转发到success.jsp页面
    }


    //修改[PUT]
    @PutMapping(value = "/book/{id}")
    public String updateBook(@PathVariable("id") String id) {
        System.out.println("修改书籍 id=" + id);
        return "redirect:/user/success";
    }
<html>
<head>
    <title>rest </title>
<%--    引入jquery--%>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () {
            //给删除超链接绑定一个点击事件
            $("#deleteBook").click(function (){
                $("#hiddenForm").attr("action", this.href);
                $(":hidden").val("DELETE");
                $("#hiddenForm").submit();
                return false; //改变点击超链接的行为, 不再提交
            })
        })
    </script>
</head>
<body>

<h3>rest风格的url, 删除一本书</h3>
<a href="user/book/600" id="deleteBook">删除指定id的书</a>
<form action="" method="post" id="hiddenForm">
    <input type="hidden" name="_method"/>
</form>

<br><hr>
<h3>rest风格的url 修改书籍[put]~</h3>
<form action="user/book/666" method="post">
    <input type="hidden" name="_method" value="PUT">
    <input type="submit" value="修改书籍~">
</form>

</body>
</html>

细节

SpringMVC映射请求数据 

RequestParam获取参数值

 @RequestParam(value="name", required=false)
 1. 获取到超链接传递的数据 请求 http://localhost:8080/springmvc/vote/vote01?name=xx
 2. @RequestParam 表示会接收提交的参数
 3. value="name" 表示提交的参数名是name
 4. required=false 表示该参数可以没有, 默认是true,表示必须有这个参数
 5. 当我们使用了@RequestParam(value="name", required=false)后就请求的参数名和方法的形参名可以不一致

    @RequestMapping(value = "/vote01")
    public String test01(@RequestParam(value = "name", required = false) String username) {

        System.out.println("得到的username= " + username);
        //返回到一个结果
        return "success";
    }
<h2>获取到超链接参数值</h2>
<a href="vote/vote01?name=hsp">获取超链接的参数</a>

获取http请求消息头

    /**
     * 需求: 获取http请求头信息, 获取到Accept-Encoding 和 Host
     * @RequestHeader("Http请求头字段")
     */
    @RequestMapping(value = "/vote02")
    public String test02(@RequestHeader("Accept-Encoding") String ae,
                         @RequestHeader("Host") String host) {
        System.out.println("Accept-Encoding= " + ae);
        System.out.println("Host= " + host);
        //返回到一个结果
        return "success";
    }
<h1>获取到消息头</h1>
<a href="vote/vote02">获取http消息头信息</a>

获取javabean形式的数据

1. 方法的形参用对应的类型来指定即可, SpringMVC会自动的进行封装
2. 如果自动的完成封装, 要求提交的数据,参数名和对象的字段名保持一致
3. 如果属性是对象,这里就是仍然是通过 字段名.字段名
        比如Master [pet], 即提交的数据 参数名是 pet.id pet.name, 这就是级联操作
4.表单控件的name与javabean属性名对应

@RequestMapping(value = "/vote03")
    public String test03(Master master) {
        System.out.println("master=" + master);
        return "success";
    }
<form action="vote/vote03" method="post">
    主人号:<input type="text" name="id"><br>
    主人名:<input type="text" name="name"><br>
    宠物号:<input type="text" name="pet.id"><br>
    宠物名:<input type="text" name="pet.name"><br>
    <input type="submit" value="添加主人和宠物">
</form>

获取servlet api

引入tomcat/lib下的servlet-api.jar

    @RequestMapping(value = "/vote04")
    public String test04(HttpServletRequest request,
                         HttpServletResponse response,
                         HttpSession hs) {
        //获取到session
        //servlet原生的方式
        HttpSession session = request.getSession();
        System.out.println("session=" + session);
        //注意:通过参数传入的 hs 和 通request.getSession() 得到的对象是
        //同一个
        System.out.println("hs= " + hs);

        String username = request.getParameter("username");
        String pwd = request.getParameter("pwd");
        System.out.println("username= " + username);
        System.out.println("pwd= " + pwd);
        return "success";
    }
<h1>演示 servlet api的使用 </h1>
<form action="vote/vote04" method="post">
    用户名:<input type="text" name="username"><br>
    密 码:<input type="password" name="pwd"><br>
    <input type="submit" value="添加用户">
</form>

模型数据

数据放入request

默认机制

    /**
     * 将提交的数据->springmvc封装到java对象->springmvc 会自动的将其放入到request域
     * 就可以在跳转到的页面取出数据.
     */
    @RequestMapping(value = "/vote05")
    public String test05(Master master) {
        return "vote_ok";
    }
<h1>添加主人信息</h1>
<form action="vote/vote05" method="post">
    主人号:<input type="text" name="id"><br>
    主人名:<input type="text" name="name"><br>
    宠物号:<input type="text" name="pet.id"><br>
    宠物名:<input type="text" name="pet.name"><br>
    <input type="submit" value="添加主人和宠物">
</form>
<h1>获取的的数据显示页面</h1>
<hr>
取出 request域的数据-通过前面讲解的el表达式来获取即可
<br>
address: ${requestScope.address}<br>
主人名字= ${requestScope.master.name}
主人id= ${requestScope.master.id}
宠物名字= ${requestScope.master.pet.name}
<a href="<%=request.getContextPath()%>/homework/login.jsp">返回重新登录</a>

 通过HttpServletRequest

springmvc默认存放对象到request域中,属性名是 类名/类型名 首字母小写
request域 ("master", master100) 
所以在jsp中按照类名首字母小写来取出

    @RequestMapping(value = "/vote05")
    public String test05(Master master100, HttpServletRequest request) {
        //设置某一字段的属性值
        request.setAttribute("address", "beijing");
        //修改name的属性值
        master100.setName("nono");
        return "vote_ok";
    }

通过请求的方法参数Map<String,Object>

    @RequestMapping(value = "/vote06")
    public String test06(Master master, Map<String, Object> map) {
        System.out.println("------test06-----");
        //原理分析:springmvc会遍历map,然后将map的k-v, 存放到request域
        map.put("address", "beijing...");
        //map.put("master", null);
        return "vote_ok";
    }

通过返回ModelAndView对象

    @RequestMapping(value = "/vote07")
    public ModelAndView test07(Master master) {

        System.out.println("----test07----");
        ModelAndView modelAndView = new ModelAndView();
        //放入属性到modelAndView对象
        modelAndView.addObject("address", "shanghai");
        //modelAndView.addObject("master", null);
        //可以把从数据库得到的数据->对象-》放入modelAndView[Service-dao-db]
        //这里指定跳转的视图名称
        modelAndView.setViewName("vote_ok");
        //返回结果
        return modelAndView;
    }

细节

数据放入session

    @RequestMapping(value = "/vote08")
    public String test08(Master master, HttpSession httpSession) {
        System.out.println("----test08----");
        //master对象是默认放在request域
        //我们将master对象放入到session域
        httpSession.setAttribute("master", master);
        httpSession.setAttribute("address", "guangzhou");
        return "vote_ok";//请求转发
    }
<h1>添加主人信息[测试session]</h1>
<form action="vote/vote08" method="post">
    主人号:<input type="text" name="id"><br>
    主人名:<input type="text" name="name"><br>
    宠物号:<input type="text" name="pet.id"><br>
    宠物名:<input type="text" name="pet.name"><br>
    <input type="submit" value="添加主人和宠物">
</form>
取出 session域的数据 <br>
address: ${sessionScope.address}<br>
主人名字= ${sessionScope.master.name}
主人信息= ${sessionScope.master}

@ModelAttribute实现prepare方法

    /**
     * 1. 当Handler的方法被标识 @ModelAttribute,就视为一个前置方法
     * 2. 当调用该Handler的其它的方法时,都会先执行该前置方法
     * 3. 类似我们前面讲解Spring时,AOP的前置通知[底层是AOP机制]
     * 4. prepareModel前置方法,会切入到其它方法前执行..
     */
    @ModelAttribute
    public void prepareModel(){
        System.out.println("prepareModel()-----完成准备工作-----");
    }

视图和视图解析器

自定义视图

多个视图解析器,会根据优先级放在arraylist中进行遍历
默认视图解析器一旦执行,就不会执行自定义视图解析器
 

    @RequestMapping(value = "/buy")
    public String buy() {
        System.out.println("------buy()-----");
        return "hspView";
    }
/**
 * 1. MyView继承了AbstractView, 就可以作为一个视图使用
 * 2. @Component(value = "myView"),该视图会注入到容器中, 名字/id是 hspView
 */
@Component(value = "hspView")
public class MyView extends AbstractView {
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model,
                                           HttpServletRequest request,
                                           HttpServletResponse response) throws Exception {

        //完成视图渲染
        //并且可以确定我们要跳转的页面 [请求转发] /WEB-INF/pages/my_view.jsp
        System.out.println("进入到自己的视图..");

        //1. 下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp
        //2. /WEB-INF/pages/my_view.jsp 会被springmvc解析
        //   /springmvc/WEB-INF/pages/my_view.jsp
        request.getRequestDispatcher("/WEB-INF/pages/my_view.jsp")
                .forward(request, response);

    }
}
    <!--
        1. 配置自定义视图解析器BeanNameViewResolver
        2. BeanNameViewResolver可以去解析我们自定义的视图
        3. 配置 属性 order, 表示视图解析器执行的顺序, 值越小, 优先级越高
        4. 属性 order 的默认值是最低优先级 ,值为 Integer.MAX_VALUE
           int LOWEST_PRECEDENCE = 2147483647
    -->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="99"/>
    </bean>
<a href="goods/buy">点击到自定义视图-</a><br/>

目标方法直接指定转发或重定向

访问WEB-INF下面的资源必须请求转发,不能直接浏览器访问

    //直接指定要请求转发的或者是重定向的页面
    @RequestMapping(value = "/order")
    public String order() {
        System.out.println("=======order()=====");
        //请求转发到 /WEB-INF/pages/my_view.jsp
        //下面的 /WEB-INF/pages/my_view.jsp 被解析成 /springmvc/WEB-INF/pages/my_view.jsp
        //return "forward:/WEB-INF/pages/my_view.jsp";
        //return "forward:/aaa/bbb/ok.jsp";

        //直接指定要重定向的页面
        //1. 对于重定向来说,不能重定向到 /WEB-INF/ 目录下
        //2. redirect 关键字,表示进行重定向
        //3. /login.jsp 在服务器解析 /springmvc/login.jsp
        return "redirect:/login.jsp";

        // /WEB-INF/pages/my_view.jsp 被解析 /springmvc/WEB-INF/pages/my_view.jsp
        //return "redirect:/WEB-INF/pages/my_view.jsp";
    }

forward对应InternalResourceView视图
redirect对应RedirectView视图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值