Precautions blog project

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/weixin_43174445/article/details/102756510

log in

如果出现:Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove ‘readOnly’ marker from transaction definition错误时。

Need to open the transaction in the business layer, if needed once the database, delete, change time

1. Configure the transaction manager in hibernate configuration file, the transaction enhancement (Open comments)

<!--配置事务管理器-->
<bean id="transactionManager"
      class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!--开启注解  增强-->
<tx:annotation-driven transaction-manager="transactionManager"/>

2. Add annotations directly on business class

@Transactional
public class CategoryServiceImpl implements CategoryService {
    @Setter
    private CategoryDao categoryDao;
    @Override
    public void addCategory(Category category) {
        categoryDao.addCategory(category);
    }

}

classification

json jar package into the correct

Using the data-id = "" id may be carried over when a transmission request id bind button

<a href="#" class="updatebtn" data-id="<s:property value="#category.cid"/>">
    <img class="img_icon" src="${pageContext.request.contextPath}/images/edit_icon.png" alt="">
</a>

Use Ajax (front-end technology) sends a request to the web layer

 $.post("${pageContext.request.contextPath}/category/category_updateUI.action",{"cid":cid},function (data) {
          },"json");

The extracted layer web page display data directly

//将取出的数据转化为json类型
JSONArray jsonArray = JSONArray.fromObject(oneCategory, jsonConfig);
System.out.println(jsonArray.toString());

//将数数据打印到页面
ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
ServletActionContext.getResponse().getWriter().println(jsonArray.toString());

The data can be directly transmitted through the data in json, so get time to take data directly on the line

          $.post("${pageContext.request.contextPath}/category/category_updateUI.action",{"cid":cid},function (data) {
             console.log("-------json------");
              console.log(data);
             /!*把json数据展示到文本框 *!/
              $("#parentid2").val(data[0].cparentid);
              $("#cname2").val(data[0].cname);
          },"json");

Note: marked using an iterator can not be used when the button id, because the only representation when id, to use class

<s:iterator value="categoryList" var="category">
    <ul class="list_goods_ul">
        <li><s:property value="#category.cparentid"/> </li>
        <li><s:property value="#category.cname"/></li>
        <li>
            <a href="#" class="updatebtn" data-id="<s:property value="#category.cid"/>">
                <img class="img_icon" src="${pageContext.request.contextPath}/images/edit_icon.png" alt="">
            </a>
        </li>
        <li><a href="#"><img class="img_icon" src="${pageContext.request.contextPath}/images/delete_icon.png" alt=""></a></li>
    </ul>
</s:iterator>

Style address using absolute path: $ {pageContext.request.contextPath}

article

Note establish relational mapping point: foreign key must pay attention also to create a corresponding foreign key objects in the domain inside

To describe a many-to-many or configured in the configuration file, get, set method

private Integer article_id;
private String article_title;
private String article_content;
private Integer article_time;
private String article_pic;
private String article_desc;
//外键
private Category category;
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.blog.domain.Article" table="article" >
        <!--建立类属性哪一个是主键  还要跟数据库当中主键进行对象-->
        <id name="article_id" column="article_id" >
            <generator class="native"/>
         </id>
        <!--建立类中的普通属性与数据库当中字段进行关联-->
        <property name="article_title" column="article_title" />
        <property name="article_content" column="article_content"/>
        <property name="article_time" column="article_time"/>
        <property name="article_pic" column="article_pic"/>
        <property name="article_desc" column="article_desc"/>
        <many-to-one name="category" class="com.blog.domain.Category" column="article_cid"></many-to-one>
    </class>
</hibernate-mapping>

important point:

If an error occurs:

