SpringMVC-3-CRUD

Select:

/**
 * @author : zhukang
 * @date : 2021-06-26
 * @return :
 * @description : 查询电子文档列表
 */
@RequestMapping(value = "/entries", method = RequestMethod.GET)
public String selectAllEntry(Map<String, Object> map){
    // 获取文档列表,存入map中
    map.put("edocEntries", edocEntryMapper.selectAllEntry());
    // 返回目标视图
    return "edocList";
}

mvc模式的servlet风格,使用注解的方法代替了一切。

注解中的value值表示了拦截的请求, / 可加可不加,最好加(因为专业)

返回的字符串是需要跳转的jsp页面的名字

形参中既可以接收数值,也可以是要扔出去的数值(model、map)

正删改一体的RSET风格拦截:

  • 前往修改页面、增加页面都使用GET请求;

  • 增删改都使用统一的拦截url,也可以携带参数,互不影响。但是需要改变请求的类型来区别:

    ​ 1.增加 == POST

    ​ 2.修改 == PUT

    ​ 3.删除 == DELETE

接收页面的参数时,需要@PathVariable注解,实体参数可以不需要;

返回目标页面时,多级目录问题需要注意,尽量使用**return "redirect:/entries";**的形式

去往添加电子文档:

   /**
     * @author : Lcywings
     * @date : 2021/6/26 10:10
     * @acl : true
     * @description : 去往添加电子文档
     */
    @RequestMapping(value = "/toAddEntry", method = RequestMethod.GET)
    public String toAddEntry(Map<String, Object> map) {
        // 获取分类列表,存入map中
        map.put("edocCategories", edocCategoryMapper.selectAllCategory());

        // 默认情况下,form表单标签,必须添加一个command作为key的模型数据
        // 添加,没有初始数据,直接提供一个空的电子文档实体即可,页面取的值都是空的
        // map.put("command", new EdocEntry());
        // 可以自定义修改表单默认的command参数
        map.put("edocEntry", new EdocEntry());

        // 返回目标视图
        return "edocInfo";
    }

添加电子文档:

  /**
     * @author : Lcywings
     * @date : 2021/6/26 10:10
     * @acl : true
     * @description : 添加电子文档
     */
    @RequestMapping(value = "/updateEntry", method = RequestMethod.POST)
    public String addEntry(EdocEntry edocEntry) {
        //填充分类数据和时间
        edocEntry.setEdocCategory(edocCategoryMapper.selectCategoryById(edocEntry.getEdocCategory().getId()));
        edocEntry.setCreateDate(new Date());

        //根据id调用修改接口
        edocEntryMapper.insertEntryById(edocEntry);
        
        // 返回目标视图
        return "redirect:/entries";
    }

去往修改电子文档页:

 /**
     * @author : Lcywings
     * @date : 2021/6/26 10:10
     * @acl : true
     * @description : 去往修改电子文档页
     */
    @RequestMapping(value = "/toModEntry/{id}", method = RequestMethod.GET)
    public String toModEntry(@PathVariable("id") Integer id, Map<String, Object> map) {
        // 获取分类列表,存入map中
        map.put("edocCategories", edocCategoryMapper.selectAllCategory());

        // 查询一个文档实体详情,存入模型数据
        // map.put("command", edocEntryMapper.selectEntryById(id));
        map.put("edocEntry", edocEntryMapper.selectEntryById(id));

        // 返回目标视图
        return "edocInfo";
    }

修改电子文档:

    /**
     * @author : Lcywings
     * @date : 2021/6/26 10:10
     * @acl : true
     * @description : 修改电子文档
     */
    @RequestMapping(value = "/updateEntry", method = RequestMethod.PUT)
    public String modEntry(EdocEntry edocEntry) {
        //填充分类数据和时间
        edocEntry.setEdocCategory(edocCategoryMapper.selectCategoryById(edocEntry.getEdocCategory().getId()));
        edocEntry.setCreateDate(new Date());

        //根据id调用修改接口
        edocEntryMapper.updateEntryById(edocEntry.getId(), edocEntry);
        // 返回目标视图
        return "redirect:/entries";
    }

删除电子文档:

/**
     * @author : Lcywings
     * @date : 2021/6/26 10:10
     * @acl : true
     * @description : 删除电子文档
     */
    @RequestMapping(value = "/updateEntry/{id}", method = RequestMethod.DELETE)
    public String deleteEntry(@PathVariable("id") Integer id, Map<String, Object> map) {
        // 获取文档id,删除电子文档
        edocEntryMapper.deleteEntryById(id);
        // 返回目标视图,rest请求存在多级,保证从项目根目录开始请求,不能少 /
        return "redirect:/entries";
    }

拦截这里大大减少的代码量,但是需要一些配置:

  1. 组件扫描
  2. 视图解析器
  3. 前端核心控制器(DispatcherServlet拦截器)
  4. Rest风格请求转换过滤器

