第二个项目总结

1.写业务的思想:先分析页面实现的是增删改查哪个功能,参数是从前台向后台传还是从后台向前台传

2.先写控制层里面的方法,然后思考业务层写哪些方法,数据层写哪些方法,用了mybatis之后,如果数据层需要接收多种数据类型需要采用Map集合的方式传递,先在业务层将需要传递的参数封装到map集合中,再将这个map集合传递到数据层。

3.mybatis中常见的接收参数类型:单个参数(基本数据类型,如:Integer,String,Long等),对象(VO类的对象),Map集合等。

4.前台向后台参数传递(前台代码):

  ● 直接通过form表单传递:点击提交(submit)时,会全部提交表单中所有的参数,表单中所有的name属性的值就是所要传递的参数名称,传递的格式为

*.action?属性名称=值&属性名称=值&...,如果表单是get模式的话可以在网址栏中直接看到传递的参数,如果是post模式就看不到了。

<form class="searchform" action="pages/back/admin/resumes/resume_list.action" method="get">
        <select name="status" class="form-control">
          <option value="">状态</option>
            <option value="1" <c:if test="${status==1}">selected</c:if>>入档</option>
          <option value="2" <c:if test="${status==2}">selected</c:if>>通知面试</option>
		<option value="3" <c:if test="${status==3}">selected</c:if>>违约</option>
		<option value="4" <c:if test="${status==4}">selected</c:if>>录用</option>
		<option value="5" <c:if test="${status==5}">selected</c:if>>不录用</option>
        </select>
        <input type="text" class="form-control" name="keywords" placeholder="请输入姓名" value="${keywords}"/>
        <button type="submit" class="btn btn-primary">搜索</button>
      </form>

  注意:表单中的隐藏域:经常用在编辑业务中,有时候我们需要修改每条记录,点击编辑之后需要向后台传递这条记录的id,但是这个id又不需要让用户看到,这个时候就可以使用隐藏域将其隐藏起来但是参数依然会传递。如下代码:

<input type="hidden" name="resid" value="${resume.resid}">

  ● 如果不使用表单提交,我们也可以使用*.action?参数=value&参数=value&参数=value&...的方式传递,这种方式适合参数比较少的情况,如下代码:

   查看预览的时候需要将预览的这条数据的id传过去,所以就可以手动在后面加参数

<td><a href="pages/back/admin/resumes/resume_editPre.action?resid=${resume.resid}" target="_blank">查看预览</a></td>

  ● 使用ajax传递参数:现在我还没搞懂,待更新