org.hibernate.LazyInitializationException: could not initialize proxy [com.blog.domain.Category#2] - no Session

Because the transaction is in the business layer when opening and closing, and covered with tostring category property, because of using lazy loading so that no session will be reported errors found

solve:

<!--配置延迟加载-->
<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>

Web.xml file to configure a delay loading filter, so that the transaction is also open in the web tier, pay attention: the need to delay loading of configuration in front struts

Paging

Data needed: the current page number (currentPage) page shows a number of pieces of data (pageSize)

The current page query subscript (index) of the total number (totalCount) record points total number of pages (totalPage)

Current data (pageList) page

Location database query = (currentPage-1) * pageSize

Total Pages = totalCount * 1.0 / totalPage rounded up (ceil)

Sample code:

package com.blog.domain;

import java.util.List;

public class PageBean<T> {
    /*当前页*/
    private Integer currentPage;
    /*一页有多少条数据*/
    private Integer pageSize;
    /*当前查询的角标*/
    private Integer index;
    /*总的记录数*/
    private Integer totalCount;
    /*总页数*/
    private Integer totalPage;
    /*当前页的数据*/
    private List<T> pageList;

    /*如果当前页没有设置,默认设置为第1页*/
    public void setCurrentPage(Integer currentPage) {
        if (currentPage == null) {
            currentPage = 1;
        }
        this.currentPage = currentPage;
    }
    /*如果没有设置当前页总记录数据,设置默认记录数为一页5条*/
    public void setPageSize(Integer pageSize) {
        if (pageSize == null) {
            pageSize = 5;
        }
        this.pageSize = pageSize;
    }
    /*计算当前页从数据库当中查询的位置*/
    public Integer getIndex() {
        return (currentPage-1)*pageSize;
    }
    /*计算总页数*/
    public Integer getTotalPage() {
        double ceil = Math.ceil(totalCount * 1.0 / pageSize);
        return (int)ceil;
    }
}

Article pagination Note:

1. Create PageBean

2. Create an action method by sending action jsp address

3.web layer accepts parameters, create off-line query, call the business layer, data processing, data is written to the value of the stack, request forwarding

public class ArticleAction extends ActionSupport implements ModelDriven<Article> {
    @Override
    public Article getModel() {
        return article;
    }
    @Setter
    private Article article;
    @Setter
    private ArticleService articleService;
    public String list(){
        List<Article> list = articleService.list();
        ActionContext.getContext().getValueStack().set("list",list);
        return "list";
    }

    public String add(){
        System.out.println(article.getArticle_title());
        return null;
    }
    @Setter
    private Integer currentPage;
    @Setter
    private String keyWord;
    public String pageList(){
        //离线条件查询
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Article.class);
        //添加查询条件这也是为什么要把离线条件查询直接写在web的原因
        if (keyWord!=null){
            detachedCriteria.add(Restrictions.like("article_title","%"+ keyWord+ "%"));
        }
        PageBean<Article> pageBean=articleService.getPageList(detachedCriteria,currentPage,5);
        ActionContext.getContext().getValueStack().push(pageBean);
        return "list";

    }

}

4. pagebean business layer to set properties, query data call dao layer, web layer returns to a pageBean

    public PageBean<Article> getPageList(DetachedCriteria detachedCriteria, Integer currentPage, int pageSize) {
        //设置数据,查询数据库
        //1.设置当前页
        pageBean.setCurrentPage(currentPage);
        //2.设置一页显示的个数
        pageBean.setPageSize(pageSize);
/*        //3.设置数据库查询的位子
        pageBean.setIndex(pageBean.getIndex());*/
        //4.设置总的记录数 需要从数据库中查找
        Integer totalCount=articleDao.getTotalCount(detachedCriteria);
        pageBean.setTotalCount(totalCount);
        //5.设置总页数
        pageBean.setTotalPage(pageBean.getTotalPage());
        //6.设置每页的数据 需要从数据库中查找
        List<Article> pageList=articleDao.getTotalList(detachedCriteria,pageBean.getIndex(),pageBean.getPageSize());
        pageBean.setPageList(pageList);
        return pageBean;
    }

5.dao layer based on the needs check out the data to the business layer

@Override
public Integer getTotalCount(DetachedCriteria detachedCriteria) {
    //使用setProjection(Projections.rowCount());查询出总的记录数,别的数据不需要
    //要注意的是查询出来的结果是一个Long类型的集合
    detachedCriteria.setProjection(Projections.rowCount());
    List<Long> list = ( List<Long>)this.getHibernateTemplate().findByCriteria(detachedCriteria);
    if(list.size()>0){
        return list.get(0).intValue();
    }
    return 0;
}

@Override
public List<Article> getTotalList(DetachedCriteria detachedCriteria, Integer index, Integer pageSize) {
    //由于之前使用过 detachedCriteria.setProjection(Projections.rowCount());所以要把他里面的条件清空
    //否者查询的还是之前的条件
    detachedCriteria.setProjection(null);
    List<Article> list = (List<Article>)this.getHibernateTemplate().findByCriteria(detachedCriteria, index, pageSize);
    return list;
}

Keyword search:

Echo ----- 1. The parameters of the non-root zone parameters saved to the value of the stack so the request will be made due to the time parameter should be with the # sign

<input type="text" class="am-form-field" id="input_search" value="<s:property value="#parameters.keyWord"/>" />

2. Next ------ bound parameters in order to allow the implementation of data can be paged to find the next, you should also echo parameters passed to the web layer

No person can not view the next page will lead to query data

//分页
$("#page").paging({
    pageNo:<s:property value="currentPage"/>,
    totalPage: <s:property value="totalPage"/>,
    totalSize: <s:property value="totalCount"/>,
    callback: function(num) {
        var keyWord = $("#input_search").val();
         $(window).attr('location','${ctx}/article/article_pageList.action?currentPage='+num+"&keyWord="+keyWord);
    }
});

Developer mode

<constant name="struts.devMode" value="true"></constant>
<package name="Article" extends="struts-default" namespace="/article">
    <action name="article_*" class="articleAction" method="{1}">
        <result name="list" >/mgr_main.jsp</result>
        <allowed-methods>list,add,pageList</allowed-methods>
    </action>