前两项是在spring-config.xml中配置,后两项是在web.xml中配置

还有一个需要注意的配置点:

  1. 静态资源释放

    这玩意不配,js之流的静态资源就会被前端核心控制器拦截并解析,但是配了组件扫描会失效,所以和mvc:annotation-driven一起使用

  2. 注解扫描

<!--  组件扫描  -->
<context:component-scan base-package="com.kgc.springmvc"/>

<!--  视图解析器-jsp视图解析
    工作原理:当前请求处理方法,返回目标视图名称时,根据视图解析器解析为目标物理视图
        prefix + 返回的视图(jsp页面)名称 + suffix -》真实物理视图
    猜测:/WEB-INF目录是安全目录,不可以直接通过浏览器访问,springmvc底层使用的是内部转发
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 前缀必须是/结尾,否则容易出错 -->
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>
<!--  配置SpringMvc的前端核心控制器  -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置前端核心控制器的初始化参数contextConfigLocation,指定springmvc框架使用的核心配置文件 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!-- web容器启动就创建实例 -->
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!-- 如果配置/*或者*.do,对rest风格支持不友好,暂时记住就是 / (好处就是可以自动放行jsp请求) -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!--  Rest风格请求转换过滤器  -->
<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>
<!--  springmvc默认是不会释放静态资源(js,css,image,html...),即被前端核心控制器拦截(找映射处理方法)
   针对静态资源要进行释放,增加一个配置<mvc:default-servlet-handler/>即可
   注意:静态资源释放会导致@RequestMapping注解失效,必须配置注解扫描使用
-->
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>

前端接收:

因为后端使用框架传参的本事还是塞在request中,所以前端使用el表达式既可以顺利的取到值,但是spring还是给我们准备了很好用的spring表单来发送数据,强就强在发送的同时兼顾接收数据,直接帮你写好name等参数,方便进出数据

<!-- springmvc的form表单标签:方便实现表单开发,数据快速回显 -->
<!--  form表单标签必须写在 form:form中才可以 -->
<form:form action="/edocInfo" method="post" modelAttribute="edocEntry">
    <!-- 判断是添加还是修改 -->
    <c:if test="${!empty edocEntry.id}" var="flag">
        <form:hidden path="id"/>
        <input type="hidden" name="_method" value="put"/>
    </c:if>
    <table border="1px" width="50%" align="center" cellspacing="0">
        <tr>
            <td>文档分类:</td>
            <td>
                <!-- items指定遍历的集合,itemLabel对应展示的文字,itemValue对应提交的值,相当于以前的<option value="itemValue">itemLabel</option> -->
                <form:select path="edocCategory.id" items="${edocCategories}" itemLabel="name" itemValue="id"/>
            </td>
        </tr>
        <tr>
            <td>书名:</td>
            <td>
                <form:input path="title"/>
            </td>
        </tr>
        <tr>
            <td>作者:</td>
            <td><form:input path="uploadUser"/></td>
        </tr>
        <tr>
            <td>摘要:</td>
            <td><form:input path="summary"/></td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <c:if test="${flag}">
                    <input type="submit" value="修改"/>
                </c:if>
                <c:if test="${!flag}">
                    <input type="submit" value="添加"/>
                </c:if>
                <input type="button" value="返回"/>
            </td>
        </tr>
    </table>
</form:form>

实际上就是帮你写好了id和name,方便进出数据:
<form:input path="title"/> ==>>

不需要遍历的select标签,拿到直接填满,类似于增强for:

<form:select path="edocCategory.id" items="${edocCategories}" itemLabel="name" itemValue="id"/>

↑转换为↓

<select id="edocCategory.id" name="edocCategory.id">
	<option value="1">文学</option><option value="2">武侠</option>
	<option value="3" selected="selected">仙侠</option>
	<option value="4">玄幻</option><option value="5">都市</option>
	<option value="6">言情</option>
</select>

js的标准用法:

返回的写法:

关键点:$ 这是项目的绝对路径

<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.4.1.min.js"></script>
<script>
    $(function () {
        $("input[type=button]").click(function () {
            history.back();
        })
    })
</script>

a标签如何发post请求:

就很离谱,本质的上是去修改表单中内容并在js中提交

<form action="#" method="post">
    <input type="hidden" name="_method" value="delete"/>
</form>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.4.1.min.js"></script>
<script>
    $(function () {
        // 调试jQuery是否正常
        // alert(123);
        // 绑定删除操作
        $(".del").click(function () {
            // 提示
            if (!confirm("确定要删除吗?")) {
                // 去除超链接的默认跳转事件
                return false;
            }
            // 提交form表单
            $("form").attr("action", $(this).attr("href")).submit();
            // 取消表单的默认提交事件
            return false;
        })
    })
</script>

Q.E.D.