5.前台向后台参数传递(后台代码):

  ●  可以直接在控制层的方法参数 的括号中直接接收(必须保证action括号中的参数名称与前台jsp参数name的值保持一致),此种传递适合传递参数比较少的情况,如下代码

 @RequestMapping("resume_editPre.action")
    public ModelAndView editPre(String resid){  //这里的resid是从前台jsp页面中的name="resid"那里传过来的,name="resid"对应的value值就是这里resid的值
        ModelAndView mav=new ModelAndView("back/admin/resumes/form");
        Resume resume=this.resumeServiceClient.getIResumeService().findResumeByResid(Long.parseLong(resid));
        List<WorkYears> allWorkYears=this.resumeServiceClient.getIResumeService().findWorkYears();
        mav.addObject(resume);
        return mav;

  ● 也可以直接在控制层的方法中直接获取一个VO类对象,一定要保证前端表单中的name属性的值与vo类对应的数据表字段相同,如下代码:

 @RequestMapping("resume_edit.action")
    public String edit(Resume resume){
        this.resumeServiceClient.getIResumeService().doEdit(resume);
        return "forward:resume_list.action";
    }

6.后台向前台参数传递:

  ● 如果传递单个参数(例如:字符串等):

    ● 后台:mav.addObject("keywords","你好");

    ● 前台:${keywords}

  ● 如果传递一个对象:

    ●  后台:Resume resume=this.resumeServiceClient.getIResumeService().findResumeByResid(Long.parseLong(resid));

        mav.addObject(resume);

    ●  前台:${resume.字段1},${resume.字段2},${resume.字段3},${resume.字段4},...

  ● 如果传递一个List集合:

    ●  后台:mav.addObject("allEducation",this.resumeServiceClient.getIResumeService().findAll());  说明:findAll()的返回值类型是一个List集合

    ●  前台:<c:forEach items="${allEducation}" var="education">${education.字段1},${education.字段2},${education.字段3},...</c:forEach>

  ● 如果传递一个Map集合:注意前面几个都是用的ModelAndView类中的addObject()方法,而传递map集合的时候用的是addAllObjects()方法

    ●  后台:Map<String,Object> map=this.resumeServiceClient.getIResumeService().findSplit(status,keywords,spu.getCurrentPage(),5,"state","name");

        mav.addAllObjects(map);说明:在业务层的方法返回的map集合里面有两个key,分别为allResumes,allRecorders

    ●  前台:<c:forEach items="${allResumes}" var="resume">${resume.字段1},${resume.字段2},${resume.字段3},...</c:forEach>

7.前台中文传到数据库乱码问题:在数据库连接的资源文件(database.properties)中,数据库连接地址后面加上?useUnicode=true&characterEncoding=UTF8

  db.druid.url=jdbc:mysql://inheart.club:3306/museum?useUnicode=true&characterEncoding=UTF8

8.分页组件的使用:

  ● 分页工具类:

package com.yootk.util.split;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;

public class SplitPageUtil {
    private Long currentPage ;//当前页
    private Integer lineSize ;//每页存放的数据记录数
    private String keyword ;//查询关键字
    private String column ;//查询列
    private String columnData ;//
    private String url ;//在哪个控制层使用的此类,写上控制层的完整路径
    public SplitPageUtil(String url) {
        this(url,null) ;
    }
    public SplitPageUtil(String url,String columnData) {
        this.url = url ;
        this.columnData = columnData ;
        this.splitHandle();
    }
    private void splitHandle() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        try {
            this.currentPage = Long.parseLong(request.getParameter("cp")) ;
        } catch (Exception e) {}
        try {
            this.lineSize = Integer.parseInt(request.getParameter("ls")) ;
        } catch (Exception e) {}
        this.column = request.getParameter("col") ;
        this.keyword = request.getParameter("kw") ;
        request.setAttribute("currentPage",this.currentPage);
        request.setAttribute("lineSize",this.lineSize);
        request.setAttribute("column",this.column);
        request.setAttribute("keyword",this.keyword);
        request.setAttribute("url",this.url);
        request.setAttribute("columnData",this.columnData);
    }

    public Long getCurrentPage() {
        if (this.currentPage == null) {
            return 1L ;
        }
        return currentPage;
    }

    public String getColumn() {
        return column;
    }

    public String getKeyword() {
        return keyword;
    }

    public Integer getLineSize() {
        if (this.lineSize == null) {
            return 5 ;
        }
        return lineSize;
    }
}

  ● 控制层要写的内容:下面这个是输入两个关键字查询两个字段

SplitPageUtil spu=new SplitPageUtil("/pages/back/admin/resumes/resume_list.action");//先实例化分页工具类实例
 Map<String,Object> map=this.resumeServiceClient.getIResumeService().findSplit(status,keywords,spu.getCurrentPage(),5,"state","name");

  说明:status,keywords分别为第一个关键字,和第二个关键字;"state","name"分别为两个查询列的名称

  ● 业务层要写的内容:使用分页查询一定要将数据的总记录数传递到前台