</package>

In front of the need to open the Struts developer mode plus

The need to see the debug jsp plus

<s:debug></s:debug>

You can click to see debug data value stack inside

upload picture

step:

1. monitor release button

$("#send").click(function () {
    $("#blog_form").submit();
})

2. Set form form form form behind add enctype = "multipart / form-data" (file upload) properties

<form id="blog_form" action="${pageContext.request.contextPath}/article/article_add.action" method="post" enctype="multipart/form-data">
    
</form>

3. Upload the action inside the processing file

3.1 file upload settings required attributes came injection

@Setter
private String uploadFileName; // 文件名称
@Setter
private File upload; // 上传文件 upload 临时文件
@Setter
private String uploadContentType; // 文件类型

3.2 file processing method which uploads

    public String add() throws IOException {
        //上传图片
/*        System.out.println(uploadFileName);
        System.out.println(upload);
        System.out.println(uploadContentType);*/
        //1.判断文件临时文件是否存在
        if (upload!=null){
            /* 临时文件存在就开始处理*/
            //2.设置文件的上传路径
            String path = ServletActionContext.getServletContext().getRealPath("/upload");
            /*对文件名称进行处理*/
         /*   截取文件后缀名*/
            //3.获取截取角标
            int index = uploadFileName.lastIndexOf(".");
            //4开始截取
            String suffixName = uploadFileName.substring(index);
            //5.生成随机的名字并去除里面的‘-’
            String uuidFileName = UUID.randomUUID().toString().replace("-", "")+suffixName;
            //6.判断上传路径是否存在,不存在就创建一个
            File file = new File(path);
            if(!file.exists()){
                file.mkdirs();
            }
            //7.上传文件
            File dictFile = new File(path + "/" + uuidFileName);
            FileUtils.copyFile(upload,dictFile);

        }
        return null;
    }

File upload process steps:

1. First, determine whether a file exists if (upload! = Null) {} exists on process

Upload path ServletActionContext.getServletContext 2. settings file () getRealPath ( "/ upload").;

3. randomly generated file name

3.1 to get the interception subscript file

​ int index = uploadFileName.lastIndexOf(".");

3.2 suffix intercepted file

​ String suffixName = uploadFileName.substring(index);

3.3 randomly generated file name and a suffix and also the inside of the splice '-' removed

​ String uuidFileName = UUID.randomUUID().toString().replace("-", “”)+suffixName;

4. Upload the judge if there is no path exists to create a

        File file = new File(path);
        if(!file.exists()){
            file.mkdirs();
        }

5. Upload file

        File dictFile = new File(path + "/" + uuidFileName);
        FileUtils.copyFile(upload,dictFile);

Note : The imported file package should import java.io.File;

Category drop-down box

Parent block (a front)

1. Add the article to a screen on the display properties of the parent class, use asynchronous loading json way

1 first transmits action, carrying cparentid = 0 parameter acquired from the database classification data

1.1 finder according to cparentid.

1.2 can find out the format of the data into json coded character set and in response to a reverse display function () in.

public String getCategory() throws IOException {
    List<Category> list=articleService.getCategory(cparentid);
    //把list转化为json格式回显
    JSONArray jsonArray = JSONArray.fromObject(list,new JsonConfig());
    //设置响应字符编码
    ServletActionContext.getResponse().setContentType("text/html;charset=utf-8");
    ServletActionContext.getResponse().getWriter().println(jsonArray.toString());
    return null;
}

2. The acquired data to the echo function (data) and writes data to traverse the inside option

$.post("${ctx}/article/article_getCategory.action",{"cparentid":0},function (data) {
    console.log(data);
    //遍历
    $(data).each(function (i, obj) {
        $("#category_select").append("<option value="+obj.cid+">"+obj.cname+"</option>");
    })
    //一进来出发事件
    $("#category_select").trigger("change");
},"json");

Subframe (hereinafter a)

1. Register a change event

2 removed from the parent class option value, var cid = $ ( "# category_select") val ().;

3. Find out from the database corresponding to the parent category subclasses of the parent class value in accordance with

4. The category is displayed in the sub-frame

note:

1. The sub-category needs to show the money box inside data to empty $ ( "# skill_select") empty () in the sub-frame;. No person will cause all subclasses overlay

2. Add the article when entering the interface they need to be the parent starting a change event not those who come in will not be loaded subclass

//一进来出发事件
$("#category_select").trigger("change");
//监听分类改变
$("#category_select").on("change",function () {
    var cid = $("#category_select").val();
    $.post("${ctx}/article/article_getCategory.action",{"cparentid":cid},function (data) {
        $("#skill_select").empty();
        $(data).each(function (i, obj) {
            $("#skill_select").append("<option value="+obj.cid+">"+obj.cname+"</option>");
        })
    },"json")
})

Guess you like

Origin blog.csdn.net/weixin_43174445/article/details/102756510