/**
* 分页查询全部的简历
* @param name "请输入姓名"框中输入的关键字
* @param state "状态"框中输入的关键字
* @param currentPage 当前页
* @param lineSize 每页显示的记录数
* @param columnone 要查的字段1,这里是状态
* @param columntwo 要查的字段,这里是姓名
* @return 返回Map集合
*/
 public Map<String, Object> findSplit(String name, String state, Long currentPage, Integer lineSize, String columnone, String columntwo) {
        Map<String,Object> params=new HashMap<>();
        Map<String,Object> results=new HashMap<>();
        params.put("name",name);
        params.put("state",state);
        params.put("start",(currentPage-1)*lineSize);
        params.put("end",lineSize);
        params.put("columnone",columnone);
        params.put("columntwo",columntwo);
        results.put("allResumes",this.resumeMapper.findAll(params));
        results.put("allRecorders",this.resumeMapper.getAllRecorders(params));//这里的key一定要写成allRecorders,因为表单上接收的是allRecorders
        return results;
    }

  ● 数据层要写的内容:

<select id="findAll" parameterType="java.util.Map" resultType="Resume"><!--根据查询条件查询出符合条件的全部数据-->
    select
    <include refid="Base_Column_List" />
    from resume
    <where>
        <if test="name != null and name !=""">
          ${columnone} like #{name}
        </if>
      <if test="state != null and state !=""">
        and ${columntwo} like #{state}    <!--如果前面name==null,mybatis会自动去掉这个and关键字-->
      </if>
    </where>
    limit #{start},#{end}
  </select>
  <select id="getAllRecorders" resultType="java.lang.Long" parameterType="java.util.Map"><!--返回符合条件的全部记录数-->
    select count(*) from resume
    <where>
    <if test="name != null and name !=""">
      ${columnone} like #{name}
    </if>
    <if test="state != null and state !=""">
      and ${columntwo} like #{state}
    </if>
    </where>
  </select>

9.如果怀疑自己在映射文件中写的sql语句对不对:可以观察dubbo微服务中的日志:里面会有执行的SQL语句,自己观察即可,里面的Total只是返回的行数

10.运行的时候先启动dubbo微服务,再启动tomcat,如果修改提供端代码就需要重启对应的微服务(可能也需要重启tomcat,我不确定),如果修改消费端后台代码就需要重启tomcat。

11.采用dubbo的目录结构:

  ● api模块:写vo类和业务层接口

  ● 提供端模块:

    ● 写业务层实现子类,用dubbo中的@Service注解

    ● 写数据层接口

    ● 写数据层接口映射文件(写SQL语句)

  ● 消费端模块:

    ● 代理业务层接口(返回值类型为远程接口)

    ● 写代理业务层接口子类(在这个类中注入远程业务接口(api中的业务接口)实例)用dubbo中的@Reference注入,并且用spring中的@Service注解

    ● 写控制层:用spring中的@Autowired注入代理业务层实例,调用远程接口方法时,先通过代理业务层实例获得远程业务接口实例再调用其方法

     修改web页面(jsp,js等)

12.要想查看自己的业务层接口有没有在zookeeper中注册可以在zookeeper服务器上查看,也可以在dubbo客户端上查看,dubbo客户端的地址:localhost:7001

  dubbo客户端上显示的都是已经启动的东西。

13.action向action跳转:

  ● 如果不传递参数,直接返回字符串,返回要跳转的action的路径,如下代码:

@RequestMapping("resume_edit.action")
    public String edit(Resume resume){
        this.resumeServiceClient.getIResumeService().doEdit(resume);
        return "forward:resume_list.action";
    }

  ● 如果传递参数,需要返回ModelAndView类型,传递参数像后台向jsp传递参数一样。在接收参数的action中接收参数的方式和jsp向后台传递参数一样。

@RequestMapping("hello.action")
    public ModelAndView hello(){
        ModelAndView mav=new ModelAndView("forward:resume_delete.action");
        mav.addObject("hello","你好");
        return mav;
    }

  ● 请求转发与路径重定向:上面代码中都用了forward关键字

    ● 请求转发(forward)即服务器端跳转(不改变网址输入框路径):浏览器向action发送一个请求,这个action再将这个请求转发到另外一个action,浏览器一共只发送一个请求;如果将jsp中传到action的参数再传给另外一个action,理论上下面hello.action中的参数hello可以直接传递到rubbish.action中,我没有测试过,写的时候尽量还是按照上面的做法传递

    @RequestMapping("hello.action")
    public ModelAndView hello(String hello){
        ModelAndView mav=new ModelAndView("forward:rubbish.action");
        return mav;
    }
    @RequestMapping("rubbish.action")
    public void rubbish(String hello){
        System.out.println(hello);
    }

    ● 路径重定向(redirect)即客户端跳转(改变网址输入框路径):浏览器向action发送一个请求,这个action处理完请求之后将这个请求返回到浏览器,浏览器再发送一个请求给redirect指定的action,浏览器一共发送了两个请求;如果一个action向另外一个action使用redirect跳转,将无法传递参数。

14.dubbo提供端又叫业务中心,又叫dubbo端,又叫微服务。

15.dubbo微服务与zookeeper的关系:zookeeper只是一个注册中心,微服务在zookeeper上注册,消费端在zookeeper上调用对应的接口方法时,zookeeper会提供给消费端微服务的主机信息接口及方法,接下来微服务就与消费端建立了关系就不再需要zookeeper了,即使zookeeper宕机了也不会影响消费端调用。zookeeper就像一个媒婆让引导双方认识,双方认识之后就和媒婆没有任何关系了。

16.<c:if>标签也可以用在<input>标签中(常用在表单回填的时候),如下代码:

        <div class="form-group">
                  <label class="col-sm-2 col-sm-2 control-label">性别</label>
                  <div class="col-sm-10">
                    <label class="radio-inline">
                      <input type="radio" name="sex" value="0" <c:if test="${resume.sex==0}">checked</c:if>><!--如果值为1,则选中男-->
                    男 </label>
                    <label class="radio-inline">
                    <input type="radio" name="sex" value="1" <c:if test="${resume.sex==1}">checked</c:if>><!--如果值为2,则选中女-->
                    女 </label>
                  </div>
                </div>

17.如果我现在想在页面上输出全部考勤人员的姓名,但是考勤表(checkork)中只有雇员eid字段,没有员工姓名字段,而雇员表中有雇员eid字段,也有雇员姓名字段。

这时就需要将全部的考勤信息查出来传到前台,并且将全部的员工信息也上传到前台,然后在jsp中写以下代码:

<c:forEach items="${allCheckorks}" var="checkork">  <!--遍历考勤表信息-->
    <c:forEach items="${allEmp}" var="emp">       <!--遍历雇员信息-->
                            ${emp.eid==checkork.eid ? emp.name :""}  <!--如果当前雇员的eid等于当前考勤表的eid,则输出该雇员的姓名-->
    </c:forEach>
</c:forEach>

18.dubbo项目中消费端打包步骤:先打引用的模块,如:api模块,common模块,util模块。再打整个项目,用:clean install 。将消费端底下的target文件夹删除,重新打消费端的包,用:clean install package。消费端的部署:将此war包上传到tomcat服务器的usr/local/tomcat/webapps/文件夹下,然后启动tomcat服务,即可在浏览器中访问。微服务的部署:将微服务打的jar包随意上传到服务器的任何一个文件夹下,并且启动微服务(就是启动那个Main方法),一台服务器上可以部署多个微服务,这些微服务之间不冲突。

19.nginx反向代理,一台nginx服务器可以代理多个tomcat(是一个项目的多个tomcat,并不是部署不同项目的tomcat),部署一个项目的多个tomcat是为了提高并发访问的。

posted @ 2019-07-20 15:54  王兴龙123  阅读(263)  评论(0编辑  收藏  举报